From 6a1d3bb1298a6e72493ff73b6fe66b5f0d3c7905 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:45:02 +0200 Subject: [PATCH] refactor: move inline styles to CSS modules Extract inline fontSize/color styles from LogTab, LayoutShell, UsersTab, GroupsTab, RolesTab, and LevelFilterBar into CSS modules. Follows project convention of CSS modules over inline styles. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ExecutionDiagram/tabs/LogTab.module.css | 97 +++++++++++++++++++ .../ExecutionDiagram/tabs/LogTab.tsx | 51 ++++------ ui/src/components/LayoutShell.module.css | 16 +++ ui/src/components/LayoutShell.tsx | 5 +- ui/src/pages/Admin/GroupsTab.tsx | 2 +- ui/src/pages/Admin/RolesTab.tsx | 2 +- ui/src/pages/Admin/UserManagement.module.css | 5 + ui/src/pages/Admin/UsersTab.tsx | 2 +- .../pages/LogsTab/LevelFilterBar.module.css | 14 +++ ui/src/pages/LogsTab/LevelFilterBar.tsx | 12 +-- 10 files changed, 162 insertions(+), 44 deletions(-) create mode 100644 ui/src/components/ExecutionDiagram/tabs/LogTab.module.css create mode 100644 ui/src/components/LayoutShell.module.css create mode 100644 ui/src/pages/LogsTab/LevelFilterBar.module.css diff --git a/ui/src/components/ExecutionDiagram/tabs/LogTab.module.css b/ui/src/components/ExecutionDiagram/tabs/LogTab.module.css new file mode 100644 index 00000000..d9326afe --- /dev/null +++ b/ui/src/components/ExecutionDiagram/tabs/LogTab.module.css @@ -0,0 +1,97 @@ +/* ========================================================================== + LOG TAB — STYLES + ========================================================================== */ +.container { + display: flex; + flex-direction: column; + height: 100%; + min-height: 0; +} + +.filterBar { + padding: 6px 10px; + border-bottom: 1px solid var(--border-subtle); +} + +.filterInput { + width: 100%; + padding: 4px 8px; + font-size: 12px; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + background: var(--bg-surface); + color: var(--text-primary); + outline: none; + font-family: var(--font-body); +} + +.logList { + flex: 1; + overflow-y: auto; + font-size: 12px; + font-family: var(--font-mono); +} + +.logTable { + width: 100%; + border-collapse: collapse; +} + +.logRow { + border-bottom: 1px solid var(--border-subtle); +} + +.timestampCell { + padding: 3px 6px; + white-space: nowrap; + color: var(--text-muted); +} + +.levelCell { + padding: 3px 4px; + white-space: nowrap; + font-weight: 600; + width: 40px; +} + +.levelError { + color: var(--error); +} + +.levelWarn { + color: var(--warning); +} + +.levelDebug { + color: var(--text-muted); +} + +.levelTrace { + color: var(--text-faint, var(--text-muted)); +} + +.levelDefault { + color: var(--text-secondary); +} + +.messageCell { + padding: 3px 6px; + color: var(--text-primary); + word-break: break-word; +} + +.footer { + padding: 6px 10px; + border-top: 1px solid var(--border-subtle); + font-size: 12px; + text-align: center; +} + +.openLogsButton { + background: none; + border: none; + color: var(--amber); + cursor: pointer; + font-size: 12px; + font-family: var(--font-body); +} diff --git a/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx b/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx index 700edcb8..10d6b4a8 100644 --- a/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx +++ b/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx @@ -2,7 +2,8 @@ import { useState, useMemo } from 'react'; import { useNavigate } from 'react-router'; import { useApplicationLogs } from '../../../api/queries/logs'; import type { LogEntryResponse } from '../../../api/queries/logs'; -import styles from '../ExecutionDiagram.module.css'; +import logStyles from './LogTab.module.css'; +import diagramStyles from '../ExecutionDiagram.module.css'; interface LogTabProps { applicationId: string; @@ -10,13 +11,13 @@ interface LogTabProps { processorId: string | null; } -function levelColor(level: string): string { +function levelClass(level: string): string { switch (level?.toUpperCase()) { - case 'ERROR': return 'var(--error)'; - case 'WARN': return 'var(--warning)'; - case 'DEBUG': return 'var(--text-muted)'; - case 'TRACE': return 'var(--text-faint, var(--text-muted))'; - default: return 'var(--text-secondary)'; + case 'ERROR': return logStyles.levelError; + case 'WARN': return logStyles.levelWarn; + case 'DEBUG': return logStyles.levelDebug; + case 'TRACE': return logStyles.levelTrace; + default: return logStyles.levelDefault; } } @@ -65,48 +66,38 @@ export function LogTab({ applicationId, exchangeId, processorId }: LogTabProps) }, [logs, processorId, filter]); if (isLoading) { - return
Loading logs...
; + return
Loading logs...
; } return ( -
-
+
+
setFilter(e.target.value)} - style={{ - width: '100%', - padding: '4px 8px', - fontSize: '12px', - border: '1px solid var(--border-subtle)', - borderRadius: 'var(--radius-sm)', - background: 'var(--bg-surface)', - color: 'var(--text-primary)', - outline: 'none', - fontFamily: 'var(--font-body)', - }} + className={logStyles.filterInput} />
-
+
{entries.length === 0 ? ( -
+
{processorId ? 'No logs for this processor' : 'No logs available'}
) : ( <> - +
{entries.map((entry, i) => ( - - + - - @@ -114,10 +105,10 @@ export function LogTab({ applicationId, exchangeId, processorId }: LogTabProps)
+
{formatTime(entry.timestamp)} + {entry.level} + {entry.message}
{exchangeId && ( -
+
diff --git a/ui/src/components/LayoutShell.module.css b/ui/src/components/LayoutShell.module.css new file mode 100644 index 00000000..390d76bf --- /dev/null +++ b/ui/src/components/LayoutShell.module.css @@ -0,0 +1,16 @@ +.starredItem { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 12px; + cursor: pointer; + font-size: 12px; + color: var(--sidebar-text); + border-radius: 4px; +} + +.starredParentApp { + color: var(--sidebar-muted); + margin-left: 4px; + font-size: 12px; +} diff --git a/ui/src/components/LayoutShell.tsx b/ui/src/components/LayoutShell.tsx index 699f2f19..040c06da 100644 --- a/ui/src/components/LayoutShell.tsx +++ b/ui/src/components/LayoutShell.tsx @@ -18,6 +18,7 @@ import { import type { SearchResult, SidebarTreeNode } from '@cameleer/design-system'; import sidebarLogo from '@cameleer/design-system/assets/cameleer3-logo.svg'; import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X } from 'lucide-react'; +import css from './LayoutShell.module.css'; import { useQueryClient } from '@tanstack/react-query'; import { useRouteCatalog } from '../api/queries/catalog'; import { useAgents } from '../api/queries/agents'; @@ -236,7 +237,7 @@ function StarredList({ items, onNavigate, onRemove }: { items: StarredItem[]; on {items.map((item) => (
onNavigate(item.path)} role="button" tabIndex={0} @@ -245,7 +246,7 @@ function StarredList({ items, onNavigate, onRemove }: { items: StarredItem[]; on {item.icon && {item.icon}} {item.label} - {item.parentApp && {item.parentApp}} + {item.parentApp && {item.parentApp}}
{duplicateUsername && ( - + Username already exists )} diff --git a/ui/src/pages/LogsTab/LevelFilterBar.module.css b/ui/src/pages/LogsTab/LevelFilterBar.module.css new file mode 100644 index 00000000..cca18bb3 --- /dev/null +++ b/ui/src/pages/LogsTab/LevelFilterBar.module.css @@ -0,0 +1,14 @@ +.wrapper { + display: flex; + align-items: center; + gap: 8px; +} + +.clearButton { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + font-size: 12px; + font-family: var(--font-body); +} diff --git a/ui/src/pages/LogsTab/LevelFilterBar.tsx b/ui/src/pages/LogsTab/LevelFilterBar.tsx index 2ef8a3db..0cacae9c 100644 --- a/ui/src/pages/LogsTab/LevelFilterBar.tsx +++ b/ui/src/pages/LogsTab/LevelFilterBar.tsx @@ -1,5 +1,6 @@ import { ButtonGroup } from '@cameleer/design-system'; import type { ButtonGroupItem } from '@cameleer/design-system'; +import styles from './LevelFilterBar.module.css'; function formatCount(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; @@ -28,19 +29,12 @@ export function LevelFilterBar({ activeLevels, onChange, levelCounts }: LevelFil })); return ( -
+
{activeLevels.size > 0 && (