From edd4b37325a899b7606a83ec8ba2eb38350d9ef7 Mon Sep 17 00:00:00 2001 From: Chris Hengge Date: Sat, 21 Mar 2026 21:09:00 -0500 Subject: [PATCH 1/5] fix(web/dashboard): rename channels card heading and add internal scroll (#4178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The card heading used the key dashboard.active_channels ("Active Channels") even though the card has a toggle between Active and All views, making the static heading misleading. The channel list div had no height cap, causing tall channel lists to stretch the card and break 3-column grid alignment. - Change heading to t("dashboard.channels") — key already present in all three locales (zh/en/tr), no i18n changes needed - Add overflow-y-auto max-h-48 pr-1 to the channel list wrapper so it scrolls internally instead of stretching the card --- web/src/pages/Dashboard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index 587ce3cdb..719e21296 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -236,7 +236,7 @@ export default function Dashboard() { className="text-sm font-semibold uppercase tracking-wider" style={{ color: "var(--pc-text-primary)" }} > - {t("dashboard.active_channels")} + {t("dashboard.channels")} -
+
{Object.entries(status.channels).length === 0 ? (

{t("dashboard.no_channels")} From a84aa60554353c4d5e63fc4ab7f3f13c31113559 Mon Sep 17 00:00:00 2001 From: Chris Hengge Date: Sat, 21 Mar 2026 21:11:15 -0500 Subject: [PATCH 2/5] fix(web/cron): contain table scroll within viewport (#4186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cron page used a block-flow root with no height constraint, causing the jobs table to grow taller than the viewport and the page itself to scroll. This was inconsistent with the Memory page pattern. - Change page root to flex flex-col h-full matching Memory's layout - Table wrapper gains flex-1 min-h-0 overflow-auto so it fills remaining height and scrolls both axes internally - Table header already has position:sticky so it pins correctly inside the scrolling container with no CSS change needed Risk: Low — layout only, no logic or API change. Does not change: job CRUD, modal, catch-up toggle, run history panel. --- web/src/pages/Cron.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/pages/Cron.tsx b/web/src/pages/Cron.tsx index cb2904b91..c45d7dc56 100644 --- a/web/src/pages/Cron.tsx +++ b/web/src/pages/Cron.tsx @@ -293,7 +293,7 @@ export default function Cron() { } return ( -

+
{/* Header */}
@@ -415,7 +415,7 @@ export default function Cron() {

{t('cron.empty')}

) : ( -
+
From 0aefde95f20b235a85426f200cf3b3b5824ef537 Mon Sep 17 00:00:00 2001 From: Chris Hengge Date: Sat, 21 Mar 2026 21:11:18 -0500 Subject: [PATCH 3/5] fix(web/config): fill viewport and add TOML syntax highlighting (#4201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues with the config editor: Layout: the page root had no height constraint and the textarea used min-h-[500px] resize-y, causing independent scrollbars on both the page and the editor. Fixed by adopting the Memory/Cron flex column pattern so the editor fills the remaining viewport height with a single scroll surface. Highlighting: plain textarea with no visual structure for TOML. Added a zero-dependency layered pre-overlay technique — no new npm packages (per CLAUDE.md anti-pattern rules). A pre element sits absolute behind a transparent textarea; highlightToml() produces HTML colour-coding sections, keys, strings, booleans, numbers, datetimes, and comments via per-line regex. onScroll syncs the overlay. Tab key inserts two spaces instead of leaving focus. dangerouslySetInnerHTML used on the pre — content is the user's own local config, not from the network, risk equivalent to any local editor. Risk: Low-Medium — no API or backend change. New rendering logic in editor only. Does not change: save/load API calls, validation, sensitive field masking behaviour. --- web/src/pages/Config.tsx | 136 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 10 deletions(-) diff --git a/web/src/pages/Config.tsx b/web/src/pages/Config.tsx index 66167b791..f23d25b47 100644 --- a/web/src/pages/Config.tsx +++ b/web/src/pages/Config.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef, useCallback } from 'react'; import { Settings, Save, @@ -9,6 +9,91 @@ import { import { getConfig, putConfig } from '@/lib/api'; import { t } from '@/lib/i18n'; + +// --------------------------------------------------------------------------- +// Lightweight zero-dependency TOML syntax highlighter. +// Produces an HTML string. The
 overlay sits behind the