CI / test (push) Successful in 10m51s
The row of a served model leads to its card, which now changes its context and longest answer, its cards, its replicas on each profile with a profile on CPUs to add and its speed beside, stops, starts and restarts it, and removes it with its files or without. Stopped on the row stops the model rather than setting its scaling to nothing. The console gains Replicas per profile, and ctl models shows the counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.0 KiB
JavaScript
71 lines
3.0 KiB
JavaScript
// What the pages did in inline handlers, which the Content-Security-Policy
|
|
// does not run: a form sent when a choice changes, a confirmation before a
|
|
// removal, a field filled from the option chosen, and the live parts of the
|
|
// cluster and node pages refreshed only while the tab is in view.
|
|
(function () {
|
|
document.addEventListener('change', function (e) {
|
|
var t = e.target;
|
|
if (t.matches && t.matches('[data-autosubmit]') && t.form) {
|
|
t.form.submit();
|
|
}
|
|
if (t.matches && t.matches('[data-suggest-into]') && t.form) {
|
|
var f = t.form.elements[t.getAttribute('data-suggest-into')];
|
|
var o = t.selectedOptions[0];
|
|
if (f && o) { f.value = o.dataset.suggest || ''; }
|
|
}
|
|
});
|
|
document.addEventListener('submit', function (e) {
|
|
// The button's own, where a form has several that mean different things.
|
|
var b = e.submitter;
|
|
var msg = (b && b.getAttribute && b.getAttribute('data-confirm')) ||
|
|
(e.target.getAttribute && e.target.getAttribute('data-confirm'));
|
|
if (msg && !window.confirm(msg)) { e.preventDefault(); }
|
|
});
|
|
// A form being filled in is not refreshed away. The live parts of the
|
|
// cluster and node pages are swapped whole every few seconds, and a form
|
|
// inside one lost what was typed into it, its open choice, its focus:
|
|
// filling one in raced the clock. While a field in the refreshing part
|
|
// has the focus, or a form in it has been typed into and not sent, it
|
|
// waits; sending the form, or leaving the page, ends that.
|
|
var edited = [];
|
|
document.addEventListener('input', function (e) {
|
|
var f = e.target.form || (e.target.closest && e.target.closest('form'));
|
|
if (f && edited.indexOf(f) < 0) { edited.push(f); }
|
|
});
|
|
document.addEventListener('submit', function (e) {
|
|
if (!e.defaultPrevented) { edited = []; }
|
|
});
|
|
function busy(root) {
|
|
var a = document.activeElement;
|
|
if (a && a !== document.body && root.contains(a) &&
|
|
a.matches('input, select, textarea, [contenteditable]')) {
|
|
return true;
|
|
}
|
|
for (var i = 0; i < edited.length; i++) {
|
|
if (root.contains(edited[i]) && document.contains(edited[i])) { return true; }
|
|
}
|
|
return false;
|
|
}
|
|
// htmx's trigger filters are evaluated JavaScript; this is the same
|
|
// "only while visible" without them, and "not while being filled in".
|
|
document.addEventListener('htmx:beforeRequest', function (e) {
|
|
var elt = e.detail.elt;
|
|
if (elt.hasAttribute('data-visible-only') &&
|
|
(document.visibilityState !== 'visible' || busy(elt))) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
// A page that reloads itself (<meta name="llmgw-refresh" content="N">)
|
|
// does it on the same terms, rather than by http-equiv, which nothing
|
|
// can hold off.
|
|
var r = document.querySelector('meta[name="llmgw-refresh"]');
|
|
var every = r ? parseInt(r.getAttribute('content'), 10) : 0;
|
|
if (every > 0) {
|
|
setInterval(function () {
|
|
if (document.visibilityState === 'visible' && !busy(document.body)) {
|
|
window.location.reload();
|
|
}
|
|
}, every * 1000);
|
|
}
|
|
})();
|