From fd931581f55f6b15a15405e8efcbc922026df146 Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Wed, 10 Jun 2026 14:25:24 +0300 Subject: [PATCH] fix(themes): style admin health alerts Add custom-theme styles for the admin configuration alerts and bump built-in theme asset versions so existing installations refresh stale theme CSS. --- backend/bot/app/web/themes/ascii/style.css | 59 ++++++++++++++++++- backend/bot/app/web/themes/ascii/theme.json | 2 +- backend/bot/app/web/themes/light/style.css | 21 +++++++ backend/bot/app/web/themes/light/theme.json | 2 +- .../bot/app/web/themes/windows95/style.css | 53 +++++++++++++++++ .../bot/app/web/themes/windows95/theme.json | 2 +- backend/config/webapp_themes_config.py | 3 + tests/test_webapp_themes_config.py | 13 ++-- 8 files changed, 145 insertions(+), 10 deletions(-) diff --git a/backend/bot/app/web/themes/ascii/style.css b/backend/bot/app/web/themes/ascii/style.css index b96b94d..c68e8cf 100644 --- a/backend/bot/app/web/themes/ascii/style.css +++ b/backend/bot/app/web/themes/ascii/style.css @@ -168,6 +168,7 @@ .theme-key-ascii .admin-toolbar-card, .theme-key-ascii .admin-table-card, .theme-key-ascii .admin-panel-dash-card, +.theme-key-ascii .admin-config-alerts, .theme-key-ascii .admin-select-trigger, .theme-key-ascii .admin-select-content, .theme-key-ascii .admin-cn-card[data-slot="card"], @@ -199,7 +200,8 @@ .theme-key-ascii .admin-tabs-trigger, .theme-key-ascii .admin-revenue-period-btn, .theme-key-ascii .admin-mobile-toggle, -.theme-key-ascii .admin-nav-item { +.theme-key-ascii .admin-nav-item, +.theme-key-ascii .admin-config-alert-link { border: 1px solid #ffffff; border-radius: 0; background: #000000; @@ -216,7 +218,8 @@ .theme-key-ascii .admin-nav-item:hover, .theme-key-ascii .admin-tabs-trigger:hover, .theme-key-ascii .admin-revenue-period-btn:hover, -.theme-key-ascii .bottom-nav button:hover { +.theme-key-ascii .bottom-nav button:hover, +.theme-key-ascii .admin-config-alert-link:hover { background: #ffffff; color: #000000; } @@ -393,6 +396,58 @@ color: #000000; } +/* ---------- Admin health config alerts ---------- */ + +.theme-key-ascii .admin-config-alerts { + position: relative; + padding-left: 18px; + color: #ffffff; +} + +.theme-key-ascii .admin-config-alerts::before { + content: "!"; + position: absolute; + top: 11px; + left: 7px; + color: #ffffff; + font-family: var(--font-mono); + font-weight: 700; +} + +.theme-key-ascii .admin-config-alerts-error { + border-color: #ff5555; + color: #ffaaaa; +} + +.theme-key-ascii .admin-config-alerts-error::before { + color: #ff5555; +} + +.theme-key-ascii .admin-config-alert-dot { + width: auto; + height: auto; + border-radius: 0; + background: transparent; + color: currentColor; + transform: none; +} + +.theme-key-ascii .admin-config-alert-dot::before { + content: ">"; + font-family: var(--font-mono); +} + +.theme-key-ascii .admin-config-alert-error .admin-config-alert-dot { + background: transparent; + color: #ff5555; +} + +.theme-key-ascii .admin-config-alert-link { + padding: 1px 7px; + font-family: var(--font-mono); + opacity: 1; +} + /* ---------- New webapp surfaces: support, purchase info, password login ---------- */ .theme-key-ascii .trial-offer-card, diff --git a/backend/bot/app/web/themes/ascii/theme.json b/backend/bot/app/web/themes/ascii/theme.json index 9ab9e61..c4042e0 100644 --- a/backend/bot/app/web/themes/ascii/theme.json +++ b/backend/bot/app/web/themes/ascii/theme.json @@ -9,7 +9,7 @@ "use_primary_accent": false, "use_in_admin": true, "css_file": "style.css", - "assets_version": 6, + "assets_version": 7, "tokens": { "color_scheme": "dark", "style_preset": "ascii" diff --git a/backend/bot/app/web/themes/light/style.css b/backend/bot/app/web/themes/light/style.css index d78fa3b..b8aba75 100644 --- a/backend/bot/app/web/themes/light/style.css +++ b/backend/bot/app/web/themes/light/style.css @@ -252,6 +252,27 @@ body:has(.theme-key-light) .install-platform-item[data-selected] { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); } +/* Admin health config alerts */ + +.theme-key-light .admin-config-alerts { + border-color: color-mix(in srgb, var(--warning) 38%, var(--admin-border)); + background: color-mix(in srgb, var(--warning) 9%, #ffffff); + box-shadow: 0 8px 20px rgba(15, 23, 42, 0.06); +} + +.theme-key-light .admin-config-alerts-error { + border-color: color-mix(in srgb, var(--danger) 38%, var(--admin-border)); + background: color-mix(in srgb, var(--danger) 8%, #ffffff); +} + +.theme-key-light .admin-config-alert-link { + background: rgba(255, 255, 255, 0.58); +} + +.theme-key-light .admin-config-alert-link:hover { + background: #ffffff; +} + /* Telegram notifications banner: keep the warm warning tint but swap the * dark-theme inset bevel for the soft drop shadow the other light cards use. */ .theme-key-light .telegram-notifications-card { diff --git a/backend/bot/app/web/themes/light/theme.json b/backend/bot/app/web/themes/light/theme.json index a501c88..7b03b1f 100644 --- a/backend/bot/app/web/themes/light/theme.json +++ b/backend/bot/app/web/themes/light/theme.json @@ -9,7 +9,7 @@ "use_primary_accent": true, "use_in_admin": true, "css_file": "style.css", - "assets_version": 5, + "assets_version": 6, "tokens": { "color_scheme": "light" } diff --git a/backend/bot/app/web/themes/windows95/style.css b/backend/bot/app/web/themes/windows95/style.css index 0d3ad91..867166f 100644 --- a/backend/bot/app/web/themes/windows95/style.css +++ b/backend/bot/app/web/themes/windows95/style.css @@ -1267,6 +1267,59 @@ body:has(.theme-key-windows95) .install-platform-item[data-selected] { inset -1px -1px 0 #dfdfdf; } +/* Admin health config alerts */ + +.theme-key-windows95 .admin-config-alerts { + border: 2px solid; + border-color: #ffffff #404040 #404040 #ffffff; + background: #ffffcc; + color: #000000; + box-shadow: + inset 1px 1px 0 #dfdfdf, + inset -1px -1px 0 #808080; +} + +.theme-key-windows95 .admin-config-alerts-error { + border-color: #ffffff #404040 #404040 #ffffff; + background: #f7d6d6; + color: #000000; +} + +.theme-key-windows95 .admin-config-alert-dot { + border-radius: 0; + background: #808000; + box-shadow: + 1px 1px 0 #ffffff, + -1px -1px 0 #404040; +} + +.theme-key-windows95 .admin-config-alert-error .admin-config-alert-dot { + background: #800000; +} + +.theme-key-windows95 .admin-config-alert-link { + border: 2px solid; + border-color: #ffffff #404040 #404040 #ffffff; + border-radius: 0; + background: #c0c0c0; + color: #000000; + box-shadow: + inset 1px 1px 0 #dfdfdf, + inset -1px -1px 0 #808080; + opacity: 1; +} + +.theme-key-windows95 .admin-config-alert-link:hover { + background: #dfdfdf; +} + +.theme-key-windows95 .admin-config-alert-link:active { + border-color: #404040 #ffffff #ffffff #404040; + box-shadow: + inset 1px 1px 0 #808080, + inset -1px -1px 0 #dfdfdf; +} + .theme-key-windows95 input::placeholder, .theme-key-windows95 textarea::placeholder, .theme-key-windows95 .input::placeholder, diff --git a/backend/bot/app/web/themes/windows95/theme.json b/backend/bot/app/web/themes/windows95/theme.json index aea131f..754fe36 100644 --- a/backend/bot/app/web/themes/windows95/theme.json +++ b/backend/bot/app/web/themes/windows95/theme.json @@ -9,7 +9,7 @@ "use_primary_accent": false, "use_in_admin": true, "css_file": "style.css", - "assets_version": 13, + "assets_version": 14, "tokens": { "color_scheme": "light", "style_preset": "win95" diff --git a/backend/config/webapp_themes_config.py b/backend/config/webapp_themes_config.py index 4cbeefe..2dc3415 100644 --- a/backend/config/webapp_themes_config.py +++ b/backend/config/webapp_themes_config.py @@ -372,6 +372,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool: or ".theme-key-light.app-shell" not in style or "Install guide theme surfaces" not in style or "Admin controls: range sliders and sortable rows" not in style + or "Admin health config alerts" not in style ) if key == "ascii": return ( @@ -383,6 +384,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool: or "New webapp surfaces: support, purchase info, password login" not in style or "Install guide theme surfaces" not in style or "Admin controls: range sliders and sortable rows" not in style + or "Admin health config alerts" not in style ) if key != "windows95": return False @@ -407,6 +409,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool: or "New webapp surfaces: support, purchase info, password login" not in style or "Install guide theme surfaces" not in style or "Admin controls: range sliders and sortable rows" not in style + or "Admin health config alerts" not in style or any(not (target_dir / "icons" / icon).exists() for icon in required_icons) ) diff --git a/tests/test_webapp_themes_config.py b/tests/test_webapp_themes_config.py index 9d26dcf..6851213 100644 --- a/tests/test_webapp_themes_config.py +++ b/tests/test_webapp_themes_config.py @@ -34,14 +34,14 @@ class WebappThemesConfigTests(unittest.TestCase): self.assertEqual(win95.tokens.style_preset, "win95") self.assertFalse(win95.use_primary_accent) self.assertTrue(win95.use_in_admin) - self.assertEqual(win95.assets_version, 13) - self.assertEqual(cfg.theme_by_key("light").assets_version, 5) + self.assertEqual(win95.assets_version, 14) + self.assertEqual(cfg.theme_by_key("light").assets_version, 6) ascii_theme = cfg.theme_by_key("ascii") self.assertIsNotNone(ascii_theme) self.assertEqual(ascii_theme.css_file, "style.css") self.assertFalse(ascii_theme.use_primary_accent) self.assertTrue(ascii_theme.use_in_admin) - self.assertEqual(ascii_theme.assets_version, 6) + self.assertEqual(ascii_theme.assets_version, 7) def test_env_override_default_theme(self): cfg = builtin_webapp_themes_config("#00fe7a") @@ -430,7 +430,7 @@ class WebappThemesConfigTests(unittest.TestCase): descriptor["assets_version"], cfg.theme_by_key("windows95").assets_version, ) - self.assertEqual(descriptor["assets_version"], 13) + self.assertEqual(descriptor["assets_version"], 14) self.assertIn("lucide-house", css) self.assertIn("lucide-earth", css) self.assertIn("lucide-circle-check", css) @@ -444,6 +444,7 @@ class WebappThemesConfigTests(unittest.TestCase): self.assertIn("New webapp surfaces: support, purchase info, password login", css) self.assertIn("Install guide theme surfaces", css) self.assertIn("Admin controls: range sliders and sortable rows", css) + self.assertIn("Admin health config alerts", css) self.assertIn( ( ".theme-key-windows95 .support-list-card {\n" @@ -486,6 +487,7 @@ class WebappThemesConfigTests(unittest.TestCase): self.assertIn(".theme-key-light.app-shell", css) self.assertIn("Install guide theme surfaces", css) self.assertIn("Admin controls: range sliders and sortable rows", css) + self.assertIn("Admin health config alerts", css) def test_resolved_refreshes_stale_builtin_ascii_assets(self): with tempfile.TemporaryDirectory() as tmp: @@ -518,7 +520,8 @@ class WebappThemesConfigTests(unittest.TestCase): descriptor = json.loads((stale_theme_dir / "theme.json").read_text(encoding="utf-8")) css = (stale_theme_dir / "style.css").read_text(encoding="utf-8") self.assertEqual(descriptor["assets_version"], cfg.theme_by_key("ascii").assets_version) - self.assertEqual(descriptor["assets_version"], 6) + self.assertEqual(descriptor["assets_version"], 7) self.assertIn("Console-style tables", css) self.assertIn("Install guide theme surfaces", css) self.assertIn("Admin controls: range sliders and sortable rows", css) + self.assertIn("Admin health config alerts", css)