audit 4: log paging at its edges, NaN refused, a red rate limit, recalculation asks, reload writes all
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
Step 4 of stage 4 (L10, L11, L13, L18, L19 and a row of
review-2026-08-followups):
- The Outbound log counts first and clamps the page to the last; a number
too large for an int (strconv's ErrRange with the largest int) is the
last page on both logs. Tested at the edges: first, last, past the last
however far, nonsense, an empty log asked for page 5.
- checkAutoMultiplier is "not within", so NaN and the infinities are out.
- rate-limited is red (components.go; the mockup first, 643892a).
- data-unsaved on both recalculate buttons: panel.js asks on submit
(ev.submitter) when a field of the page differs from what it was drawn
with; testdata/unsaved_test.js under TestPanelJS.
- HandleReload writes what a restore's first start writes - the filter
lists and the DMARC maps too - and a failed step is an error flash on
Health that names it, not plain text; the success flash says what was
written.
Tested on the test server: go vet + go test of 25 packages, make e2e (all
pass, 695 s) on this tree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,9 +99,58 @@
|
||||
var form = ev.target.closest("form[data-confirm]");
|
||||
if (form && !window.confirm(form.dataset.confirm)) {
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
// A button that does something else than save - recalculate a rate
|
||||
// limit - leaves the page, and what was typed on it and not saved goes
|
||||
// with it. Such a button carries data-unsaved, the question to ask when
|
||||
// a field of the page differs from what the page was drawn with (audit
|
||||
// 2026-10-12, L19). HTML Living Standard, SubmitEvent: submitter is the
|
||||
// button that submitted the form.
|
||||
var button = ev.submitter;
|
||||
if (button && button.dataset && button.dataset.unsaved && hasUnsavedEdit() &&
|
||||
!window.confirm(button.dataset.unsaved)) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// hasUnsavedEdit tells whether a field of the page holds a value the page
|
||||
// was not drawn with: defaultValue, defaultChecked and defaultSelected are
|
||||
// what the markup said (HTML Living Standard, the input, select and
|
||||
// textarea elements). A select none of whose options says selected was
|
||||
// drawn with its first option, or none when it is a list (size or multiple).
|
||||
function hasUnsavedEdit() {
|
||||
var fields = document.querySelectorAll("input, select, textarea");
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var f = fields[i];
|
||||
if (f.disabled || f.type === "hidden" || f.type === "submit" || f.type === "button" || f.type === "reset") {
|
||||
continue;
|
||||
}
|
||||
if (f.type === "checkbox" || f.type === "radio") {
|
||||
if (f.checked !== f.defaultChecked) {
|
||||
return true;
|
||||
}
|
||||
} else if (f.tagName === "SELECT") {
|
||||
var drawn = -1;
|
||||
for (var j = 0; j < f.options.length; j++) {
|
||||
if (f.options[j].defaultSelected) {
|
||||
drawn = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (drawn < 0 && !f.multiple && f.size <= 1 && f.options.length > 0) {
|
||||
drawn = 0;
|
||||
}
|
||||
if (f.selectedIndex !== drawn) {
|
||||
return true;
|
||||
}
|
||||
} else if (f.value !== f.defaultValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Conditional field visibility ------------------------------------
|
||||
// Several forms hide a block until a select, checkbox or file input says it
|
||||
// applies. One rule table drives them all so the five near-identical helpers
|
||||
|
||||
Reference in New Issue
Block a user