1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-10 04:06:47 +00:00

fix(instances): the VM list searches its VMs, collapses its hosts together and says when it is empty

- The search read a row's whole text, so a word on a button or in a
  state label matched every row. VM rows now carry data-search (the
  name, title and owners, and the host in the flat list), and
  table_filter.js searches that text when a row has it; the state has
  its own filter.
- Nothing matching left an empty table. table_filter.js shows the
  page's #no-match while no row does; the VM list's says so and offers
  "Clear the filters". A user with no VMs at all is told so instead of
  an empty table.
- The grouped list's "#" toggled each host on its own: a host
  collapsed by hand opened while the others closed. It now collapses
  every host, or opens them all once all are collapsed.
- One alert names every host the panel cannot reach, with why, in
  place of one dismissible alert per host; users who see no hosts keep
  their own message.
- A host's VM list showed a VM's maximum memory, the Instances page
  its current memory: both show the current memory now.
- The owners' users are prefetched with the VMs; the flat list's
  Bootstrap 4 font-italic is fst-italic.
This commit is contained in:
catborise 2026-10-27 22:20:50 +03:00
parent 321749f8fa
commit 2d80f21a4a
9 changed files with 114 additions and 37 deletions

View file

@ -1,14 +1,17 @@
// The search box of a list page, and the instance list's state list.
//
// A row shows when its text contains the search, in any case: plain text,
// not a pattern. With a state list, the row's [data-state] must be the
// chosen state too. In a grouped list a search for a group's host shows all
// of its rows, and its header row (data-group-header) shows while any of its
// rows does. The search is remembered for a day, per page.
// not a pattern. A row with data-search is searched in that text only, not
// in its buttons and menus. With a state list, the row's [data-state] must
// be the chosen state too. In a grouped list a search for a group's host
// shows all of its rows, and its header row (data-group-header) shows while
// any of its rows does. A page's #no-match shows while no row does. The
// search is remembered for a day, per page.
function filterTable(doc) {
var text = doc.getElementById("filter").value.toLowerCase();
var states = doc.getElementById("state-filter");
var state = states ? states.value : "";
var anyShown = false;
doc.querySelectorAll(".searchable").forEach(function (group) {
var host = group.dataset.host;
var hostMatches = host !== undefined && host.toLowerCase().includes(text);
@ -19,14 +22,20 @@ function filterTable(doc) {
return;
}
var mark = row.querySelector("[data-state]");
var searched = row.dataset.search !== undefined ? row.dataset.search : row.textContent;
row.hidden = !((!state || (mark && mark.dataset.state === state)) &&
(hostMatches || row.textContent.toLowerCase().includes(text)));
(hostMatches || searched.toLowerCase().includes(text)));
shown = shown || !row.hidden;
});
if (header) {
header.hidden = !shown;
}
anyShown = anyShown || shown;
});
var noMatch = doc.getElementById("no-match");
if (noMatch) {
noMatch.hidden = anyShown;
}
}
if (typeof module !== "undefined") {
@ -44,5 +53,16 @@ if (typeof module !== "undefined") {
filterTable(document);
});
}
var clear = document.getElementById("clear-filters");
if (clear) {
clear.addEventListener("click", function () {
search.value = "";
Cookies.remove(document.title + "_filter");
if (states) {
states.value = "";
}
filterTable(document);
});
}
filterTable(document);
}