- 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.
The list pages' search (filter-table.js) read what was typed as a
regular expression: a "(" or "[" stopped it with an error. It also
needed jQuery, while the instance list had its own script for the same
search. Both are now static/js/table_filter.js: plain text in any case,
the instance list's state list and host groups where a page has them,
remembered for a day as before. A group's header row is marked as one
(data-group-header) instead of being any row without a state.
The list gets a state selector beside the search box. The search now
matches plain text in any case (a '(' no longer breaks it), and in the
grouped list a host's name shows all of its VMs while a host row shows
only while one of its VMs does. The filter moves to
static/js/instance_filter.js with a Node test; the other lists keep
filter-table.js. Collapsing a host now sets a class on its table body
instead of each row's display, so a collapsed host and the filter no
longer undo each other.