fix: resolve UI glitches and improve consistency
- Sidebar: make +App button more subtle (lower opacity, brightens on hover) - Sidebar: add filter chips to hide empty routes and offline/stale apps - Sidebar: hide filter chips and +App button when sidebar is collapsed - Exchange table: reorder columns to Status, Attributes, App, Route, Started, Duration; remove ExchangeId and Agent columns - Exchange detail log tab: query by exchangeId only (no applicationId required), filter by processorId when processor selected - KPI tooltips: styled tooltips with current/previous values, time period labels, percentage change, themed with DS variables - KPI tooltips: fix overflow by left-aligning first two and right-aligning last two - Exchange detail: show full datetime (YYYY-MM-DD HH:mm:ss.SSS) for start/end times - Status labels: unify to title-case (Completed, Failed, Running) across all views - Status filter buttons: match title-case labels (Completed, Warning, Failed, Running) - Create app: show full external URL using routingDomain from env config or window.location.origin fallback - Create app: add Runtime Type selector and Custom Arguments to Resources tab - Create app: add Sensitive Keys tab with agent defaults, global keys, and app-specific keys (matching admin page design) - Create app: add placeholder text to all Input fields for consistency - Update design-system to 0.1.52 (sidebar collapse toggle fix) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ import {
|
||||
} from '@cameleer/design-system';
|
||||
import type { SearchResult, SidebarTreeNode, DropdownItem, ButtonGroupItem, ExchangeStatus } from '@cameleer/design-system';
|
||||
import sidebarLogo from '@cameleer/design-system/assets/cameleer-logo.svg';
|
||||
import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X, User, Plus } from 'lucide-react';
|
||||
import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X, User, Plus, EyeOff } from 'lucide-react';
|
||||
import { AboutMeDialog } from './AboutMeDialog';
|
||||
import css from './LayoutShell.module.css';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
@@ -270,9 +270,9 @@ function StarredList({ items, onNavigate, onRemove }: { items: StarredItem[]; on
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
const STATUS_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'completed', label: 'OK', color: 'var(--success)' },
|
||||
{ value: 'warning', label: 'Warn', color: 'var(--warning)' },
|
||||
{ value: 'failed', label: 'Error', color: 'var(--error)' },
|
||||
{ value: 'completed', label: 'Completed', color: 'var(--success)' },
|
||||
{ value: 'warning', label: 'Warning', color: 'var(--warning)' },
|
||||
{ value: 'failed', label: 'Failed', color: 'var(--error)' },
|
||||
{ value: 'running', label: 'Running', color: 'var(--running)' },
|
||||
]
|
||||
|
||||
@@ -345,6 +345,15 @@ function LayoutContent() {
|
||||
|
||||
// --- Sidebar filter -----------------------------------------------
|
||||
const [filterQuery, setFilterQuery] = useState('');
|
||||
const [hideEmptyRoutes, setHideEmptyRoutes] = useState(() => readCollapsed('sidebar:hideEmptyRoutes', false));
|
||||
const [hideOfflineApps, setHideOfflineApps] = useState(() => readCollapsed('sidebar:hideOfflineApps', false));
|
||||
|
||||
const toggleHideEmptyRoutes = useCallback(() => {
|
||||
setHideEmptyRoutes((prev) => { writeCollapsed('sidebar:hideEmptyRoutes', !prev); return !prev; });
|
||||
}, []);
|
||||
const toggleHideOfflineApps = useCallback(() => {
|
||||
setHideOfflineApps((prev) => { writeCollapsed('sidebar:hideOfflineApps', !prev); return !prev; });
|
||||
}, []);
|
||||
|
||||
const setSelectedEnv = useCallback((env: string | undefined) => {
|
||||
setSelectedEnvRaw(env);
|
||||
@@ -430,10 +439,27 @@ function LayoutContent() {
|
||||
}));
|
||||
}, [catalog]);
|
||||
|
||||
// --- Apply sidebar filters -----------------------------------------
|
||||
const filteredSidebarApps: SidebarApp[] = useMemo(() => {
|
||||
let apps = sidebarApps;
|
||||
if (hideOfflineApps) {
|
||||
apps = apps.filter((a) => a.health !== 'dead' && a.health !== 'stale');
|
||||
}
|
||||
if (hideEmptyRoutes) {
|
||||
apps = apps
|
||||
.map((a) => ({
|
||||
...a,
|
||||
routes: a.routes.filter((r) => r.exchangeCount > 0),
|
||||
}))
|
||||
.filter((a) => a.exchangeCount > 0 || a.routes.length > 0);
|
||||
}
|
||||
return apps;
|
||||
}, [sidebarApps, hideOfflineApps, hideEmptyRoutes]);
|
||||
|
||||
// --- Tree nodes ---------------------------------------------------
|
||||
const appTreeNodes: SidebarTreeNode[] = useMemo(
|
||||
() => buildAppTreeNodes(sidebarApps, makeStatusDot, makeChevron, makeStopIcon, makePauseIcon),
|
||||
[sidebarApps],
|
||||
() => buildAppTreeNodes(filteredSidebarApps, makeStatusDot, makeChevron, makeStopIcon, makePauseIcon),
|
||||
[filteredSidebarApps],
|
||||
);
|
||||
|
||||
const adminTreeNodes: SidebarTreeNode[] = useMemo(
|
||||
@@ -692,9 +718,29 @@ function LayoutContent() {
|
||||
version={__APP_VERSION__}
|
||||
/>
|
||||
|
||||
{/* Sidebar filters */}
|
||||
{!sidebarCollapsed && <div className={css.sidebarFilters}>
|
||||
<button
|
||||
className={`${css.filterChip} ${hideEmptyRoutes ? css.filterChipActive : ''}`}
|
||||
onClick={toggleHideEmptyRoutes}
|
||||
title="Hide routes with 0 executions"
|
||||
>
|
||||
<span className={css.filterChipIcon}><EyeOff size={10} /></span>
|
||||
Empty routes
|
||||
</button>
|
||||
<button
|
||||
className={`${css.filterChip} ${hideOfflineApps ? css.filterChipActive : ''}`}
|
||||
onClick={toggleHideOfflineApps}
|
||||
title="Hide stale and disconnected apps"
|
||||
>
|
||||
<span className={css.filterChipIcon}><EyeOff size={10} /></span>
|
||||
Offline apps
|
||||
</button>
|
||||
</div>}
|
||||
|
||||
{/* Applications section */}
|
||||
<div className={css.appSectionWrap}>
|
||||
{canControl && (
|
||||
{canControl && !sidebarCollapsed && (
|
||||
<button
|
||||
className={css.addAppBtn}
|
||||
onClick={(e) => { e.stopPropagation(); navigate('/apps/new'); }}
|
||||
|
||||
Reference in New Issue
Block a user