1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 11:46:49 +00:00

refactor(instances): the VM lists' scripts load from static files

The VM lists lose their inline scripts and handlers: host_groups.js
collapses a host's VMs in the grouped list, new_vm_dialog.js reads the
new-VM dialog's CPU bars and capacity lines, and console_window.js
(loaded by every page) opens a console button's window, on the lists and
on the VM page alike. A list row's Start no longer calls the please-wait
dialog, which the list pages do not have (the call only raised an
error). The VM page's URL placeholders take the __name__ form the other
pages use.
This commit is contained in:
catborise 2026-11-02 09:35:07 +03:00
parent e143fe353a
commit 946629b035
11 changed files with 98 additions and 91 deletions

View file

@ -0,0 +1,6 @@
// A console button (data-url, data-window) opens the console in one window
// per VM: opening it again reloads that window.
document.addEventListener("click", function (event) {
var button = event.target.closest("button[data-window]");
if (button) window.open(button.dataset.url, button.dataset.window, "width=850,height=650");
});

24
static/js/host_groups.js Normal file
View file

@ -0,0 +1,24 @@
// The VM list grouped by host (allinstances_index_grouped.html): a host's
// VMs collapse under its row. A collapsed host's VM rows are hidden by its
// table body's class, so the search (table_filter.js, the hidden attribute)
// can still hide them too.
function set_host_collapsed(tbody, collapsed) {
$(tbody).toggleClass('host-collapsed', collapsed);
$(tbody).find('[aria-controls]').attr('aria-expanded', !collapsed);
$(tbody).find('.host-chevron').toggleClass('bi-chevron-down', collapsed).toggleClass('bi-chevron-up', !collapsed);
$(tbody).find('.host-collapsed-badge').toggleClass('d-none', !collapsed);
// expanded while any host is, as the next click collapses them all
$('#hide-all-instances').attr('aria-expanded', $('tbody.searchable').not('.host-collapsed').length > 0);
}
// every host the same way: collapsed, unless all already are
$('#hide-all-instances').on('click', function () {
var bodies = $('tbody.searchable');
var collapse = bodies.not('.host-collapsed').length > 0;
bodies.each(function () { set_host_collapsed(this, collapse); });
});
$('.host-toggle').on('click', function () {
var tbody = $(this).closest('tbody');
set_host_collapsed(tbody, !tbody.hasClass('host-collapsed'));
});

View file

@ -50,10 +50,6 @@
show_tab('#clone');
});
// one window per VM: opening it again reloads it
on("console_button", "click", function () {
window.open(this.dataset.url, this.dataset.window, 'width=850,height=650');
});
if (summary.dataset.vdiUrl) {
$.get(summary.dataset.vdiUrl, function (data) {
$("#vdi_url_input").attr("value", data);
@ -88,7 +84,7 @@
var pool = document.getElementById("selected_storage");
if (pool) {
pool.addEventListener("change", function () {
$.getJSON(pool.dataset.volumesUrl.replace("POOL", encodeURIComponent(pool.value)), function (data) {
$.getJSON(pool.dataset.volumesUrl.replace("__pool__", encodeURIComponent(pool.value)), function (data) {
var vols = $("#vols").empty();
$.each(data['vols'], function (i, item) {
vols.append($("<option>").val(item).text(item));
@ -109,7 +105,7 @@
var cloneName = document.getElementById("clone_name");
// the DHCP host entry of the clone's name holds one address: the first NIC's
function guess_mac_address() {
$.getJSON(cloneName.dataset.guessMacUrl.replace("NAME", encodeURIComponent(cloneName.value)), function (data) {
$.getJSON(cloneName.dataset.guessMacUrl.replace("__name__", encodeURIComponent(cloneName.value)), function (data) {
$('input[name="clone-net-mac-0"]').val(data['mac']);
});
}

View file

@ -0,0 +1,50 @@
// The new-VM dialog's CPU bars and capacity lines, read when the
// dialog opens, two reads at a time: a CPU read holds a worker for
// a second, a capacity read while it reads the host's VMs. Answers
// of an earlier opening are ignored.
const addInstance = document.getElementById("AddInstance");
let opening = 0, queue = [], reading = 0;
function setCpuUsage(cell, percent, text) {
const meter = cell.querySelector(".progress");
cell.querySelector(".progress-bar").style.width = (percent || 0) + "%";
if (percent === null) {
meter.removeAttribute("aria-valuenow");
} else {
meter.setAttribute("aria-valuenow", percent);
}
cell.querySelector(".cpu-usage-value").textContent = text;
}
// data: the answer, or null when the read failed
function show(element, data) {
if (element.classList.contains("compute-capacity")) {
element.textContent = data === null ? "" : data.trim();
return;
}
const usage = data !== null && typeof data.cpudata === "number" ? Math.round(data.cpudata) : null;
setCpuUsage(element, usage, usage === null ? "—" : usage + "%");
}
function readNext() {
while (reading < 2 && queue.length) {
const element = queue.shift(), current = opening;
reading++;
$.get(element.dataset.url)
.done((data) => { if (current === opening) show(element, data); })
.fail(() => { if (current === opening) show(element, null); })
.always(() => { reading--; readNext(); });
}
}
addInstance.addEventListener("show.bs.modal", function () {
opening++;
addInstance.querySelectorAll(".cpu-usage").forEach((cell) => setCpuUsage(cell, null, "…"));
// host by host, as the list shows them
queue = Array.from(addInstance.querySelectorAll(".cpu-usage, .compute-capacity"));
readNext();
});
addInstance.addEventListener("hide.bs.modal", function () {
opening++;
queue = [];
});