Skip to content

Commit 9352af2

Browse files
committed
refactor(web): improve UX across entity detail and graph panels
- Change "Select fields" to "Fields shown" for clearer terminology - Change "default (all fields)" to "All fields" for consistency - Enhance empty state in GraphAlgorithmsPanel with actionable messaging - Add collapsible sections to EntityDataDisplay (Basic Information and Identifiers expanded by default, others collapsed)
1 parent f0eaff5 commit 9352af2

File tree

3 files changed

+88
-32
lines changed

3 files changed

+88
-32
lines changed

apps/web/src/components/EntityDataDisplay.tsx

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@ import {
1111
Badge,
1212
Box,
1313
Code,
14+
Collapse,
1415
Divider,
1516
Group,
1617
Paper,
1718
Stack,
1819
Text,
1920
Title,
21+
UnstyledButton,
2022
} from "@mantine/core";
2123
import {
2224
IconCalendar,
2325
IconChartBar,
2426
IconCheck,
27+
IconChevronDown,
28+
IconChevronUp,
2529
IconClipboard,
2630
IconExternalLink,
2731
IconFile,
@@ -33,6 +37,7 @@ import {
3337
IconX,
3438
} from "@tabler/icons-react";
3539
import { Link } from "@tanstack/react-router";
40+
import { useState } from "react";
3641

3742
import { ICON_SIZE } from "@/config/style-constants";
3843
import { useVersionComparison } from "@/hooks/use-version-comparison";
@@ -442,6 +447,30 @@ export const EntityDataDisplay = ({ data, title }: EntityDataDisplayProps) => {
442447
// Group and prepare data
443448
const sections = groupFields(data);
444449

450+
// Track collapsed state for each section
451+
// Basic Information and Identifiers are expanded by default, others collapsed
452+
const [collapsedSections, setCollapsedSections] = useState<Set<string>>(() => {
453+
const initial = new Set<string>();
454+
sections.forEach(section => {
455+
if (section.name !== "Basic Information" && section.name !== "Identifiers") {
456+
initial.add(section.name);
457+
}
458+
});
459+
return initial;
460+
});
461+
462+
const toggleSection = (sectionName: string) => {
463+
setCollapsedSections(prev => {
464+
const next = new Set(prev);
465+
if (next.has(sectionName)) {
466+
next.delete(sectionName);
467+
} else {
468+
next.add(sectionName);
469+
}
470+
return next;
471+
});
472+
};
473+
445474
// Version comparison for Works
446475
const workId = typeof data.id === 'string' && data.id.startsWith('W') ? data.id : undefined;
447476
const shouldShowComparison = Boolean(workId && isDataVersionSelectorVisible());
@@ -463,32 +492,50 @@ export const EntityDataDisplay = ({ data, title }: EntityDataDisplayProps) => {
463492
)}
464493

465494
{/* Render sections */}
466-
{sections.map((section) => (
467-
<Paper key={section.name} withBorder p="md" radius="md">
468-
{/* Section header */}
469-
<Group gap="sm" mb="md">
470-
{section.icon}
471-
<Text size="lg" fw={600}>{section.name}</Text>
472-
<Badge variant="light" color="gray" size="sm">
473-
{section.fields.length} {section.fields.length === 1 ? "field" : "fields"}
474-
</Badge>
475-
</Group>
476-
477-
<Divider mb="md" />
478-
479-
{/* Section fields */}
480-
<Stack gap="md">
481-
{section.fields.map((field) => (
482-
<Box key={field.key}>
483-
<Text size="sm" fw={600} c="blue.7" mb="xs">
484-
{humanizeFieldName(field.key)}
485-
</Text>
486-
{renderValueContent(field.value)}
487-
</Box>
488-
))}
489-
</Stack>
490-
</Paper>
491-
))}
495+
{sections.map((section) => {
496+
const isCollapsed = collapsedSections.has(section.name);
497+
return (
498+
<Paper key={section.name} withBorder p="md" radius="md">
499+
{/* Clickable section header */}
500+
<UnstyledButton
501+
onClick={() => toggleSection(section.name)}
502+
style={{ width: '100%' }}
503+
mb="sm"
504+
>
505+
<Group gap="sm" justify="space-between" pr="xs">
506+
<Group gap="sm">
507+
{section.icon}
508+
<Text size="lg" fw={600}>{section.name}</Text>
509+
<Badge variant="light" color="gray" size="sm">
510+
{section.fields.length} {section.fields.length === 1 ? "field" : "fields"}
511+
</Badge>
512+
</Group>
513+
{isCollapsed ? (
514+
<IconChevronDown size={ICON_SIZE.MD} color="var(--mantine-color-dimmed)" />
515+
) : (
516+
<IconChevronUp size={ICON_SIZE.MD} color="var(--mantine-color-dimmed)" />
517+
)}
518+
</Group>
519+
</UnstyledButton>
520+
521+
<Collapse in={!isCollapsed}>
522+
<Divider mb="md" />
523+
524+
{/* Section fields */}
525+
<Stack gap="md">
526+
{section.fields.map((field) => (
527+
<Box key={field.key}>
528+
<Text size="sm" fw={600} c="blue.7" mb="xs">
529+
{humanizeFieldName(field.key)}
530+
</Text>
531+
{renderValueContent(field.value)}
532+
</Box>
533+
))}
534+
</Stack>
535+
</Collapse>
536+
</Paper>
537+
);
538+
})}
492539
</Stack>
493540
);
494541
};

apps/web/src/components/algorithms/GraphAlgorithmsPanel.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,19 @@ export const GraphAlgorithmsPanel = ({
308308

309309
if (nodes.length === 0) {
310310
return (
311-
<Card style={{ border: BORDER_STYLE_GRAY_3 }} p="md">
312-
<Alert icon={<IconAlertCircle size={ICON_SIZE.MD} />} title="No Graph Data" color="gray">
313-
Add nodes and edges to the graph to run algorithms.
314-
</Alert>
311+
<Card style={{ border: BORDER_STYLE_GRAY_3 }} p="lg">
312+
<Stack align="center" gap="md" mih="200px" justify="center">
313+
<IconGraph size={ICON_SIZE.XL} color="var(--mantine-color-gray-4)" style={{ opacity: 0.5 }} />
314+
<Stack gap="xs" ta="center">
315+
<Title order={4} c="dimmed">Build Your Graph</Title>
316+
<Text size="sm" c="dimmed">
317+
Add entities from search results or entity detail pages to start analyzing connections.
318+
</Text>
319+
<Text size="xs" c="dimmed" mt="sm">
320+
Use the graph icon button on any entity to add it here.
321+
</Text>
322+
</Stack>
323+
</Stack>
315324
</Card>
316325
);
317326
}

apps/web/src/components/entity-detail/EntityDetailLayout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,12 @@ export const EntityDetailLayout = ({
403403
</Group>
404404
<Group align="flex-start" gap="sm" wrap="nowrap">
405405
<Text size="sm" fw={600} c="dimmed" miw={isMobile() ? "80px" : "100px"}>
406-
Select fields:
406+
Fields shown:
407407
</Text>
408408
<Text size="sm" c="dimmed" flex={1}>
409409
{selectParam && typeof selectParam === 'string'
410410
? selectParam
411-
: `default (all fields)`}
411+
: `All fields`}
412412
</Text>
413413
</Group>
414414
</Stack>

0 commit comments

Comments
 (0)