add localizations, exclude ref from recursion
This commit is contained in:
1 parent
b24e42e516
commit
073635d786
19 files changed
+140
-26
No files matched your search
@@ -58,8 +58,6 @@ const SETTINGS_TABS = [
|
||||
|
||||
type SettingsTabKey = (typeof SETTINGS_TABS)[number]["key"];
|
||||
|
||||
// Maps a validation error back to the tab holding it, so a failed save can
|
||||
// reveal the offending field instead of naming one on a hidden tab.
|
||||
const FIELD_TAB: Record<string, SettingsTabKey> = {
|
||||
checkTTL: "monitoring",
|
||||
globalThresholds: "monitoring",
|
||||
@@ -74,10 +72,6 @@ const tabForField = (field: string): SettingsTabKey =>
|
||||
? "email"
|
||||
: (FIELD_TAB[field.split(".")[0]] ?? "general");
|
||||
|
||||
// Error rows named the raw schema key ("systemEmailRejectUnauthorized"). Each
|
||||
// field already owns a translated label, so reuse those rather than adding
|
||||
// strings. Labels that append an explanation after a dash are trimmed to the
|
||||
// name itself.
|
||||
const FIELD_LABEL_KEY: Record<string, string> = {
|
||||
checkTTL: "pages.settings.form.retention.option.days.label",
|
||||
"globalThresholds.cpu": "pages.settings.form.thresholds.option.cpu.label",
|
||||
@@ -104,10 +98,6 @@ const FIELD_LABEL_KEY: Record<string, string> = {
|
||||
"pages.settings.form.email.option.rejectUnauthorized.label",
|
||||
};
|
||||
|
||||
// react-hook-form nests errors by path, so a grouped field arrives as
|
||||
// { globalThresholds: { cpu: { message } } }. Iterating the top level alone
|
||||
// yields an entry whose own message is undefined, which renders as a bare
|
||||
// "globalThresholds" naming none of the four sliders. Walk to the leaves.
|
||||
type FieldErrorLeaf = { path: string; message?: string };
|
||||
|
||||
const flattenFieldErrors = (errors: unknown, prefix = ""): FieldErrorLeaf[] => {
|
||||
@@ -115,6 +105,9 @@ const flattenFieldErrors = (errors: unknown, prefix = ""): FieldErrorLeaf[] => {
|
||||
return [];
|
||||
}
|
||||
return Object.entries(errors).flatMap(([key, value]) => {
|
||||
if (key === "ref") {
|
||||
return [];
|
||||
}
|
||||
const path = prefix ? `${prefix}.${key}` : key;
|
||||
if (typeof value !== "object" || value === null) {
|
||||
return [];
|
||||
@@ -141,11 +134,7 @@ export const SettingsPage = () => {
|
||||
[isAdmin]
|
||||
);
|
||||
|
||||
// An unknown tab, or an admin tab requested by a non-admin, falls back to the
|
||||
// first tab the current user can actually see.
|
||||
const requestedTab = searchParams.get("tab");
|
||||
// visibleTabs always contains "general" today; the constant fallback keeps a
|
||||
// future gating change from throwing on an empty list.
|
||||
const firstVisibleTab: SettingsTabKey = visibleTabs[0]?.key ?? SETTINGS_TABS[0].key;
|
||||
const activeTab: SettingsTabKey =
|
||||
visibleTabs.find((tab) => tab.key === requestedTab)?.key ?? firstVisibleTab;
|
||||
@@ -160,16 +149,19 @@ export const SettingsPage = () => {
|
||||
setSearchParams(updated, { replace: true });
|
||||
};
|
||||
|
||||
// A "tab" that does not resolve -- an unknown key, or an admin tab followed by
|
||||
// a non-admin -- leaves the URL claiming a tab the page is not showing. Drop it
|
||||
// so the address bar matches what is rendered.
|
||||
// Drop a "tab" param that does not resolve to a rendered tab, or that names
|
||||
// the first tab, which is addressed with no param at all.
|
||||
useEffect(() => {
|
||||
if (requestedTab !== null && requestedTab !== activeTab) {
|
||||
const updated = new URLSearchParams(searchParams);
|
||||
updated.delete("tab");
|
||||
setSearchParams(updated, { replace: true });
|
||||
if (requestedTab === null) {
|
||||
return;
|
||||
}
|
||||
}, [requestedTab, activeTab, searchParams, setSearchParams]);
|
||||
if (requestedTab === activeTab && activeTab !== firstVisibleTab) {
|
||||
return;
|
||||
}
|
||||
const updated = new URLSearchParams(searchParams);
|
||||
updated.delete("tab");
|
||||
setSearchParams(updated, { replace: true });
|
||||
}, [requestedTab, activeTab, firstVisibleTab, searchParams, setSearchParams]);
|
||||
|
||||
// Local state for demo monitors dialog
|
||||
const [isDemoMonitorsDialogOpen, setIsDemoMonitorsDialogOpen] = useState(false);
|
||||
@@ -418,10 +410,6 @@ export const SettingsPage = () => {
|
||||
logger.debug("Form validation errors", errors);
|
||||
};
|
||||
|
||||
// The save bar lists errors by field name, and the offending field may sit on
|
||||
// a tab that is not open. Submitting cannot reveal it -- the button is
|
||||
// disabled while the form is invalid -- so each listed field switches to its
|
||||
// own tab instead.
|
||||
const revealField = (field: string) => {
|
||||
const target = tabForField(field);
|
||||
if (visibleTabs.some((tab) => tab.key === target)) {
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "عام",
|
||||
"monitoring": "المراقبة",
|
||||
"email": "البريد الإلكتروني",
|
||||
"integrations": "التكاملات",
|
||||
"data": "البيانات"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "المنطقة الزمنية للعرض",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "General",
|
||||
"monitoring": "Monitoratge",
|
||||
"email": "Correu electrònic",
|
||||
"integrations": "Integracions",
|
||||
"data": "Dades"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Zona horària de visualització",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Obecné",
|
||||
"monitoring": "Monitorování",
|
||||
"email": "E-mail",
|
||||
"integrations": "Integrace",
|
||||
"data": "Data"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Zobrazované časové pásmo",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Allgemein",
|
||||
"monitoring": "Überwachung",
|
||||
"email": "E-Mail",
|
||||
"integrations": "Integrationen",
|
||||
"data": "Daten"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Anzeigesprache Zeitzone",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "General",
|
||||
"monitoring": "Monitorización",
|
||||
"email": "Correo electrónico",
|
||||
"integrations": "Integraciones",
|
||||
"data": "Datos"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Zona horaria de visualización",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Yleiset",
|
||||
"monitoring": "Valvonta",
|
||||
"email": "Sähköposti",
|
||||
"integrations": "Integraatiot",
|
||||
"data": "Tiedot"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Näytettävä aikavyöhyke",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Général",
|
||||
"monitoring": "Surveillance",
|
||||
"email": "E-mail",
|
||||
"integrations": "Intégrations",
|
||||
"data": "Données"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Fuseau horaire d'affichage",
|
||||
|
||||
@@ -1237,6 +1237,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Generale",
|
||||
"monitoring": "Monitoraggio",
|
||||
"email": "Email",
|
||||
"integrations": "Integrazioni",
|
||||
"data": "Dati"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Fuso orario di visualizzazione",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "一般",
|
||||
"monitoring": "監視",
|
||||
"email": "メール",
|
||||
"integrations": "連携",
|
||||
"data": "データ"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "表示タイムゾーン",
|
||||
|
||||
@@ -1207,6 +1207,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Ogólne",
|
||||
"monitoring": "Monitorowanie",
|
||||
"email": "E-mail",
|
||||
"integrations": "Integracje",
|
||||
"data": "Dane"
|
||||
},
|
||||
"form": {
|
||||
"about": {
|
||||
"developedBy": "Opracowane przez Bluewave Labs",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Geral",
|
||||
"monitoring": "Monitoramento",
|
||||
"email": "E-mail",
|
||||
"integrations": "Integrações",
|
||||
"data": "Dados"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Fuso horário de exibição",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Общие",
|
||||
"monitoring": "Мониторинг",
|
||||
"email": "Электронная почта",
|
||||
"integrations": "Интеграции",
|
||||
"data": "Данные"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Часовой пояс отображения",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "ทั่วไป",
|
||||
"monitoring": "การตรวจสอบ",
|
||||
"email": "อีเมล",
|
||||
"integrations": "การเชื่อมต่อ",
|
||||
"data": "ข้อมูล"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "เขตเวลาที่แสดง",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Genel",
|
||||
"monitoring": "İzleme",
|
||||
"email": "E-posta",
|
||||
"integrations": "Entegrasyonlar",
|
||||
"data": "Veri"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Görüntüleme saat dilimi",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Загальні",
|
||||
"monitoring": "Моніторинг",
|
||||
"email": "Електронна пошта",
|
||||
"integrations": "Інтеграції",
|
||||
"data": "Дані"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Часовий пояс відображення",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "Chung",
|
||||
"monitoring": "Giám sát",
|
||||
"email": "Email",
|
||||
"integrations": "Tích hợp",
|
||||
"data": "Dữ liệu"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "Múi giờ hiển thị",
|
||||
|
||||
@@ -1142,6 +1142,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "常规",
|
||||
"monitoring": "监控",
|
||||
"email": "邮件",
|
||||
"integrations": "集成",
|
||||
"data": "数据"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "显示时区",
|
||||
|
||||
@@ -1141,6 +1141,13 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"tabs": {
|
||||
"general": "一般",
|
||||
"monitoring": "監控",
|
||||
"email": "郵件",
|
||||
"integrations": "整合",
|
||||
"data": "資料"
|
||||
},
|
||||
"form": {
|
||||
"timezone": {
|
||||
"title": "顯示時區",
|
||||
|
||||
Reference in new issue
Block a user