Show nested settings validation errors

This commit is contained in:
ushan0v
2026-07-14 01:06:41 +03:00
parent c60ce8179b
commit adf4edc73c
8 changed files with 1262 additions and 1162 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: FORKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-13 00:06+0300\n"
"PO-Revision-Date: 2026-07-13 00:06+0300\n"
"POT-Creation-Date: 2026-07-13 01:05+0300\n"
"PO-Revision-Date: 2026-07-13 01:05+0300\n"
"Last-Translator: ushan0v\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -248,6 +248,9 @@ msgstr "Не удалось получить результаты проверк
msgid "Cannot save server"
msgstr "Не удалось сохранить сервер"
msgid "Cannot save settings"
msgstr "Не удалось сохранить настройки"
msgid "Cascade connection"
msgstr "Каскадное подключение"
@@ -3391,6 +3391,39 @@ function renderStackedJsonSettingsModal(title, map, onSave) {
const originalButtonNodes = Array.from(buttonRow.childNodes);
let closed = false;
let saveButton;
let validationSummary;
const clearValidationSummary = () => {
if (validationSummary && validationSummary.parentNode) {
validationSummary.parentNode.removeChild(validationSummary);
}
validationSummary = null;
};
const showValidationSummary = (error) => {
clearValidationSummary();
const message = error?.message || "";
validationSummary = E(
"div",
{
class:
"alert-message warning fkp-stacked-settings-validation-summary",
},
[
E("strong", {}, _("Cannot save settings")),
E("div", {}, _("Fix the highlighted fields and save again.")),
message ? E("small", {}, message) : "",
],
);
buttonRow.parentNode.insertBefore(validationSummary, buttonRow);
const invalidInput = nodes.querySelector(".cbi-input-invalid");
if (invalidInput) {
invalidInput.scrollIntoView({ block: "center", behavior: "smooth" });
invalidInput.focus({ preventScroll: true });
}
};
const restoreButtonRow = () => {
buttonRow.textContent = "";
@@ -3404,6 +3437,7 @@ function renderStackedJsonSettingsModal(title, map, onSave) {
}
closed = true;
clearValidationSummary();
if (nodes.parentNode) {
nodes.parentNode.removeChild(nodes);
@@ -3420,6 +3454,7 @@ function renderStackedJsonSettingsModal(title, map, onSave) {
if (saveButton) {
saveButton.disabled = true;
}
clearValidationSummary();
return map
.parse()
@@ -3427,10 +3462,11 @@ function renderStackedJsonSettingsModal(title, map, onSave) {
onSave(cleanFormSectionData(map.data.get(map.config, "settings")));
close();
})
.catch(() => {
.catch((error) => {
if (saveButton) {
saveButton.disabled = false;
}
showValidationSummary(error);
});
};
+5 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: FORKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-13 00:06+0300\n"
"PO-Revision-Date: 2026-07-13 00:06+0300\n"
"POT-Creation-Date: 2026-07-13 01:05+0300\n"
"PO-Revision-Date: 2026-07-13 01:05+0300\n"
"Last-Translator: ushan0v\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -248,6 +248,9 @@ msgstr "Не удалось получить результаты проверк
msgid "Cannot save server"
msgstr "Не удалось сохранить сервер"
msgid "Cannot save settings"
msgstr "Не удалось сохранить настройки"
msgid "Cascade connection"
msgstr "Каскадное подключение"
File diff suppressed because it is too large Load Diff
+9
View File
@@ -37,6 +37,15 @@ for po in "$SOURCE_PO" "$PACKAGE_PO"; do
' "$po"; then
fail "Dismiss must not override LuCI alert closing with Отмена in $po"
fi
awk '
$0 == "msgid \"Cannot save settings\"" {
getline
if ($0 == "msgstr \"Не удалось сохранить настройки\"")
found = 1
}
END { exit found ? 0 : 1 }
' "$po" || fail "Cannot save settings must have a Russian translation in $po"
done
cmp -s "$SOURCE_PO" "$PACKAGE_PO" ||
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -eo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SECTION_JS="$ROOT_DIR/luci-app-forkop/htdocs/luci-static/resources/view/forkop/section.js"
fail() {
printf 'FAIL: %s\n' "$1" >&2
exit 1
}
modal_source="$(sed -n '/^function renderStackedJsonSettingsModal(/,/^function renderJsonOutboundSettingsModal(/p' "$SECTION_JS")"
grep -Fq '.catch((error) => {' <<<"$modal_source" ||
fail "stacked settings Save must retain the validation error"
grep -Fq 'fkp-stacked-settings-validation-summary' <<<"$modal_source" ||
fail "stacked settings Save must render a visible validation summary"
grep -Fq '_("Cannot save settings")' <<<"$modal_source" ||
fail "stacked settings validation summary must explain that Save failed"
grep -Fq '_("Fix the highlighted fields and save again.")' <<<"$modal_source" ||
fail "stacked settings validation summary must tell the user how to recover"
grep -Fq 'const invalidInput = nodes.querySelector(".cbi-input-invalid");' <<<"$modal_source" ||
fail "stacked settings validation must target only the active nested form"
grep -Fq 'invalidInput.scrollIntoView({ block: "center", behavior: "smooth" });' <<<"$modal_source" ||
fail "stacked settings validation must reveal the first invalid field"
grep -Fq 'invalidInput.focus({ preventScroll: true });' <<<"$modal_source" ||
fail "stacked settings validation must focus the first invalid field"
[[ "$(grep -Fc 'clearValidationSummary();' <<<"$modal_source")" -ge 3 ]] ||
fail "stacked settings validation summary must be cleared before retry and close"
printf 'LuCI stacked settings validation checks passed\n'