mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
Deleting or detaching a disk, deleting a network card, forcing a VM off, reverting or deleting a snapshot, stopping or deleting a pool, a network, an interface, a filter or a secret, and the other actions that ask first opened the browser's yes/no box (confirm()), and the ISO upload told its mistakes in the browser's alert(). One dialog in the base page now asks for all of them: its title and confirming button carry the button's own words, its body the button's question, the confirming button red for a destructive action. Confirmed, the button is clicked again, so its form sends what it did before. A button inside another dialog (the flavors) hides that one while asking and shows it again after; Cancel gives the focus back, and the confirming button acts once. The ISO upload's mistakes show in its dialog's error box, announced.
117 lines
4.9 KiB
HTML
117 lines
4.9 KiB
HTML
{% load static %}
|
|
{% load django_bootstrap5 %}
|
|
{% load i18n %}
|
|
<!DOCTYPE html>
|
|
{% get_current_language as LANGUAGE_CODE %}<html lang="{{ LANGUAGE_CODE }}">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<meta name="description" content="WebVirtCloud panel for manage virtual machine">
|
|
<meta name="author" content="anatoliy.guskov@gmail.com">
|
|
|
|
<title>{% block title %}{% endblock %}</title>
|
|
|
|
<!-- Bootstrap Core CSS -->
|
|
{# error pages render without app_settings: they get zephyr #}
|
|
{% with theme=app_settings.BOOTSTRAP_THEME|default:"zephyr" %}<link href="{% static "css/themes/"|add:theme|add:".min.css" %}" rel="stylesheet" id="wvc_css">{% endwith %}
|
|
|
|
<!-- WebVirtCloud CSS -->
|
|
<link href="{% static "css/webvirtcloud.css" %}" rel="stylesheet">
|
|
|
|
<!-- Aditional CSS -->
|
|
{% block style %}{% endblock %}
|
|
|
|
<!-- Custom Fonts -->
|
|
<link href="{% static "css/bootstrap-icons.min.css" %}" rel="stylesheet" type="text/css">
|
|
|
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
<link rel="shortcut icon" href="{% static 'favicon.ico' %}">
|
|
</head>
|
|
|
|
<body class="pb-5"{% block body_attrs %}{% endblock %}>
|
|
|
|
{% if request.user.is_authenticated %}
|
|
{% include 'navbar.html' %}
|
|
{% endif %}
|
|
|
|
<div role="main" class="container">
|
|
{% block page_header %}{# a page with a heading of its own leaves it out #}
|
|
<div>
|
|
<div>
|
|
<div class="float-end">
|
|
{% block page_heading_extra %}
|
|
{% endblock page_heading_extra %}
|
|
</div>
|
|
<h3 class="mb-3">
|
|
{% block page_heading %}
|
|
{% endblock page_heading %}
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
{% endblock page_header %}
|
|
<div id="messages">{% bootstrap_messages %}</div>
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
|
|
{# the dialog every button with data-confirm asks in (confirm_dialog.js) #}
|
|
<div class="modal fade" id="confirm-dialog" tabindex="-1" aria-labelledby="confirm-dialog-title" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title text-break" id="confirm-dialog-title"></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans "Close" %}"></button>
|
|
</div>
|
|
<div class="modal-body text-break"></div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
|
<button type="button" class="btn btn-primary" data-confirm-ok></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bootstrap core JavaScript
|
|
================================================== -->
|
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
<!-- jQuery -->
|
|
<script src="{% static 'js/jquery.js' %}"></script>
|
|
<!-- Bootstrap Core JavaScript -->
|
|
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
|
|
<script src="{% static 'js/confirm_dialog.js' %}"></script>
|
|
<!-- JavaScript Cookie -->
|
|
<script src="{% static 'js/js.cookie.js' %}"></script>
|
|
<!-- Table sorting -->
|
|
<script src="{% static 'js/tablesort.min.js' %}"></script>
|
|
<script src="{% static 'js/tablesort.number.min.js' %}"></script>
|
|
<script src="{% static 'js/sort_tables.js' %}"></script>
|
|
<script>
|
|
// After a refused submission, start at the error. The places an error
|
|
// can be, most specific first: a refused field, its form's summary, an
|
|
// open dialog's copy of the messages (the page's are behind it), the
|
|
// page's messages. A page that sets itself up first has
|
|
// data-error-focus="manual" and calls this when it is ready.
|
|
const ERROR_PLACES = [".is-invalid", ".form-errors", ".modal.show .modal-messages .alert-danger",
|
|
"#messages .alert-danger"];
|
|
|
|
function focusFirstError() {
|
|
for (const selector of ERROR_PLACES) {
|
|
const target = [...document.querySelectorAll(selector)].find(e => e.offsetParent !== null);
|
|
if (target) {
|
|
if (!target.matches("input, select, textarea")) target.tabIndex = -1;
|
|
target.focus();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
window.focusFirstError = focusFirstError;
|
|
if (document.body.dataset.errorFocus !== "manual") focusFirstError();
|
|
</script>
|
|
{% block script %}{% endblock %}
|
|
</body>
|
|
</html>
|