1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/templates/base.html
catborise dba41f97f3 fix(instances): a refused VM create form comes back with what was entered
When the server refused a VM create submission (a field error, a busy
resource, a reused submission key, an existing VM name, a missing MAC
for a new disk), the page came back on its first tab with the flavor
dialog closed and every entered value gone: the hand-written fields
showed fixed defaults, and the errors sat in a block at the top of the
page, outside #messages and tied to no field.

The view builds one NewVMForm per create form on the page (custom,
template, one per flavor; create_forms), each with its own defaults; a
hidden form_id, which is also the prefix of the form's field ids, names
the submitted one, and it comes back bound. Every field renders from its
own form and is marked by two small template tags (form_fields:
error_attrs, field_error) when refused; a summary at the top of the
form lists all of its errors, also those of fields it keeps hidden. The
submitted tab or flavor dialog, marked data-form-id, reopens with any
"Advanced" section that holds an error; a reopened dialog shows the
messages too; the template form gets its pool, template and storage
back. base.html's error focus is a function that walks the places an
error can be, and a page can call it once it is set up, as the create
page does. form_id changes nothing in how a POST is processed; one of
an unknown form (a flavor deleted since) has its errors in the
messages. The default video now applies to every create form.

The custom form's disks and networks are not restored yet.
2026-10-20 08:12:25 +03:00

93 lines
3.6 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{% block body_attrs %}{% endblock %}>
{% if request.user.is_authenticated %}
{% include 'navbar.html' %}
{% endif %}
<div role="main" class="container">
<div>
<div>
<div class="float-end">
{% block page_heading_extra %}
{% endblock page_heading_extra %}
</div>
<h3 class="ms-0 page-header">
{% block page_heading %}
{% endblock page_heading %}
</h3>
</div>
</div>
<div id="messages">{% bootstrap_messages %}</div>
{% block content %}{% endblock %}
</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>
<!-- JavaScript Cookie -->
<script src="{% static 'js/js.cookie.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>