refactor(settings): split General into focused pages
Build / build (push) Successful in 10m38s

General was a 547-line catch-all mixing seven concerns, destructive
actions (image prune) inches away from form fields, and Cloudflare DNS
buried under four unrelated cards. A single "Save" committed everything
at once — one invalid field blocked valid edits elsewhere.

Splits:
- /settings                Overview: timezone, core infra, proxy choice
- /settings/integrations   outgoing notification URL + incoming webhook
- /settings/dns            wildcard + Cloudflare provider
- /settings/maintenance    stale threshold, prune threshold, prune action
                           (in a dedicated "Danger zone" card)
- /settings/credentials    removed (was an 18-line redirect stub)

Sidebar is grouped (Overview / Routing / System / Security) with
section headers; NPM & Traefik items remain conditional on the
proxy-provider choice. Each page loads settings and PUTs only its own
subset, so mistakes on one page can't block edits on another.

No backend changes — the API already accepts Partial<Settings>.
This commit is contained in:
2026-04-23 14:53:48 +03:00
parent 03d58a072c
commit e08acf5c0e
8 changed files with 771 additions and 459 deletions
+27
View File
@@ -269,11 +269,18 @@
"settings": {
"title": "Settings",
"general": "General",
"integrations": "Integrations",
"dns": "DNS",
"maintenance": "Maintenance",
"registries": "Registries",
"credentials": "Credentials",
"authentication": "Authentication",
"backup": "Backups",
"appearance": "Appearance",
"groupMain": "Overview",
"groupProxy": "Routing",
"groupSystem": "System",
"groupSecurity": "Security",
"staleThreshold": "Stale threshold (days)",
"staleThresholdHelp": "Containers inactive for longer than this will be flagged as stale.",
"dockerCleanup": "Docker Image Cleanup",
@@ -310,6 +317,10 @@
"settingsGeneral": {
"title": "General Settings",
"globalConfig": "Global Configuration",
"globalConfigDesc": "Core infrastructure: the base domain, network, and polling cadence Tinyforge uses to orchestrate containers.",
"configureNpm": "Nginx Proxy Manager is selected.",
"configureTraefik": "Traefik is selected.",
"configureLink": "Configure provider",
"domain": "Domain",
"domainHelp": "Base domain for subdomain routing (e.g., example.com → stage-dev-app.example.com)",
"serverIp": "Server IP (Docker Host)",
@@ -1079,5 +1090,21 @@
"previewFull": "Full timestamp",
"previewDate": "Date only",
"previewHint": "Timestamps like the event log will look exactly like this."
},
"settingsDns": {
"title": "DNS Configuration",
"description": "Choose whether routes rely on a wildcard record or per-subdomain records managed by a DNS provider."
},
"settingsIntegrations": {
"title": "Integrations",
"outgoing": "Outgoing notifications",
"outgoingDesc": "Where Tinyforge posts deploy and alert events. Paste a webhook URL (Apprise, Discord, Slack, your own handler).",
"incoming": "Incoming webhook"
},
"settingsMaintenance": {
"title": "Maintenance",
"thresholds": "Thresholds",
"thresholdsDesc": "Tune when Tinyforge flags stale containers and warns about unused image disk usage.",
"dangerZone": "Danger zone"
}
}
+27
View File
@@ -269,11 +269,18 @@
"settings": {
"title": "Настройки",
"general": "Общие",
"integrations": "Интеграции",
"dns": "DNS",
"maintenance": "Обслуживание",
"registries": "Реестры",
"credentials": "Учётные данные",
"authentication": "Аутентификация",
"backup": "Резервные копии",
"appearance": "Внешний вид",
"groupMain": "Обзор",
"groupProxy": "Маршрутизация",
"groupSystem": "Система",
"groupSecurity": "Безопасность",
"staleThreshold": "Порог устаревания (дни)",
"staleThresholdHelp": "Контейнеры, неактивные дольше этого срока, будут помечены как устаревшие.",
"dockerCleanup": "Очистка Docker-образов",
@@ -310,6 +317,10 @@
"settingsGeneral": {
"title": "Общие настройки",
"globalConfig": "Глобальная конфигурация",
"globalConfigDesc": "Базовая инфраструктура: домен, сеть и интервал опроса, используемые Tinyforge для оркестрации контейнеров.",
"configureNpm": "Выбран Nginx Proxy Manager.",
"configureTraefik": "Выбран Traefik.",
"configureLink": "Настроить провайдера",
"domain": "Домен",
"domainHelp": "Базовый домен для маршрутизации (напр., example.com → stage-dev-app.example.com)",
"serverIp": "IP сервера (Docker Host)",
@@ -1079,5 +1090,21 @@
"previewFull": "Полная метка времени",
"previewDate": "Только дата",
"previewHint": "Метки времени в логе событий будут выглядеть именно так."
},
"settingsDns": {
"title": "Настройка DNS",
"description": "Выберите, использовать ли wildcard-запись или отдельные поддомены, управляемые DNS-провайдером."
},
"settingsIntegrations": {
"title": "Интеграции",
"outgoing": "Исходящие уведомления",
"outgoingDesc": "Куда Tinyforge отправляет события деплоев и алертов. Укажите webhook-URL (Apprise, Discord, Slack, свой обработчик).",
"incoming": "Входящий вебхук"
},
"settingsMaintenance": {
"title": "Обслуживание",
"thresholds": "Пороги",
"thresholdsDesc": "Настройте, когда Tinyforge помечает контейнеры как устаревшие и предупреждает о неиспользуемых образах.",
"dangerZone": "Опасная зона"
}
}