refactor organism components to use .withProps() subcomponents and extract inline code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
69b17add75
commit
ca6de91a96
7 changed files with 250 additions and 96 deletions
|
|
@ -38,6 +38,49 @@ const METHOD_OPTIONS = [
|
||||||
"elicitation/create",
|
"elicitation/create",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const ContentPanel = Paper.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
p: "md",
|
||||||
|
});
|
||||||
|
|
||||||
|
const HeaderRow = Group.withProps({
|
||||||
|
justify: "space-between",
|
||||||
|
wrap: "wrap",
|
||||||
|
});
|
||||||
|
|
||||||
|
const ToolbarButton = Button.withProps({
|
||||||
|
variant: "light",
|
||||||
|
size: "sm",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyState = Text.withProps({
|
||||||
|
c: "dimmed",
|
||||||
|
ta: "center",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const CountText = Text.withProps({
|
||||||
|
size: "sm",
|
||||||
|
c: "dimmed",
|
||||||
|
});
|
||||||
|
|
||||||
|
function entryKey(entry: HistoryEntryProps): string {
|
||||||
|
return `${entry.timestamp}-${entry.method}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPinnedTitle(count: number): string {
|
||||||
|
return `Pinned Requests (${count})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPagination(displayed: number, total: number): string {
|
||||||
|
return `Showing ${displayed} of ${total} entries`;
|
||||||
|
}
|
||||||
|
|
||||||
export function HistoryScreen({
|
export function HistoryScreen({
|
||||||
entries,
|
entries,
|
||||||
pinnedEntries,
|
pinnedEntries,
|
||||||
|
|
@ -52,10 +95,10 @@ export function HistoryScreen({
|
||||||
onExport,
|
onExport,
|
||||||
}: HistoryScreenProps) {
|
}: HistoryScreenProps) {
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Paper withBorder p="md">
|
<ContentPanel>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Group justify="space-between" wrap="wrap">
|
<HeaderRow>
|
||||||
<Title order={3}>Request History</Title>
|
<Title order={3}>Request History</Title>
|
||||||
<Group>
|
<Group>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
@ -70,26 +113,17 @@ export function HistoryScreen({
|
||||||
onChange={(value) => onMethodFilterChange(value ?? "")}
|
onChange={(value) => onMethodFilterChange(value ?? "")}
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<Button variant="light" size="sm" onClick={onExport}>
|
<ToolbarButton onClick={onExport}>Export JSON</ToolbarButton>
|
||||||
Export JSON
|
<ToolbarButton onClick={onClearAll}>Clear All</ToolbarButton>
|
||||||
</Button>
|
|
||||||
<Button variant="light" size="sm" onClick={onClearAll}>
|
|
||||||
Clear All
|
|
||||||
</Button>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</HeaderRow>
|
||||||
|
|
||||||
{entries.length === 0 ? (
|
{entries.length === 0 ? (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>No request history</EmptyState>
|
||||||
No request history
|
|
||||||
</Text>
|
|
||||||
) : (
|
) : (
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
{entries.map((entry) => (
|
{entries.map((entry) => (
|
||||||
<HistoryEntry
|
<HistoryEntry key={entryKey(entry)} {...entry} />
|
||||||
key={`${entry.timestamp}-${entry.method}`}
|
|
||||||
{...entry}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
@ -97,30 +131,25 @@ export function HistoryScreen({
|
||||||
{pinnedEntries.length > 0 && (
|
{pinnedEntries.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Title order={4}>Pinned Requests ({pinnedEntries.length})</Title>
|
<Title order={4}>{formatPinnedTitle(pinnedEntries.length)}</Title>
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
{pinnedEntries.map((entry) => (
|
{pinnedEntries.map((entry) => (
|
||||||
<HistoryEntry
|
<HistoryEntry key={entryKey(entry)} {...entry} />
|
||||||
key={`${entry.timestamp}-${entry.method}`}
|
|
||||||
{...entry}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Group justify="flex-end">
|
<Group justify="flex-end">
|
||||||
<Text size="sm" c="dimmed">
|
<CountText>
|
||||||
Showing {displayedCount} of {totalCount} entries
|
{formatPagination(displayedCount, totalCount)}
|
||||||
</Text>
|
</CountText>
|
||||||
{displayedCount < totalCount && (
|
{displayedCount < totalCount && (
|
||||||
<Button variant="light" size="sm" onClick={onLoadMore}>
|
<ToolbarButton onClick={onLoadMore}>Load More</ToolbarButton>
|
||||||
Load More
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</ContentPanel>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,38 @@ export interface LoggingScreenProps {
|
||||||
onCopyAll: () => void;
|
onCopyAll: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const SidebarCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
});
|
||||||
|
|
||||||
|
const FullHeightCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
h: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const FullHeightStack = Stack.withProps({
|
||||||
|
gap: "sm",
|
||||||
|
h: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const ToolbarButton = Button.withProps({
|
||||||
|
variant: "light",
|
||||||
|
size: "sm",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyCenter = Stack.withProps({
|
||||||
|
flex: 1,
|
||||||
|
align: "center",
|
||||||
|
justify: "center",
|
||||||
|
});
|
||||||
|
|
||||||
export function LoggingScreen({
|
export function LoggingScreen({
|
||||||
controls,
|
controls,
|
||||||
entries,
|
entries,
|
||||||
|
|
@ -31,16 +63,16 @@ export function LoggingScreen({
|
||||||
onCopyAll,
|
onCopyAll,
|
||||||
}: LoggingScreenProps) {
|
}: LoggingScreenProps) {
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Grid align="stretch">
|
<Grid align="stretch">
|
||||||
<Grid.Col span={3}>
|
<Grid.Col span={3}>
|
||||||
<Card withBorder padding="lg">
|
<SidebarCard>
|
||||||
<LogControls {...controls} />
|
<LogControls {...controls} />
|
||||||
</Card>
|
</SidebarCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={9}>
|
<Grid.Col span={9}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
<Stack gap="sm" h="100%">
|
<FullHeightStack>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Title order={4}>Log Stream</Title>
|
<Title order={4}>Log Stream</Title>
|
||||||
<Group>
|
<Group>
|
||||||
|
|
@ -49,9 +81,7 @@ export function LoggingScreen({
|
||||||
checked={autoScroll}
|
checked={autoScroll}
|
||||||
onChange={onToggleAutoScroll}
|
onChange={onToggleAutoScroll}
|
||||||
/>
|
/>
|
||||||
<Button variant="light" size="sm" onClick={onCopyAll}>
|
<ToolbarButton onClick={onCopyAll}>Copy All</ToolbarButton>
|
||||||
Copy All
|
|
||||||
</Button>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
{entries.length > 0 ? (
|
{entries.length > 0 ? (
|
||||||
|
|
@ -63,14 +93,14 @@ export function LoggingScreen({
|
||||||
</Stack>
|
</Stack>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
) : (
|
) : (
|
||||||
<Stack flex={1} align="center" justify="center">
|
<EmptyCenter>
|
||||||
<Text c="dimmed">No log entries</Text>
|
<Text c="dimmed">No log entries</Text>
|
||||||
</Stack>
|
</EmptyCenter>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</FullHeightStack>
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,23 @@ export interface PromptsScreenProps {
|
||||||
onRefreshList: () => void;
|
onRefreshList: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const FullHeightCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
h: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyState = Text.withProps({
|
||||||
|
c: "dimmed",
|
||||||
|
ta: "center",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
export function PromptsScreen({
|
export function PromptsScreen({
|
||||||
promptForm,
|
promptForm,
|
||||||
messages,
|
messages,
|
||||||
|
|
@ -19,10 +36,10 @@ export function PromptsScreen({
|
||||||
onRefreshList,
|
onRefreshList,
|
||||||
}: PromptsScreenProps) {
|
}: PromptsScreenProps) {
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Grid align="stretch">
|
<Grid align="stretch">
|
||||||
<Grid.Col span={5}>
|
<Grid.Col span={5}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<ListChangedIndicator
|
<ListChangedIndicator
|
||||||
visible={listChanged}
|
visible={listChanged}
|
||||||
|
|
@ -30,20 +47,20 @@ export function PromptsScreen({
|
||||||
/>
|
/>
|
||||||
<PromptArgumentsForm {...promptForm} />
|
<PromptArgumentsForm {...promptForm} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={7}>
|
<Grid.Col span={7}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
{messages ? (
|
{messages ? (
|
||||||
<PromptMessagesDisplay {...messages} />
|
<PromptMessagesDisplay {...messages} />
|
||||||
) : (
|
) : (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>
|
||||||
Select a prompt and click Get Prompt to see messages
|
Select a prompt and click Get Prompt to see messages
|
||||||
</Text>
|
</EmptyState>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,42 @@ export interface ResourcesScreenProps {
|
||||||
onSelectResource: (uri: string) => void;
|
onSelectResource: (uri: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const FullHeightCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
h: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const DetailCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyState = Text.withProps({
|
||||||
|
c: "dimmed",
|
||||||
|
ta: "center",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const SubscriptionMeta = Text.withProps({
|
||||||
|
span: true,
|
||||||
|
c: "dimmed",
|
||||||
|
size: "xs",
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatSectionCount(label: string, count: number): string {
|
||||||
|
return `${label} (${count})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatLastUpdated(lastUpdated: string): string {
|
||||||
|
return ` — ${lastUpdated}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function ResourcesScreen({
|
export function ResourcesScreen({
|
||||||
resources,
|
resources,
|
||||||
templates,
|
templates,
|
||||||
|
|
@ -54,10 +90,10 @@ export function ResourcesScreen({
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Grid align="stretch">
|
<Grid align="stretch">
|
||||||
<Grid.Col span={4}>
|
<Grid.Col span={4}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Title order={4}>Resources</Title>
|
<Title order={4}>Resources</Title>
|
||||||
<ListChangedIndicator
|
<ListChangedIndicator
|
||||||
|
|
@ -72,7 +108,7 @@ export function ResourcesScreen({
|
||||||
<Accordion multiple defaultValue={openSections}>
|
<Accordion multiple defaultValue={openSections}>
|
||||||
<Accordion.Item value="resources">
|
<Accordion.Item value="resources">
|
||||||
<Accordion.Control disabled={filteredResources.length === 0}>
|
<Accordion.Control disabled={filteredResources.length === 0}>
|
||||||
URIs ({filteredResources.length})
|
{formatSectionCount("URIs", filteredResources.length)}
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
|
|
@ -85,7 +121,7 @@ export function ResourcesScreen({
|
||||||
|
|
||||||
<Accordion.Item value="templates">
|
<Accordion.Item value="templates">
|
||||||
<Accordion.Control disabled={templates.length === 0}>
|
<Accordion.Control disabled={templates.length === 0}>
|
||||||
Templates ({templates.length})
|
{formatSectionCount("Templates", templates.length)}
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
|
|
@ -101,7 +137,7 @@ export function ResourcesScreen({
|
||||||
|
|
||||||
<Accordion.Item value="subscriptions">
|
<Accordion.Item value="subscriptions">
|
||||||
<Accordion.Control disabled={subscriptions.length === 0}>
|
<Accordion.Control disabled={subscriptions.length === 0}>
|
||||||
Subscriptions ({subscriptions.length})
|
{formatSectionCount("Subscriptions", subscriptions.length)}
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
|
|
@ -109,10 +145,9 @@ export function ResourcesScreen({
|
||||||
<Text key={sub.name} size="sm">
|
<Text key={sub.name} size="sm">
|
||||||
{sub.name}
|
{sub.name}
|
||||||
{sub.lastUpdated && (
|
{sub.lastUpdated && (
|
||||||
<Text span c="dimmed" size="xs">
|
<SubscriptionMeta>
|
||||||
{" "}
|
{formatLastUpdated(sub.lastUpdated)}
|
||||||
— {sub.lastUpdated}
|
</SubscriptionMeta>
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
|
|
@ -121,21 +156,19 @@ export function ResourcesScreen({
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
|
||||||
<Grid.Col span={8}>
|
<Grid.Col span={8}>
|
||||||
<Card withBorder padding="lg">
|
<DetailCard>
|
||||||
{selectedResource ? (
|
{selectedResource ? (
|
||||||
<ResourcePreviewPanel {...selectedResource} />
|
<ResourcePreviewPanel {...selectedResource} />
|
||||||
) : (
|
) : (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>Select a resource to preview</EmptyState>
|
||||||
Select a resource to preview
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</DetailCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,17 @@ export interface ServerListScreenProps {
|
||||||
onImportServerJson: () => void;
|
onImportServerJson: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyState = Text.withProps({
|
||||||
|
c: "dimmed",
|
||||||
|
ta: "center",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
export function ServerListScreen({
|
export function ServerListScreen({
|
||||||
servers,
|
servers,
|
||||||
onAddManually,
|
onAddManually,
|
||||||
|
|
@ -17,7 +28,7 @@ export function ServerListScreen({
|
||||||
onImportServerJson,
|
onImportServerJson,
|
||||||
}: ServerListScreenProps) {
|
}: ServerListScreenProps) {
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Group justify="flex-end">
|
<Group justify="flex-end">
|
||||||
<AddServerMenu
|
<AddServerMenu
|
||||||
|
|
@ -28,9 +39,9 @@ export function ServerListScreen({
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
{servers.length === 0 ? (
|
{servers.length === 0 ? (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>
|
||||||
No servers configured. Add a server to get started.
|
No servers configured. Add a server to get started.
|
||||||
</Text>
|
</EmptyState>
|
||||||
) : (
|
) : (
|
||||||
<SimpleGrid
|
<SimpleGrid
|
||||||
cols={{ base: 1, md: 2 }}
|
cols={{ base: 1, md: 2 }}
|
||||||
|
|
@ -43,6 +54,6 @@ export function ServerListScreen({
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,25 @@ export interface TasksScreenProps {
|
||||||
onClearHistory: () => void;
|
onClearHistory: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const ContentPanel = Paper.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
p: "md",
|
||||||
|
});
|
||||||
|
|
||||||
|
const CompactButton = Button.withProps({
|
||||||
|
variant: "light",
|
||||||
|
size: "xs",
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatSectionTitle(label: string, count: number): string {
|
||||||
|
return `${label} (${count})`;
|
||||||
|
}
|
||||||
|
|
||||||
export function TasksScreen({
|
export function TasksScreen({
|
||||||
activeTasks,
|
activeTasks,
|
||||||
completedTasks,
|
completedTasks,
|
||||||
|
|
@ -24,14 +43,14 @@ export function TasksScreen({
|
||||||
onClearHistory,
|
onClearHistory,
|
||||||
}: TasksScreenProps) {
|
}: TasksScreenProps) {
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Paper withBorder p="md">
|
<ContentPanel>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Title order={4}>Active Tasks ({activeTasks.length})</Title>
|
<Title order={4}>
|
||||||
<Button variant="light" size="xs" onClick={onRefresh}>
|
{formatSectionTitle("Active Tasks", activeTasks.length)}
|
||||||
Refresh Tasks
|
</Title>
|
||||||
</Button>
|
<CompactButton onClick={onRefresh}>Refresh Tasks</CompactButton>
|
||||||
</Group>
|
</Group>
|
||||||
{activeTasks.length === 0 ? (
|
{activeTasks.length === 0 ? (
|
||||||
<Text c="dimmed">No active tasks</Text>
|
<Text c="dimmed">No active tasks</Text>
|
||||||
|
|
@ -44,11 +63,13 @@ export function TasksScreen({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Title order={4}>Completed Tasks ({completedTasks.length})</Title>
|
<Title order={4}>
|
||||||
|
{formatSectionTitle("Completed Tasks", completedTasks.length)}
|
||||||
|
</Title>
|
||||||
{completedTasks.length > 0 && (
|
{completedTasks.length > 0 && (
|
||||||
<Button variant="light" size="xs" onClick={onClearHistory}>
|
<CompactButton onClick={onClearHistory}>
|
||||||
Clear History
|
Clear History
|
||||||
</Button>
|
</CompactButton>
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
{completedTasks.length === 0 ? (
|
{completedTasks.length === 0 ? (
|
||||||
|
|
@ -61,7 +82,7 @@ export function TasksScreen({
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</ContentPanel>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,23 @@ export interface ToolsScreenProps {
|
||||||
onSelectTool: (name: string) => void;
|
onSelectTool: (name: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageContainer = Container.withProps({
|
||||||
|
size: "xl",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
|
const FullHeightCard = Card.withProps({
|
||||||
|
withBorder: true,
|
||||||
|
padding: "lg",
|
||||||
|
h: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const EmptyState = Text.withProps({
|
||||||
|
c: "dimmed",
|
||||||
|
ta: "center",
|
||||||
|
py: "xl",
|
||||||
|
});
|
||||||
|
|
||||||
export function ToolsScreen({
|
export function ToolsScreen({
|
||||||
tools,
|
tools,
|
||||||
selectedTool,
|
selectedTool,
|
||||||
|
|
@ -43,10 +60,10 @@ export function ToolsScreen({
|
||||||
: tools;
|
: tools;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container size="xl" py="xl">
|
<PageContainer>
|
||||||
<Grid align="stretch">
|
<Grid align="stretch">
|
||||||
<Grid.Col span={3}>
|
<Grid.Col span={3}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Title order={4}>Tools</Title>
|
<Title order={4}>Tools</Title>
|
||||||
<ListChangedIndicator
|
<ListChangedIndicator
|
||||||
|
|
@ -66,33 +83,29 @@ export function ToolsScreen({
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
|
||||||
<Grid.Col span={5}>
|
<Grid.Col span={5}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
{selectedTool ? (
|
{selectedTool ? (
|
||||||
<ToolDetailPanel {...selectedTool} />
|
<ToolDetailPanel {...selectedTool} />
|
||||||
) : (
|
) : (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>Select a tool to view details</EmptyState>
|
||||||
Select a tool to view details
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
|
||||||
<Grid.Col span={4}>
|
<Grid.Col span={4}>
|
||||||
<Card withBorder padding="lg" h="100%">
|
<FullHeightCard>
|
||||||
{result ? (
|
{result ? (
|
||||||
<ResultPanel {...result} />
|
<ResultPanel {...result} />
|
||||||
) : (
|
) : (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<EmptyState>Results will appear here</EmptyState>
|
||||||
Results will appear here
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</FullHeightCard>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue