@elevasis/ui 2.22.0 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/index.d.ts +2915 -0
- package/dist/app/index.js +5 -4
- package/dist/{chunk-3HEUGBOT.js → chunk-2WZ635SS.js} +2 -2
- package/dist/{chunk-GJ7EIABJ.js → chunk-4NWNS7TX.js} +1 -1
- package/dist/{chunk-LKVBEE63.js → chunk-FUEXGRFR.js} +2 -2
- package/dist/{chunk-6IA2OMAE.js → chunk-HC2KV6BU.js} +9 -0
- package/dist/{chunk-IBUYJXA3.js → chunk-KCJ6VATY.js} +1133 -578
- package/dist/{chunk-WWJ6S2HQ.js → chunk-KLFIJDTD.js} +1 -1
- package/dist/{chunk-COG4ABRI.js → chunk-M2HWJY6O.js} +704 -375
- package/dist/{chunk-LVJGPE6H.js → chunk-MTR6AN2C.js} +3 -12
- package/dist/chunk-OWHQ65EQ.js +211 -0
- package/dist/{chunk-XOTJNW4Q.js → chunk-QIW6OCEI.js} +18 -1
- package/dist/{chunk-B4FHWKEF.js → chunk-QULLZ5PE.js} +193 -10
- package/dist/{chunk-QZJM3RYI.js → chunk-SNHGSCKH.js} +1 -1
- package/dist/{chunk-LVUCBY7X.js → chunk-UDJE54WN.js} +85 -3
- package/dist/{chunk-IOTLB6ND.js → chunk-VGNAV3TH.js} +406 -195
- package/dist/{chunk-BSZRKBAW.js → chunk-YBZT7MJR.js} +3 -3
- package/dist/{chunk-SQ5JGELM.js → chunk-ZDKQNQ4X.js} +19 -1
- package/dist/components/index.d.ts +500 -466
- package/dist/components/index.js +75 -32
- package/dist/components/navigation/index.js +2 -2
- package/dist/features/auth/index.d.ts +472 -389
- package/dist/features/crm/index.d.ts +468 -391
- package/dist/features/crm/index.js +8 -8
- package/dist/features/dashboard/index.js +8 -8
- package/dist/features/delivery/index.d.ts +466 -383
- package/dist/features/delivery/index.js +8 -8
- package/dist/features/lead-gen/index.d.ts +213 -65
- package/dist/features/lead-gen/index.js +9 -8
- package/dist/features/monitoring/index.js +9 -9
- package/dist/features/monitoring/requests/index.js +7 -7
- package/dist/features/operations/index.js +11 -10
- package/dist/features/settings/index.d.ts +472 -389
- package/dist/features/settings/index.js +9 -9
- package/dist/hooks/delivery/index.d.ts +466 -383
- package/dist/hooks/index.d.ts +967 -744
- package/dist/hooks/index.js +7 -7
- package/dist/hooks/published.d.ts +967 -744
- package/dist/hooks/published.js +7 -7
- package/dist/index.d.ts +1360 -1069
- package/dist/index.js +8 -8
- package/dist/initialization/index.d.ts +472 -389
- package/dist/organization/index.d.ts +11 -1
- package/dist/organization/index.js +2 -2
- package/dist/profile/index.d.ts +472 -389
- package/dist/provider/index.d.ts +3132 -169
- package/dist/provider/index.js +6 -6
- package/dist/provider/published.d.ts +3098 -168
- package/dist/provider/published.js +3 -3
- package/dist/supabase/index.d.ts +577 -413
- package/dist/test-utils/index.d.ts +21 -1
- package/dist/test-utils/index.js +13 -4
- package/dist/theme/index.js +2 -2
- package/dist/types/index.d.ts +472 -389
- package/package.json +2 -2
- package/src/test-utils/README.md +2 -0
- /package/dist/{chunk-ZBCTB5CA.js → chunk-EIOJNUPL.js} +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { ChatHeader, ChatSidebar } from './chunk-ROSMICXG.js';
|
|
2
2
|
import { SubshellSidebarLoader, SubshellLoader } from './chunk-3JCMO7SD.js';
|
|
3
|
-
import { BaseNode, useGraphTheme, BaseEdge, FormFieldRenderer, ExecutionStats, UnifiedWorkflowGraph, WorkflowExecutionTimeline, AgentExecutionVisualizer, AgentExecutionTimeline, GraphBackground, GraphFitViewButton, GraphFitViewHandler } from './chunk-
|
|
4
|
-
import {
|
|
3
|
+
import { BaseNode, useGraphTheme, BaseEdge, FormFieldRenderer, ExecutionStats, UnifiedWorkflowGraph, WorkflowExecutionTimeline, AgentExecutionVisualizer, AgentExecutionTimeline, GraphBackground, GraphFitViewButton, GraphFitViewHandler } from './chunk-FUEXGRFR.js';
|
|
4
|
+
import { LabelSchema, ColorTokenSchema, IconNameSchema, PathSchema, DescriptionSchema, DisplayMetadataSchema, ModelIdSchema, ReferenceIdsSchema, OrganizationModelSalesSchema } from './chunk-OWHQ65EQ.js';
|
|
5
|
+
import { ResourceHealthPanel } from './chunk-4NWNS7TX.js';
|
|
5
6
|
import { useCyberColors, CyberDonut } from './chunk-TSSKOQBX.js';
|
|
6
7
|
import { AppShellLoader } from './chunk-M25JL54Z.js';
|
|
7
8
|
import { PageContainer } from './chunk-BZZCNLT6.js';
|
|
8
9
|
import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
|
|
9
10
|
import { CustomModal, ConfirmationModal } from './chunk-KVJ3LFH2.js';
|
|
10
11
|
import { getResourceStatusColor, useTimelineData, useAgentIterationData, getStatusIcon } from './chunk-E4WQGJNS.js';
|
|
11
|
-
import { useErrorDetail, useExecution, useArchivedLogs, useDeleteExecution, useRetryExecution, useCancelExecution, useCommandQueueTotals, useStatusFilter, useResourceSearch, useResourcesDomainFilters, usePaginationState, useResources, useRecentExecutionsByResource, filterByDomainFilters, collectResourceFilterFacets, useExecuteAsync, useResourceDefinition, isSessionCapable, useDeleteTask, useCommandQueue, useSubmitAction, useCommandViewData, useCommandViewStats, useCommandViewStore, useResourceExecutions, useCheckpointTasks, COMMAND_VIEW_VISUALIZATION_MODES, useExecutionPanelState, useDeleteSession, useCreateSession, useSessions, useSessionExecutions, useSession, useBulkDeleteExecutions, getCommandViewGraphPositions } from './chunk-
|
|
12
|
+
import { useErrorDetail, useExecution, useArchivedLogs, useDeleteExecution, useRetryExecution, useCancelExecution, useCommandQueueTotals, useStatusFilter, useResourceSearch, useResourcesDomainFilters, usePaginationState, useResources, useRecentExecutionsByResource, filterByDomainFilters, collectResourceFilterFacets, useExecuteAsync, useResourceDefinition, isSessionCapable, useDeleteTask, useCommandQueue, useSubmitAction, useCommandViewData, useCommandViewStats, useCommandViewStore, useResourceExecutions, useCheckpointTasks, COMMAND_VIEW_VISUALIZATION_MODES, useExecutionPanelState, useDeleteSession, useCreateSession, useSessions, useSessionExecutions, useSession, useBulkDeleteExecutions, getCommandViewGraphPositions } from './chunk-QULLZ5PE.js';
|
|
12
13
|
import { showApiErrorNotification, showSuccessNotification } from './chunk-Z6FAH4XV.js';
|
|
13
14
|
import { useGraphHighlighting, calculateGraphHeight, Graph_module_css_default, GRAPH_CONSTANTS } from './chunk-22UVE3RA.js';
|
|
14
15
|
import { useMergedExecution } from './chunk-3ZMAGTWF.js';
|
|
@@ -25,7 +26,7 @@ import { ResourceStatusColors, toWorkflowLogMessages } from './chunk-KRWALB24.js
|
|
|
25
26
|
import { useInitialization } from './chunk-DK2HVHCY.js';
|
|
26
27
|
import { useOrganization } from './chunk-DD3CCMCZ.js';
|
|
27
28
|
import { z } from 'zod';
|
|
28
|
-
import { Stack, Group, Text, Badge, Title, Textarea, Alert, Button, ActionIcon, Collapse, Card, ThemeIcon, SimpleGrid, Divider, Paper, Space, CopyButton, Center, Tooltip, Code, Menu, useMantineTheme, UnstyledButton, Select, RangeSlider, Box, Progress, Tabs, Pagination, TextInput, Modal, LoadingOverlay, Loader, SegmentedControl, ScrollArea, Checkbox, MultiSelect, Switch } from '@mantine/core';
|
|
29
|
+
import { Stack, Group, Text, Badge, Title, Textarea, Alert, Button, ActionIcon, Collapse, Card, ThemeIcon, SimpleGrid, Divider, Paper, Space, CopyButton, Center, Tooltip, Code, Menu, useMantineTheme, UnstyledButton, Select, RangeSlider, Box, Progress, Tabs, Pagination, TextInput, Modal, LoadingOverlay, Loader, SegmentedControl, ScrollArea, Checkbox, NumberInput, MultiSelect, Switch } from '@mantine/core';
|
|
29
30
|
import { IconBrain, IconFileText, IconMail, IconSend, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconCode, IconAlertCircle, IconChevronRight, IconTool, IconSettings, IconCpu, IconClockHour4, IconVersions, IconPlayerPlay, IconNetwork, IconSitemap, IconCopy, IconPlayerStop, IconReload, IconTrash, IconTerminal2, IconBug, IconChevronDown, IconMessage, IconArrowLeft, IconRobot, IconGitBranch, IconDotsVertical, IconFilter, IconCircleCheck, IconCategory, IconDatabase, IconApps, IconRoute, IconAdjustmentsHorizontal, IconSearch, IconCircleX, IconCircleDashed, IconExternalLink, IconFolders, IconBraces, IconBolt, IconTopologyStar3, IconInfoCircle, IconPlus, IconLayoutSidebarRightExpand, IconNote, IconArchive, IconDownload, IconTimeline, IconActivityHeartbeat, IconClockPause, IconArrowsMaximize, IconShare2, IconHistory } from '@tabler/icons-react';
|
|
30
31
|
import { useForm } from '@mantine/form';
|
|
31
32
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -40,51 +41,6 @@ import cytoscape from 'cytoscape';
|
|
|
40
41
|
import { create } from 'zustand';
|
|
41
42
|
import { formatDistanceToNow } from 'date-fns';
|
|
42
43
|
|
|
43
|
-
var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
|
|
44
|
-
var LabelSchema = z.string().trim().min(1).max(120);
|
|
45
|
-
var DescriptionSchema = z.string().trim().min(1).max(2e3);
|
|
46
|
-
var ColorTokenSchema = z.string().trim().min(1).max(50);
|
|
47
|
-
var IconNameSchema = z.string().trim().min(1).max(80);
|
|
48
|
-
var PathSchema = z.string().trim().startsWith("/").max(300);
|
|
49
|
-
var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
|
|
50
|
-
var DisplayMetadataSchema = z.object({
|
|
51
|
-
label: LabelSchema,
|
|
52
|
-
description: DescriptionSchema.optional(),
|
|
53
|
-
color: ColorTokenSchema.optional(),
|
|
54
|
-
icon: IconNameSchema.optional()
|
|
55
|
-
});
|
|
56
|
-
var TechStackEntrySchema = z.object({
|
|
57
|
-
/** Name of the external platform (e.g. "HubSpot", "Stripe", "Notion"). */
|
|
58
|
-
platform: z.string().trim().min(1).max(200),
|
|
59
|
-
/** Free-form description of what this integration is used for. */
|
|
60
|
-
purpose: z.string().trim().min(1).max(500),
|
|
61
|
-
/**
|
|
62
|
-
* Health of the credential backing this integration.
|
|
63
|
-
* - configured: credential present and valid
|
|
64
|
-
* - pending: not yet set up
|
|
65
|
-
* - expired: credential existed but has lapsed
|
|
66
|
-
* - missing: expected but not present
|
|
67
|
-
*/
|
|
68
|
-
credentialStatus: z.enum(["configured", "pending", "expired", "missing"]),
|
|
69
|
-
/**
|
|
70
|
-
* Whether this integration is the primary system of record for its domain
|
|
71
|
-
* (e.g. HubSpot is SoR for contacts). Defaults to false.
|
|
72
|
-
*/
|
|
73
|
-
isSystemOfRecord: z.boolean().default(false)
|
|
74
|
-
});
|
|
75
|
-
DisplayMetadataSchema.extend({
|
|
76
|
-
id: ModelIdSchema,
|
|
77
|
-
resourceId: z.string().trim().min(1).max(255),
|
|
78
|
-
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
79
|
-
featureIds: ReferenceIdsSchema,
|
|
80
|
-
entityIds: ReferenceIdsSchema,
|
|
81
|
-
surfaceIds: ReferenceIdsSchema,
|
|
82
|
-
capabilityIds: ReferenceIdsSchema,
|
|
83
|
-
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
84
|
-
techStack: TechStackEntrySchema.optional()
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// ../core/src/organization-model/domains/features.ts
|
|
88
44
|
var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
|
|
89
45
|
z.string().trim().min(1).max(200).regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node references must use kind:dotted-path");
|
|
90
46
|
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
|
|
@@ -110,26 +66,6 @@ var OrganizationModelBrandingSchema = z.object({
|
|
|
110
66
|
dark: z.string().trim().min(1).max(2048).optional()
|
|
111
67
|
}).default({})
|
|
112
68
|
});
|
|
113
|
-
var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
|
|
114
|
-
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
115
|
-
id: ModelIdSchema,
|
|
116
|
-
order: z.number().int().min(0),
|
|
117
|
-
semanticClass: SalesStageSemanticClassSchema,
|
|
118
|
-
surfaceIds: ReferenceIdsSchema,
|
|
119
|
-
resourceIds: ReferenceIdsSchema
|
|
120
|
-
});
|
|
121
|
-
var SalesPipelineSchema = z.object({
|
|
122
|
-
id: ModelIdSchema,
|
|
123
|
-
label: z.string().trim().min(1).max(120),
|
|
124
|
-
description: DescriptionSchema.optional(),
|
|
125
|
-
entityId: ModelIdSchema,
|
|
126
|
-
stages: z.array(SalesStageSchema).min(1)
|
|
127
|
-
});
|
|
128
|
-
var OrganizationModelSalesSchema = z.object({
|
|
129
|
-
entityId: ModelIdSchema,
|
|
130
|
-
defaultPipelineId: ModelIdSchema,
|
|
131
|
-
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
132
|
-
});
|
|
133
69
|
var ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
|
|
134
70
|
id: ModelIdSchema,
|
|
135
71
|
order: z.number().int().min(0)
|
|
@@ -4684,7 +4620,7 @@ function titleCase2(value) {
|
|
|
4684
4620
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
4685
4621
|
}
|
|
4686
4622
|
function MetricCard({ metric }) {
|
|
4687
|
-
return /* @__PURE__ */ jsx(
|
|
4623
|
+
return /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
4688
4624
|
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: metric.label }),
|
|
4689
4625
|
/* @__PURE__ */ jsx(Text, { size: "lg", fw: 800, children: metric.value }),
|
|
4690
4626
|
metric.hint ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: metric.hint }) : null
|
|
@@ -4769,6 +4705,7 @@ function OrganizationGraphDetailPanel({
|
|
|
4769
4705
|
selectedElement,
|
|
4770
4706
|
supplementalSummary,
|
|
4771
4707
|
followUpSections,
|
|
4708
|
+
expandAroundPanel,
|
|
4772
4709
|
onClearSelection,
|
|
4773
4710
|
className
|
|
4774
4711
|
}) {
|
|
@@ -4806,6 +4743,7 @@ function OrganizationGraphDetailPanel({
|
|
|
4806
4743
|
onClearSelection ? /* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: onClearSelection, children: "Clear" }) : null
|
|
4807
4744
|
] }),
|
|
4808
4745
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, md: 4 }, spacing: "sm", children: state.metrics.map((metric) => /* @__PURE__ */ jsx(MetricCard, { metric }, metric.label)) }),
|
|
4746
|
+
expandAroundPanel,
|
|
4809
4747
|
supplementalSummary && (supplementalSummary.metrics.length > 0 || supplementalSummary.metadata.length > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4810
4748
|
/* @__PURE__ */ jsx(
|
|
4811
4749
|
Divider,
|
|
@@ -5833,184 +5771,895 @@ function buildCommandViewDrillDownSections({
|
|
|
5833
5771
|
}
|
|
5834
5772
|
return sections;
|
|
5835
5773
|
}
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
hotspots,
|
|
5846
|
-
visibleResources,
|
|
5847
|
-
hiddenResources = 0,
|
|
5848
|
-
resourcesHidden,
|
|
5849
|
-
selectedLabel,
|
|
5850
|
-
onFocusHotspot,
|
|
5851
|
-
onResourcesHiddenChange,
|
|
5852
|
-
onResetFocus
|
|
5853
|
-
}) {
|
|
5854
|
-
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
5855
|
-
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5856
|
-
/* @__PURE__ */ jsx(IconActivityHeartbeat, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5857
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.successRate == null ? "N/A" : `${Math.round(overview.successRate)}%` }),
|
|
5858
|
-
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
5859
|
-
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", children: overview?.successCount ?? 0 }),
|
|
5860
|
-
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "red", size: "xs", children: overview?.failureCount ?? 0 }),
|
|
5861
|
-
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "yellow", size: "xs", children: overview?.warningCount ?? 0 })
|
|
5862
|
-
] }),
|
|
5863
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, style: { flexShrink: 1, minWidth: 0 }, children: overview ? `${overview.totalRuns} runs / ${overview.trackedResources} resources` : "" })
|
|
5864
|
-
] }),
|
|
5865
|
-
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5866
|
-
/* @__PURE__ */ jsx(IconAlertTriangle, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5867
|
-
hotspots.length > 0 ? /* @__PURE__ */ jsx(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0, overflow: "hidden" }, children: hotspots.map((hotspot) => /* @__PURE__ */ jsx(Group, { gap: 4, wrap: "nowrap", children: /* @__PURE__ */ jsx(
|
|
5868
|
-
Badge,
|
|
5869
|
-
{
|
|
5870
|
-
variant: "light",
|
|
5871
|
-
color: "red",
|
|
5872
|
-
size: "xs",
|
|
5873
|
-
style: { cursor: "pointer", flexShrink: 0 },
|
|
5874
|
-
onClick: () => onFocusHotspot(hotspot.resourceId),
|
|
5875
|
-
children: hotspot.label
|
|
5876
|
-
}
|
|
5877
|
-
) }, hotspot.nodeId)) }) : /* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 10 }), children: "No hotspots" })
|
|
5878
|
-
] }),
|
|
5879
|
-
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5880
|
-
/* @__PURE__ */ jsx(IconClockPause, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5881
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.pendingApprovals ?? 0 }),
|
|
5882
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", truncate: true, children: [
|
|
5883
|
-
"pending / ",
|
|
5884
|
-
overview?.activeHumanCheckpoints ?? 0,
|
|
5885
|
-
" queues"
|
|
5886
|
-
] })
|
|
5887
|
-
] }),
|
|
5888
|
-
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5889
|
-
/* @__PURE__ */ jsx(IconTopologyStar3, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5890
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, truncate: true, style: { minWidth: 0 }, children: selectedLabel ?? `${visibleResources} visible / ${hiddenResources} hidden` }),
|
|
5891
|
-
/* @__PURE__ */ jsx(
|
|
5892
|
-
Button,
|
|
5893
|
-
{
|
|
5894
|
-
size: "compact-xs",
|
|
5895
|
-
variant: resourcesHidden ? "light" : "subtle",
|
|
5896
|
-
onClick: () => onResourcesHiddenChange(!resourcesHidden),
|
|
5897
|
-
style: { flexShrink: 0 },
|
|
5898
|
-
children: resourcesHidden ? "Show resources" : "Hide resources"
|
|
5899
|
-
}
|
|
5900
|
-
),
|
|
5901
|
-
/* @__PURE__ */ jsx(Button, { size: "compact-xs", variant: "subtle", onClick: onResetFocus, style: { flexShrink: 0 }, children: "Reset" })
|
|
5902
|
-
] })
|
|
5903
|
-
] });
|
|
5904
|
-
}
|
|
5905
|
-
var FILTER_STATE_ICONS2 = {
|
|
5906
|
-
neutral: IconCircleDashed,
|
|
5907
|
-
include: IconCircleCheck,
|
|
5908
|
-
exclude: IconCircleX
|
|
5909
|
-
};
|
|
5910
|
-
var FILTER_STATE_COLORS2 = {
|
|
5911
|
-
neutral: "var(--color-text-dimmed)",
|
|
5912
|
-
include: "var(--mantine-color-green-6)",
|
|
5913
|
-
exclude: "var(--mantine-color-red-6)"
|
|
5774
|
+
|
|
5775
|
+
// src/features/operations/organization-graph/path-tracing/trace.ts
|
|
5776
|
+
var NODE_KIND_ORDER = {
|
|
5777
|
+
organization: 0,
|
|
5778
|
+
feature: 1,
|
|
5779
|
+
surface: 2,
|
|
5780
|
+
capability: 3,
|
|
5781
|
+
entity: 4,
|
|
5782
|
+
resource: 5
|
|
5914
5783
|
};
|
|
5915
|
-
var
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5784
|
+
var NODE_KIND_LABEL = {
|
|
5785
|
+
organization: "Organization",
|
|
5786
|
+
feature: "Feature",
|
|
5787
|
+
surface: "Surface",
|
|
5788
|
+
capability: "Capability",
|
|
5789
|
+
entity: "Entity",
|
|
5790
|
+
resource: "Resource"
|
|
5919
5791
|
};
|
|
5920
|
-
function
|
|
5921
|
-
|
|
5922
|
-
|
|
5792
|
+
function getNodeLabel(node) {
|
|
5793
|
+
return node.label || node.sourceId || node.id;
|
|
5794
|
+
}
|
|
5795
|
+
function compareTraceNodes(a, b) {
|
|
5796
|
+
const kindDelta = NODE_KIND_ORDER[a.kind] - NODE_KIND_ORDER[b.kind];
|
|
5797
|
+
if (kindDelta !== 0) {
|
|
5798
|
+
return kindDelta;
|
|
5923
5799
|
}
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
...commandViewData.externalResources,
|
|
5930
|
-
...commandViewData.humanCheckpoints
|
|
5931
|
-
];
|
|
5800
|
+
const labelDelta = getNodeLabel(a).localeCompare(getNodeLabel(b));
|
|
5801
|
+
if (labelDelta !== 0) {
|
|
5802
|
+
return labelDelta;
|
|
5803
|
+
}
|
|
5804
|
+
return a.id.localeCompare(b.id);
|
|
5932
5805
|
}
|
|
5933
|
-
function
|
|
5934
|
-
if (
|
|
5935
|
-
|
|
5936
|
-
|
|
5806
|
+
function buildMissingNodeMessage(selection, missingNodeIds) {
|
|
5807
|
+
if (missingNodeIds.length === 0) {
|
|
5808
|
+
return "The selected trace is not available.";
|
|
5809
|
+
}
|
|
5810
|
+
if (missingNodeIds.length === 1) {
|
|
5811
|
+
const missingId = missingNodeIds[0];
|
|
5812
|
+
return `Graph node "${missingId}" is not available.`;
|
|
5813
|
+
}
|
|
5814
|
+
return `Graph nodes "${selection.sourceId}" and "${selection.targetId}" are not available.`;
|
|
5937
5815
|
}
|
|
5938
|
-
function
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
const resourceFacets = collectResourceFilterFacets(getCommandViewResources(commandViewData));
|
|
5957
|
-
const Section = ({ children }) => layout === "stack" ? /* @__PURE__ */ jsx(
|
|
5958
|
-
Stack,
|
|
5959
|
-
{
|
|
5960
|
-
gap: "sm",
|
|
5961
|
-
pb: "sm",
|
|
5962
|
-
style: {
|
|
5963
|
-
borderBottom: "1px solid var(--color-border)"
|
|
5964
|
-
},
|
|
5965
|
-
children
|
|
5816
|
+
function buildPathNotFoundMessage(source, target) {
|
|
5817
|
+
return `No directed path found from "${source.label}" to "${target.label}".`;
|
|
5818
|
+
}
|
|
5819
|
+
function buildOrganizationGraphTraceIndex(graph) {
|
|
5820
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
5821
|
+
const edgesById = /* @__PURE__ */ new Map();
|
|
5822
|
+
const outgoingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
5823
|
+
const incomingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
5824
|
+
for (const node of graph.nodes) {
|
|
5825
|
+
nodesById.set(node.id, node);
|
|
5826
|
+
outgoingEdgesByNodeId.set(node.id, []);
|
|
5827
|
+
incomingEdgesByNodeId.set(node.id, []);
|
|
5828
|
+
}
|
|
5829
|
+
for (const edge of graph.edges) {
|
|
5830
|
+
edgesById.set(edge.id, edge);
|
|
5831
|
+
const outgoingEdges = outgoingEdgesByNodeId.get(edge.sourceId);
|
|
5832
|
+
if (outgoingEdges) {
|
|
5833
|
+
outgoingEdges.push(edge);
|
|
5966
5834
|
}
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
onChangeFilters({
|
|
5971
|
-
...filters,
|
|
5972
|
-
domainFilters: {
|
|
5973
|
-
...filters.domainFilters,
|
|
5974
|
-
[domainId]: nextDomainFilterState(current)
|
|
5975
|
-
}
|
|
5976
|
-
});
|
|
5977
|
-
};
|
|
5978
|
-
const handleResourceVisibilityAction = () => {
|
|
5979
|
-
if (resourcesHidden) {
|
|
5980
|
-
onRevealResources();
|
|
5981
|
-
return;
|
|
5835
|
+
const incomingEdges = incomingEdgesByNodeId.get(edge.targetId);
|
|
5836
|
+
if (incomingEdges) {
|
|
5837
|
+
incomingEdges.push(edge);
|
|
5982
5838
|
}
|
|
5983
|
-
|
|
5839
|
+
}
|
|
5840
|
+
return {
|
|
5841
|
+
nodesById,
|
|
5842
|
+
edgesById,
|
|
5843
|
+
outgoingEdgesByNodeId,
|
|
5844
|
+
incomingEdgesByNodeId
|
|
5984
5845
|
};
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
5846
|
+
}
|
|
5847
|
+
function getOrganizationGraphTraceNodeKindLabel(kind) {
|
|
5848
|
+
return NODE_KIND_LABEL[kind];
|
|
5849
|
+
}
|
|
5850
|
+
function formatOrganizationGraphTraceNodeOptionLabel(option) {
|
|
5851
|
+
return `${option.label} \xB7 ${getOrganizationGraphTraceNodeKindLabel(option.kind)}`;
|
|
5852
|
+
}
|
|
5853
|
+
function getOrganizationGraphTraceNodeOptions(graph) {
|
|
5854
|
+
return [...graph.nodes].sort(compareTraceNodes).map((node) => ({
|
|
5855
|
+
id: node.id,
|
|
5856
|
+
label: getNodeLabel(node),
|
|
5857
|
+
kind: node.kind,
|
|
5858
|
+
sourceId: node.sourceId,
|
|
5859
|
+
description: node.description,
|
|
5860
|
+
enabled: node.enabled
|
|
5861
|
+
}));
|
|
5862
|
+
}
|
|
5863
|
+
function resolveOrganizationGraphPathTrace(graph, selection) {
|
|
5864
|
+
const index = buildOrganizationGraphTraceIndex(graph);
|
|
5865
|
+
const source = selection.sourceId ? index.nodesById.get(selection.sourceId) ?? null : null;
|
|
5866
|
+
const target = selection.targetId ? index.nodesById.get(selection.targetId) ?? null : null;
|
|
5867
|
+
const missingNodeIds = [
|
|
5868
|
+
selection.sourceId && !source ? selection.sourceId : null,
|
|
5869
|
+
selection.targetId && !target ? selection.targetId : null
|
|
5870
|
+
].filter((value) => Boolean(value));
|
|
5871
|
+
if (!selection.sourceId && !selection.targetId) {
|
|
5872
|
+
return {
|
|
5873
|
+
status: "idle",
|
|
5874
|
+
selection,
|
|
5875
|
+
source,
|
|
5876
|
+
target,
|
|
5877
|
+
missingNodeIds: [],
|
|
5878
|
+
pathNodes: [],
|
|
5879
|
+
pathEdges: [],
|
|
5880
|
+
highlightNodeIds: [],
|
|
5881
|
+
highlightEdgeIds: [],
|
|
5882
|
+
distance: 0,
|
|
5883
|
+
message: "Select a source and target to trace a path."
|
|
5884
|
+
};
|
|
5885
|
+
}
|
|
5886
|
+
if (!selection.sourceId || !selection.targetId) {
|
|
5887
|
+
return {
|
|
5888
|
+
status: "incomplete",
|
|
5889
|
+
selection,
|
|
5890
|
+
source,
|
|
5891
|
+
target,
|
|
5892
|
+
missingNodeIds,
|
|
5893
|
+
pathNodes: [],
|
|
5894
|
+
pathEdges: [],
|
|
5895
|
+
highlightNodeIds: [],
|
|
5896
|
+
highlightEdgeIds: [],
|
|
5897
|
+
distance: 0,
|
|
5898
|
+
message: "Select both a source and a target to resolve a path."
|
|
5899
|
+
};
|
|
5900
|
+
}
|
|
5901
|
+
if (missingNodeIds.length > 0 || !source || !target) {
|
|
5902
|
+
return {
|
|
5903
|
+
status: "missing-node",
|
|
5904
|
+
selection,
|
|
5905
|
+
source,
|
|
5906
|
+
target,
|
|
5907
|
+
missingNodeIds,
|
|
5908
|
+
pathNodes: [],
|
|
5909
|
+
pathEdges: [],
|
|
5910
|
+
highlightNodeIds: [],
|
|
5911
|
+
highlightEdgeIds: [],
|
|
5912
|
+
distance: 0,
|
|
5913
|
+
message: buildMissingNodeMessage(selection, missingNodeIds)
|
|
5914
|
+
};
|
|
5915
|
+
}
|
|
5916
|
+
if (source.id === target.id) {
|
|
5917
|
+
return {
|
|
5918
|
+
status: "found",
|
|
5919
|
+
selection,
|
|
5920
|
+
source,
|
|
5921
|
+
target,
|
|
5922
|
+
missingNodeIds: [],
|
|
5923
|
+
pathNodes: [source],
|
|
5924
|
+
pathEdges: [],
|
|
5925
|
+
highlightNodeIds: [source.id],
|
|
5926
|
+
highlightEdgeIds: [],
|
|
5927
|
+
distance: 0,
|
|
5928
|
+
message: `Source and target already point to "${source.label}".`
|
|
5929
|
+
};
|
|
5930
|
+
}
|
|
5931
|
+
const visitedNodeIds = /* @__PURE__ */ new Set([source.id]);
|
|
5932
|
+
const predecessorByNodeId = /* @__PURE__ */ new Map();
|
|
5933
|
+
const queue = [source.id];
|
|
5934
|
+
while (queue.length > 0) {
|
|
5935
|
+
const currentNodeId = queue.shift();
|
|
5936
|
+
if (!currentNodeId) {
|
|
5937
|
+
continue;
|
|
5938
|
+
}
|
|
5939
|
+
const outgoingEdges = index.outgoingEdgesByNodeId.get(currentNodeId) ?? [];
|
|
5940
|
+
for (const edge of outgoingEdges) {
|
|
5941
|
+
if (visitedNodeIds.has(edge.targetId)) {
|
|
5942
|
+
continue;
|
|
5943
|
+
}
|
|
5944
|
+
visitedNodeIds.add(edge.targetId);
|
|
5945
|
+
predecessorByNodeId.set(edge.targetId, {
|
|
5946
|
+
nodeId: currentNodeId,
|
|
5947
|
+
edgeId: edge.id
|
|
5948
|
+
});
|
|
5949
|
+
if (edge.targetId === target.id) {
|
|
5950
|
+
queue.length = 0;
|
|
5951
|
+
break;
|
|
5952
|
+
}
|
|
5953
|
+
queue.push(edge.targetId);
|
|
5954
|
+
}
|
|
5955
|
+
}
|
|
5956
|
+
if (!predecessorByNodeId.has(target.id)) {
|
|
5957
|
+
return {
|
|
5958
|
+
status: "not-found",
|
|
5959
|
+
selection,
|
|
5960
|
+
source,
|
|
5961
|
+
target,
|
|
5962
|
+
missingNodeIds: [],
|
|
5963
|
+
pathNodes: [],
|
|
5964
|
+
pathEdges: [],
|
|
5965
|
+
highlightNodeIds: [],
|
|
5966
|
+
highlightEdgeIds: [],
|
|
5967
|
+
distance: 0,
|
|
5968
|
+
message: buildPathNotFoundMessage(source, target)
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
const pathNodes = [target];
|
|
5972
|
+
const pathEdges = [];
|
|
5973
|
+
let cursorNodeId = target.id;
|
|
5974
|
+
while (cursorNodeId !== source.id) {
|
|
5975
|
+
const predecessor = predecessorByNodeId.get(cursorNodeId);
|
|
5976
|
+
if (!predecessor) {
|
|
5977
|
+
break;
|
|
5978
|
+
}
|
|
5979
|
+
const edge = index.edgesById.get(predecessor.edgeId);
|
|
5980
|
+
const previousNode = index.nodesById.get(predecessor.nodeId);
|
|
5981
|
+
if (edge) {
|
|
5982
|
+
pathEdges.push(edge);
|
|
5983
|
+
}
|
|
5984
|
+
if (previousNode) {
|
|
5985
|
+
pathNodes.push(previousNode);
|
|
5986
|
+
}
|
|
5987
|
+
cursorNodeId = predecessor.nodeId;
|
|
5988
|
+
}
|
|
5989
|
+
pathNodes.reverse();
|
|
5990
|
+
pathEdges.reverse();
|
|
5991
|
+
return {
|
|
5992
|
+
status: "found",
|
|
5993
|
+
selection,
|
|
5994
|
+
source,
|
|
5995
|
+
target,
|
|
5996
|
+
missingNodeIds: [],
|
|
5997
|
+
pathNodes,
|
|
5998
|
+
pathEdges,
|
|
5999
|
+
highlightNodeIds: pathNodes.map((node) => node.id),
|
|
6000
|
+
highlightEdgeIds: pathEdges.map((edge) => edge.id),
|
|
6001
|
+
distance: pathEdges.length,
|
|
6002
|
+
message: `Path found from "${source.label}" to "${target.label}" across ${pathEdges.length} edge${pathEdges.length === 1 ? "" : "s"}.`
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
|
|
6006
|
+
// src/features/operations/organization-graph/expand-around/expandAroundGraph.ts
|
|
6007
|
+
var DEFAULT_MAX_DEPTH = 1;
|
|
6008
|
+
var DEFAULT_MAX_RESULTS = 25;
|
|
6009
|
+
var ORG_MODEL_ROOT_KINDS = /* @__PURE__ */ new Set([
|
|
6010
|
+
"feature",
|
|
6011
|
+
"surface",
|
|
6012
|
+
"entity",
|
|
6013
|
+
"capability"
|
|
6014
|
+
]);
|
|
6015
|
+
var PRESET_EDGE_KINDS = {
|
|
6016
|
+
coverage: ["contains", "exposes", "operates-on", "maps_to", "references"],
|
|
6017
|
+
"operational-dependencies": ["references"],
|
|
6018
|
+
"org-context": ["contains", "exposes", "operates-on", "maps_to"],
|
|
6019
|
+
"impact-path": ["references"]
|
|
6020
|
+
};
|
|
6021
|
+
var PRESET_RELATIONSHIP_TYPES = {
|
|
6022
|
+
"operational-dependencies": ["triggers", "uses", "approval"],
|
|
6023
|
+
"impact-path": ["triggers", "uses", "approval"]
|
|
6024
|
+
};
|
|
6025
|
+
var PRESET_DIRECTIONS = {
|
|
6026
|
+
coverage: "both",
|
|
6027
|
+
"operational-dependencies": "both",
|
|
6028
|
+
"org-context": "both",
|
|
6029
|
+
"impact-path": "both"
|
|
6030
|
+
};
|
|
6031
|
+
function toSet(values) {
|
|
6032
|
+
if (!values || values.length === 0) {
|
|
6033
|
+
return null;
|
|
6034
|
+
}
|
|
6035
|
+
return new Set(values);
|
|
6036
|
+
}
|
|
6037
|
+
function clampMaxDepth(maxDepth) {
|
|
6038
|
+
if (maxDepth === 2 || maxDepth === 3) {
|
|
6039
|
+
return maxDepth;
|
|
6040
|
+
}
|
|
6041
|
+
return 1;
|
|
6042
|
+
}
|
|
6043
|
+
function resolvePreset(rootNode, preset) {
|
|
6044
|
+
if (preset) {
|
|
6045
|
+
return preset;
|
|
6046
|
+
}
|
|
6047
|
+
if (!rootNode) {
|
|
6048
|
+
return null;
|
|
6049
|
+
}
|
|
6050
|
+
if (ORG_MODEL_ROOT_KINDS.has(rootNode.kind)) {
|
|
6051
|
+
return "coverage";
|
|
6052
|
+
}
|
|
6053
|
+
if (rootNode.kind === "resource") {
|
|
6054
|
+
return "operational-dependencies";
|
|
6055
|
+
}
|
|
6056
|
+
return null;
|
|
6057
|
+
}
|
|
6058
|
+
function resolveRequest(rootNode, request) {
|
|
6059
|
+
const preset = resolvePreset(rootNode, request.preset);
|
|
6060
|
+
const maxResults = request.maxResults === void 0 || !Number.isFinite(request.maxResults) ? DEFAULT_MAX_RESULTS : Math.max(0, request.maxResults);
|
|
6061
|
+
return {
|
|
6062
|
+
rootNodeId: request.rootNodeId,
|
|
6063
|
+
direction: request.direction ?? (preset ? PRESET_DIRECTIONS[preset] : "both"),
|
|
6064
|
+
maxDepth: clampMaxDepth(request.maxDepth ?? DEFAULT_MAX_DEPTH),
|
|
6065
|
+
maxResults,
|
|
6066
|
+
edgeKinds: toSet(request.edgeKinds ?? (preset ? PRESET_EDGE_KINDS[preset] : void 0)),
|
|
6067
|
+
relationshipTypes: toSet(
|
|
6068
|
+
request.relationshipTypes ?? (preset ? PRESET_RELATIONSHIP_TYPES[preset] : void 0)
|
|
6069
|
+
),
|
|
6070
|
+
preset,
|
|
6071
|
+
nodeKinds: toSet(request.nodeKinds),
|
|
6072
|
+
resourceTypes: toSet(request.resourceTypes),
|
|
6073
|
+
includeHiddenResources: request.includeHiddenResources ?? false
|
|
6074
|
+
};
|
|
6075
|
+
}
|
|
6076
|
+
function getOppositeNodeId(edge, currentNodeId) {
|
|
6077
|
+
if (edge.sourceId === currentNodeId) {
|
|
6078
|
+
return edge.targetId;
|
|
6079
|
+
}
|
|
6080
|
+
if (edge.targetId === currentNodeId) {
|
|
6081
|
+
return edge.sourceId;
|
|
6082
|
+
}
|
|
6083
|
+
return null;
|
|
6084
|
+
}
|
|
6085
|
+
function getCandidateEdges(index, nodeId2, direction) {
|
|
6086
|
+
if (direction === "outgoing") {
|
|
6087
|
+
return index.outgoingEdgesByNodeId.get(nodeId2) ?? [];
|
|
6088
|
+
}
|
|
6089
|
+
if (direction === "incoming") {
|
|
6090
|
+
return index.incomingEdgesByNodeId.get(nodeId2) ?? [];
|
|
6091
|
+
}
|
|
6092
|
+
const seenEdgeIds = /* @__PURE__ */ new Set();
|
|
6093
|
+
const edges = [];
|
|
6094
|
+
for (const edge of [
|
|
6095
|
+
...index.outgoingEdgesByNodeId.get(nodeId2) ?? [],
|
|
6096
|
+
...index.incomingEdgesByNodeId.get(nodeId2) ?? []
|
|
6097
|
+
]) {
|
|
6098
|
+
if (seenEdgeIds.has(edge.id)) {
|
|
6099
|
+
continue;
|
|
6100
|
+
}
|
|
6101
|
+
seenEdgeIds.add(edge.id);
|
|
6102
|
+
edges.push(edge);
|
|
6103
|
+
}
|
|
6104
|
+
return edges;
|
|
6105
|
+
}
|
|
6106
|
+
function matchesPresetTraversalDirection(edge, currentNodeId, request) {
|
|
6107
|
+
if (request.preset === "coverage" && (edge.kind === "contains" || edge.kind === "exposes")) {
|
|
6108
|
+
return edge.sourceId === currentNodeId;
|
|
6109
|
+
}
|
|
6110
|
+
return true;
|
|
6111
|
+
}
|
|
6112
|
+
function matchesEdgeFilters(edge, currentNodeId, request) {
|
|
6113
|
+
if (request.edgeKinds && !request.edgeKinds.has(edge.kind)) {
|
|
6114
|
+
return false;
|
|
6115
|
+
}
|
|
6116
|
+
if (request.relationshipTypes && (!edge.relationshipType || !request.relationshipTypes.has(edge.relationshipType))) {
|
|
6117
|
+
return false;
|
|
6118
|
+
}
|
|
6119
|
+
return matchesPresetTraversalDirection(edge, currentNodeId, request);
|
|
6120
|
+
}
|
|
6121
|
+
function matchesNodeFilters(node, request) {
|
|
6122
|
+
if (request.nodeKinds && !request.nodeKinds.has(node.kind)) {
|
|
6123
|
+
return false;
|
|
6124
|
+
}
|
|
6125
|
+
if (request.resourceTypes) {
|
|
6126
|
+
if (node.kind !== "resource") {
|
|
6127
|
+
return false;
|
|
6128
|
+
}
|
|
6129
|
+
if (!node.resourceType || !request.resourceTypes.has(node.resourceType)) {
|
|
6130
|
+
return false;
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
return true;
|
|
6134
|
+
}
|
|
6135
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
6136
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
6137
|
+
}
|
|
6138
|
+
function getNodeDisplayName(node) {
|
|
6139
|
+
return node.label || node.sourceId || node.id;
|
|
6140
|
+
}
|
|
6141
|
+
function buildSummaryMessages(input) {
|
|
6142
|
+
const { rootNode, preset, expandedNodes, counts, truncated } = input;
|
|
6143
|
+
if (!rootNode) {
|
|
6144
|
+
return ["Select an available node to expand around."];
|
|
6145
|
+
}
|
|
6146
|
+
if (!preset && rootNode.kind === "organization") {
|
|
6147
|
+
return ["Choose a feature, surface, capability, entity, or resource before expanding."];
|
|
6148
|
+
}
|
|
6149
|
+
if (expandedNodes.length === 0) {
|
|
6150
|
+
return [`No matching graph context found around "${getNodeDisplayName(rootNode)}".`];
|
|
6151
|
+
}
|
|
6152
|
+
const resourceCount = expandedNodes.filter((node) => node.kind === "resource").length;
|
|
6153
|
+
const semanticContextCount = expandedNodes.length - resourceCount;
|
|
6154
|
+
const rootLabel = getNodeDisplayName(rootNode);
|
|
6155
|
+
const messages = [];
|
|
6156
|
+
if (preset === "coverage" && ORG_MODEL_ROOT_KINDS.has(rootNode.kind)) {
|
|
6157
|
+
if (resourceCount > 0 && semanticContextCount > 0) {
|
|
6158
|
+
messages.push(
|
|
6159
|
+
`${pluralize(resourceCount, "resource")} and ${pluralize(
|
|
6160
|
+
semanticContextCount,
|
|
6161
|
+
"semantic context node"
|
|
6162
|
+
)} support "${rootLabel}".`
|
|
6163
|
+
);
|
|
6164
|
+
} else if (resourceCount > 0) {
|
|
6165
|
+
messages.push(`${pluralize(resourceCount, "resource")} support "${rootLabel}".`);
|
|
6166
|
+
} else {
|
|
6167
|
+
messages.push(
|
|
6168
|
+
`${pluralize(semanticContextCount, "semantic context node")} found around "${rootLabel}"; no mapped resources matched this coverage preset.`
|
|
6169
|
+
);
|
|
6170
|
+
}
|
|
6171
|
+
} else if (preset === "operational-dependencies") {
|
|
6172
|
+
messages.push(`${pluralize(resourceCount, "operational dependency resource")} found around "${rootLabel}".`);
|
|
6173
|
+
} else if (preset === "org-context") {
|
|
6174
|
+
messages.push(`${pluralize(expandedNodes.length, "semantic context node")} found around "${rootLabel}".`);
|
|
6175
|
+
} else if (preset === "impact-path") {
|
|
6176
|
+
messages.push(`${pluralize(resourceCount, "resource")} can call or be affected by "${rootLabel}".`);
|
|
6177
|
+
} else {
|
|
6178
|
+
messages.push(`${pluralize(expandedNodes.length, "node")} found around "${rootLabel}".`);
|
|
6179
|
+
}
|
|
6180
|
+
if (counts.hiddenResourceNodes > 0) {
|
|
6181
|
+
messages.push(`${pluralize(counts.hiddenResourceNodes, "hidden resource")} matched current visibility settings.`);
|
|
6182
|
+
}
|
|
6183
|
+
if (counts.alreadyVisibleNodes > 0) {
|
|
6184
|
+
messages.push(`${pluralize(counts.alreadyVisibleNodes, "node")} already visible in the graph.`);
|
|
6185
|
+
}
|
|
6186
|
+
if (truncated) {
|
|
6187
|
+
messages.push(`Results were limited to ${pluralize(expandedNodes.length, "node")}.`);
|
|
6188
|
+
}
|
|
6189
|
+
return messages;
|
|
6190
|
+
}
|
|
6191
|
+
function expandAroundGraph(graph, request, options = {}) {
|
|
6192
|
+
const index = buildOrganizationGraphTraceIndex(graph);
|
|
6193
|
+
const rootNode = index.nodesById.get(request.rootNodeId) ?? null;
|
|
6194
|
+
const resolved = resolveRequest(rootNode, request);
|
|
6195
|
+
const alreadyVisibleNodeIds = new Set(options.alreadyVisibleNodeIds ?? []);
|
|
6196
|
+
const hiddenResourceNodeIds = new Set(options.hiddenResourceNodeIds ?? []);
|
|
6197
|
+
const expandedNodeIds = /* @__PURE__ */ new Set();
|
|
6198
|
+
const expandedEdgeIds = /* @__PURE__ */ new Set();
|
|
6199
|
+
const frontierNodeIds = /* @__PURE__ */ new Set();
|
|
6200
|
+
const visitedDepthByNodeId = /* @__PURE__ */ new Map([[resolved.rootNodeId, 0]]);
|
|
6201
|
+
const hasExplicitTraversalFilter = Boolean(
|
|
6202
|
+
request.preset || request.edgeKinds?.length || request.relationshipTypes?.length || request.nodeKinds?.length || request.resourceTypes?.length
|
|
6203
|
+
);
|
|
6204
|
+
const queue = rootNode && (resolved.preset || hasExplicitTraversalFilter) ? [{ nodeId: rootNode.id, depth: 0 }] : [];
|
|
6205
|
+
let truncated = false;
|
|
6206
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex += 1) {
|
|
6207
|
+
const current = queue[queueIndex];
|
|
6208
|
+
if (current.depth >= resolved.maxDepth) {
|
|
6209
|
+
if (current.nodeId !== resolved.rootNodeId) {
|
|
6210
|
+
frontierNodeIds.add(current.nodeId);
|
|
6211
|
+
}
|
|
6212
|
+
continue;
|
|
6213
|
+
}
|
|
6214
|
+
for (const edge of getCandidateEdges(index, current.nodeId, resolved.direction)) {
|
|
6215
|
+
if (!matchesEdgeFilters(edge, current.nodeId, resolved)) {
|
|
6216
|
+
continue;
|
|
6217
|
+
}
|
|
6218
|
+
const nextNodeId = getOppositeNodeId(edge, current.nodeId);
|
|
6219
|
+
if (!nextNodeId) {
|
|
6220
|
+
continue;
|
|
6221
|
+
}
|
|
6222
|
+
const nextNode = index.nodesById.get(nextNodeId);
|
|
6223
|
+
if (!nextNode || !matchesNodeFilters(nextNode, resolved)) {
|
|
6224
|
+
continue;
|
|
6225
|
+
}
|
|
6226
|
+
if (!resolved.includeHiddenResources && hiddenResourceNodeIds.has(nextNode.id)) {
|
|
6227
|
+
continue;
|
|
6228
|
+
}
|
|
6229
|
+
const nextDepth = current.depth + 1;
|
|
6230
|
+
const previousDepth = visitedDepthByNodeId.get(nextNode.id);
|
|
6231
|
+
if (previousDepth !== void 0) {
|
|
6232
|
+
if (nextNode.id === resolved.rootNodeId || expandedNodeIds.has(nextNode.id)) {
|
|
6233
|
+
expandedEdgeIds.add(edge.id);
|
|
6234
|
+
}
|
|
6235
|
+
continue;
|
|
6236
|
+
}
|
|
6237
|
+
if (expandedNodeIds.size >= resolved.maxResults) {
|
|
6238
|
+
truncated = true;
|
|
6239
|
+
frontierNodeIds.add(nextNode.id);
|
|
6240
|
+
continue;
|
|
6241
|
+
}
|
|
6242
|
+
visitedDepthByNodeId.set(nextNode.id, nextDepth);
|
|
6243
|
+
expandedNodeIds.add(nextNode.id);
|
|
6244
|
+
expandedEdgeIds.add(edge.id);
|
|
6245
|
+
if (nextDepth >= resolved.maxDepth) {
|
|
6246
|
+
frontierNodeIds.add(nextNode.id);
|
|
6247
|
+
continue;
|
|
6248
|
+
}
|
|
6249
|
+
queue.push({ nodeId: nextNode.id, depth: nextDepth });
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
const expandedNodes = [...expandedNodeIds].map((nodeId2) => index.nodesById.get(nodeId2)).filter((node) => Boolean(node));
|
|
6253
|
+
const hiddenResourceNodes = expandedNodes.filter((node) => hiddenResourceNodeIds.has(node.id)).length;
|
|
6254
|
+
const alreadyVisibleNodes = expandedNodes.filter((node) => alreadyVisibleNodeIds.has(node.id)).length;
|
|
6255
|
+
const newNodes = expandedNodes.filter(
|
|
6256
|
+
(node) => !hiddenResourceNodeIds.has(node.id) && !alreadyVisibleNodeIds.has(node.id)
|
|
6257
|
+
).length;
|
|
6258
|
+
const counts = {
|
|
6259
|
+
newNodes,
|
|
6260
|
+
newEdges: expandedEdgeIds.size,
|
|
6261
|
+
alreadyVisibleNodes,
|
|
6262
|
+
hiddenResourceNodes
|
|
6263
|
+
};
|
|
6264
|
+
const summaryMessages = buildSummaryMessages({
|
|
6265
|
+
rootNode,
|
|
6266
|
+
preset: resolved.preset,
|
|
6267
|
+
expandedNodes,
|
|
6268
|
+
counts,
|
|
6269
|
+
truncated
|
|
6270
|
+
});
|
|
6271
|
+
return {
|
|
6272
|
+
rootNodeId: request.rootNodeId,
|
|
6273
|
+
rootNode,
|
|
6274
|
+
preset: resolved.preset,
|
|
6275
|
+
direction: resolved.direction,
|
|
6276
|
+
maxDepth: resolved.maxDepth,
|
|
6277
|
+
maxResults: resolved.maxResults,
|
|
6278
|
+
expandedNodeIds: [...expandedNodeIds],
|
|
6279
|
+
expandedEdgeIds: [...expandedEdgeIds],
|
|
6280
|
+
frontierNodeIds: [...frontierNodeIds].filter((nodeId2) => nodeId2 !== resolved.rootNodeId),
|
|
6281
|
+
truncated,
|
|
6282
|
+
counts,
|
|
6283
|
+
summaryMessages,
|
|
6284
|
+
message: summaryMessages[0] ?? ""
|
|
6285
|
+
};
|
|
6286
|
+
}
|
|
6287
|
+
var PRESET_OPTIONS = [
|
|
6288
|
+
{ value: "coverage", label: "Coverage" },
|
|
6289
|
+
{ value: "operational-dependencies", label: "Operational dependencies" },
|
|
6290
|
+
{ value: "org-context", label: "Org context" },
|
|
6291
|
+
{ value: "impact-path", label: "Impact path" }
|
|
6292
|
+
];
|
|
6293
|
+
var DIRECTION_OPTIONS = [
|
|
6294
|
+
{ value: "both", label: "Both" },
|
|
6295
|
+
{ value: "outgoing", label: "Outgoing" },
|
|
6296
|
+
{ value: "incoming", label: "Incoming" }
|
|
6297
|
+
];
|
|
6298
|
+
var EDGE_KIND_OPTIONS = [
|
|
6299
|
+
{ value: "contains", label: "Containment" },
|
|
6300
|
+
{ value: "references", label: "References" },
|
|
6301
|
+
{ value: "exposes", label: "Exposes" },
|
|
6302
|
+
{ value: "maps_to", label: "Maps to" },
|
|
6303
|
+
{ value: "operates-on", label: "Operates on" },
|
|
6304
|
+
{ value: "uses", label: "Uses" }
|
|
6305
|
+
];
|
|
6306
|
+
var RELATIONSHIP_OPTIONS = [
|
|
6307
|
+
{ value: "triggers", label: "Triggers" },
|
|
6308
|
+
{ value: "uses", label: "Uses" },
|
|
6309
|
+
{ value: "approval", label: "Approval" }
|
|
6310
|
+
];
|
|
6311
|
+
var RESOURCE_TYPE_OPTIONS = [
|
|
6312
|
+
{ value: "workflow", label: "Workflow" },
|
|
6313
|
+
{ value: "agent", label: "Agent" },
|
|
6314
|
+
{ value: "trigger", label: "Trigger" },
|
|
6315
|
+
{ value: "integration", label: "Integration" },
|
|
6316
|
+
{ value: "external", label: "External" },
|
|
6317
|
+
{ value: "human_checkpoint", label: "Human checkpoint" }
|
|
6318
|
+
];
|
|
6319
|
+
function updateValue(value, key, nextValue, onChange) {
|
|
6320
|
+
onChange({
|
|
6321
|
+
...value,
|
|
6322
|
+
[key]: nextValue
|
|
6323
|
+
});
|
|
6324
|
+
}
|
|
6325
|
+
function toOptionalArray(values) {
|
|
6326
|
+
return values.length > 0 ? values : void 0;
|
|
6327
|
+
}
|
|
6328
|
+
function toMaxDepth(value) {
|
|
6329
|
+
const numeric = typeof value === "number" ? value : Number.parseInt(value, 10);
|
|
6330
|
+
if (numeric === 3) return 3;
|
|
6331
|
+
if (numeric === 2) return 2;
|
|
6332
|
+
return 1;
|
|
6333
|
+
}
|
|
6334
|
+
function ExpandAroundPanel({
|
|
6335
|
+
selectedNode,
|
|
6336
|
+
value,
|
|
6337
|
+
result,
|
|
6338
|
+
appliedNodeCount,
|
|
6339
|
+
appliedEdgeCount,
|
|
6340
|
+
onChange,
|
|
6341
|
+
onPreview,
|
|
6342
|
+
onApply,
|
|
6343
|
+
onClear
|
|
6344
|
+
}) {
|
|
6345
|
+
const disabled = !selectedNode;
|
|
6346
|
+
const canApply = Boolean(result && result.expandedNodeIds.length > 0);
|
|
6347
|
+
const rootIsTooBroad = selectedNode?.kind === "organization" && !value.preset;
|
|
6348
|
+
return /* @__PURE__ */ jsx(Paper, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
6349
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", wrap: "wrap", children: [
|
|
6350
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
6351
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 800, children: "Expand Around" }),
|
|
6352
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: selectedNode ? `Preview typed graph context around ${selectedNode.label}.` : "Select a graph node to preview nearby operational context." })
|
|
6353
|
+
] }),
|
|
6354
|
+
appliedNodeCount > 0 || appliedEdgeCount > 0 ? /* @__PURE__ */ jsxs(Badge, { variant: "light", color: "blue", children: [
|
|
6355
|
+
appliedNodeCount,
|
|
6356
|
+
" nodes / ",
|
|
6357
|
+
appliedEdgeCount,
|
|
6358
|
+
" edges applied"
|
|
6359
|
+
] }) : null
|
|
6360
|
+
] }),
|
|
6361
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", children: [
|
|
6362
|
+
/* @__PURE__ */ jsx(
|
|
6363
|
+
Select,
|
|
6364
|
+
{
|
|
6365
|
+
label: "Preset",
|
|
6366
|
+
placeholder: "Auto",
|
|
6367
|
+
data: PRESET_OPTIONS,
|
|
6368
|
+
value: value.preset ?? null,
|
|
6369
|
+
onChange: (preset) => updateValue(value, "preset", preset ?? void 0, onChange),
|
|
6370
|
+
disabled,
|
|
6371
|
+
clearable: true
|
|
6372
|
+
}
|
|
6373
|
+
),
|
|
6374
|
+
/* @__PURE__ */ jsx(
|
|
6375
|
+
Select,
|
|
6376
|
+
{
|
|
6377
|
+
label: "Direction",
|
|
6378
|
+
data: DIRECTION_OPTIONS,
|
|
6379
|
+
value: value.direction ?? "both",
|
|
6380
|
+
onChange: (direction) => updateValue(value, "direction", direction ?? "both", onChange),
|
|
6381
|
+
disabled
|
|
6382
|
+
}
|
|
6383
|
+
),
|
|
6384
|
+
/* @__PURE__ */ jsx(
|
|
6385
|
+
NumberInput,
|
|
6386
|
+
{
|
|
6387
|
+
label: "Depth",
|
|
6388
|
+
min: 1,
|
|
6389
|
+
max: 3,
|
|
6390
|
+
value: value.maxDepth ?? 1,
|
|
6391
|
+
onChange: (maxDepth) => updateValue(value, "maxDepth", toMaxDepth(maxDepth), onChange),
|
|
6392
|
+
disabled
|
|
6393
|
+
}
|
|
6394
|
+
),
|
|
6395
|
+
/* @__PURE__ */ jsx(
|
|
6396
|
+
NumberInput,
|
|
6397
|
+
{
|
|
6398
|
+
label: "Max results",
|
|
6399
|
+
min: 1,
|
|
6400
|
+
max: 100,
|
|
6401
|
+
value: value.maxResults ?? 25,
|
|
6402
|
+
onChange: (maxResults) => updateValue(
|
|
6403
|
+
value,
|
|
6404
|
+
"maxResults",
|
|
6405
|
+
Math.max(1, typeof maxResults === "number" ? maxResults : Number.parseInt(maxResults, 10) || 25),
|
|
6406
|
+
onChange
|
|
6407
|
+
),
|
|
6408
|
+
disabled
|
|
6409
|
+
}
|
|
6410
|
+
)
|
|
6411
|
+
] }),
|
|
6412
|
+
/* @__PURE__ */ jsx(
|
|
6413
|
+
MultiSelect,
|
|
6414
|
+
{
|
|
6415
|
+
label: "Relationship filters",
|
|
6416
|
+
placeholder: "Preset defaults",
|
|
6417
|
+
data: RELATIONSHIP_OPTIONS,
|
|
6418
|
+
value: value.relationshipTypes ?? [],
|
|
6419
|
+
onChange: (relationshipTypes) => updateValue(value, "relationshipTypes", toOptionalArray(relationshipTypes), onChange),
|
|
6420
|
+
disabled,
|
|
6421
|
+
clearable: true
|
|
6422
|
+
}
|
|
6423
|
+
),
|
|
6424
|
+
/* @__PURE__ */ jsx(
|
|
6425
|
+
MultiSelect,
|
|
6426
|
+
{
|
|
6427
|
+
label: "Edge kind filters",
|
|
6428
|
+
placeholder: "Preset defaults",
|
|
6429
|
+
data: EDGE_KIND_OPTIONS,
|
|
6430
|
+
value: value.edgeKinds ?? [],
|
|
6431
|
+
onChange: (edgeKinds) => updateValue(value, "edgeKinds", toOptionalArray(edgeKinds), onChange),
|
|
6432
|
+
disabled,
|
|
6433
|
+
clearable: true
|
|
6434
|
+
}
|
|
6435
|
+
),
|
|
6436
|
+
/* @__PURE__ */ jsx(
|
|
6437
|
+
MultiSelect,
|
|
6438
|
+
{
|
|
6439
|
+
label: "Resource type filters",
|
|
6440
|
+
placeholder: "All resource types",
|
|
6441
|
+
data: RESOURCE_TYPE_OPTIONS,
|
|
6442
|
+
value: value.resourceTypes ?? [],
|
|
6443
|
+
onChange: (resourceTypes) => updateValue(value, "resourceTypes", toOptionalArray(resourceTypes), onChange),
|
|
6444
|
+
disabled,
|
|
6445
|
+
clearable: true
|
|
6446
|
+
}
|
|
6447
|
+
),
|
|
6448
|
+
/* @__PURE__ */ jsx(
|
|
6449
|
+
Switch,
|
|
6450
|
+
{
|
|
6451
|
+
label: "Include hidden resources",
|
|
6452
|
+
checked: value.includeHiddenResources ?? true,
|
|
6453
|
+
onChange: (event) => updateValue(value, "includeHiddenResources", event.currentTarget.checked, onChange),
|
|
6454
|
+
disabled
|
|
6455
|
+
}
|
|
6456
|
+
),
|
|
6457
|
+
rootIsTooBroad ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "orange", children: "The organization root is broad. Choose a narrower node or a semantic preset before previewing." }) : null,
|
|
6458
|
+
result ? /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
6459
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "wrap", children: [
|
|
6460
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
|
|
6461
|
+
result.counts.newNodes,
|
|
6462
|
+
" new"
|
|
6463
|
+
] }),
|
|
6464
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
|
|
6465
|
+
result.counts.alreadyVisibleNodes,
|
|
6466
|
+
" visible"
|
|
6467
|
+
] }),
|
|
6468
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", color: result.counts.hiddenResourceNodes > 0 ? "orange" : "gray", children: [
|
|
6469
|
+
result.counts.hiddenResourceNodes,
|
|
6470
|
+
" hidden"
|
|
6471
|
+
] }),
|
|
6472
|
+
result.truncated ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: "yellow", children: "Truncated" }) : null
|
|
6473
|
+
] }),
|
|
6474
|
+
result.summaryMessages.map((message) => /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: message }, message))
|
|
6475
|
+
] }) }) : null,
|
|
6476
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "wrap", children: [
|
|
6477
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6478
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "light", onClick: onPreview, disabled: disabled || rootIsTooBroad, children: "Preview" }),
|
|
6479
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", onClick: onApply, disabled: !canApply, children: "Apply" })
|
|
6480
|
+
] }),
|
|
6481
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: onClear, disabled: !result && appliedNodeCount === 0, children: "Clear expansion" })
|
|
6482
|
+
] })
|
|
6483
|
+
] }) });
|
|
6484
|
+
}
|
|
6485
|
+
var cellStyle = {
|
|
6486
|
+
padding: "var(--mantine-spacing-sm) var(--mantine-spacing-md)",
|
|
6487
|
+
display: "flex",
|
|
6488
|
+
alignItems: "center",
|
|
6489
|
+
gap: "var(--mantine-spacing-sm)",
|
|
6490
|
+
minWidth: 0
|
|
6491
|
+
};
|
|
6492
|
+
function CommandViewHealthStrip({
|
|
6493
|
+
overview,
|
|
6494
|
+
hotspots,
|
|
6495
|
+
visibleResources,
|
|
6496
|
+
hiddenResources = 0,
|
|
6497
|
+
resourcesHidden,
|
|
6498
|
+
selectedLabel,
|
|
6499
|
+
onFocusHotspot,
|
|
6500
|
+
onResourcesHiddenChange,
|
|
6501
|
+
onResetFocus
|
|
6502
|
+
}) {
|
|
6503
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
6504
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
6505
|
+
/* @__PURE__ */ jsx(IconActivityHeartbeat, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
6506
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.successRate == null ? "N/A" : `${Math.round(overview.successRate)}%` }),
|
|
6507
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
6508
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", children: overview?.successCount ?? 0 }),
|
|
6509
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "red", size: "xs", children: overview?.failureCount ?? 0 }),
|
|
6510
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "yellow", size: "xs", children: overview?.warningCount ?? 0 })
|
|
6511
|
+
] }),
|
|
6512
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, style: { flexShrink: 1, minWidth: 0 }, children: overview ? `${overview.totalRuns} runs / ${overview.trackedResources} resources` : "" })
|
|
6513
|
+
] }),
|
|
6514
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
6515
|
+
/* @__PURE__ */ jsx(IconAlertTriangle, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
6516
|
+
hotspots.length > 0 ? /* @__PURE__ */ jsx(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0, overflow: "hidden" }, children: hotspots.map((hotspot) => /* @__PURE__ */ jsx(Group, { gap: 4, wrap: "nowrap", children: /* @__PURE__ */ jsx(
|
|
6517
|
+
Badge,
|
|
6518
|
+
{
|
|
6519
|
+
variant: "light",
|
|
6520
|
+
color: "red",
|
|
6521
|
+
size: "xs",
|
|
6522
|
+
style: { cursor: "pointer", flexShrink: 0 },
|
|
6523
|
+
onClick: () => onFocusHotspot(hotspot.resourceId),
|
|
6524
|
+
children: hotspot.label
|
|
6525
|
+
}
|
|
6526
|
+
) }, hotspot.nodeId)) }) : /* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 10 }), children: "No hotspots" })
|
|
6527
|
+
] }),
|
|
6528
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
6529
|
+
/* @__PURE__ */ jsx(IconClockPause, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
6530
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.pendingApprovals ?? 0 }),
|
|
6531
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", truncate: true, children: [
|
|
6532
|
+
"pending / ",
|
|
6533
|
+
overview?.activeHumanCheckpoints ?? 0,
|
|
6534
|
+
" queues"
|
|
6535
|
+
] })
|
|
6536
|
+
] }),
|
|
6537
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
6538
|
+
/* @__PURE__ */ jsx(IconTopologyStar3, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
6539
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, truncate: true, style: { minWidth: 0 }, children: selectedLabel ?? `${visibleResources} visible / ${hiddenResources} hidden` }),
|
|
6540
|
+
/* @__PURE__ */ jsx(
|
|
6541
|
+
Button,
|
|
6542
|
+
{
|
|
6543
|
+
size: "compact-xs",
|
|
6544
|
+
variant: resourcesHidden ? "light" : "subtle",
|
|
6545
|
+
onClick: () => onResourcesHiddenChange(!resourcesHidden),
|
|
6546
|
+
style: { flexShrink: 0 },
|
|
6547
|
+
children: resourcesHidden ? "Show resources" : "Hide resources"
|
|
6548
|
+
}
|
|
6549
|
+
),
|
|
6550
|
+
/* @__PURE__ */ jsx(Button, { size: "compact-xs", variant: "subtle", onClick: onResetFocus, style: { flexShrink: 0 }, children: "Reset" })
|
|
6551
|
+
] })
|
|
6552
|
+
] });
|
|
6553
|
+
}
|
|
6554
|
+
var FILTER_STATE_ICONS2 = {
|
|
6555
|
+
neutral: IconCircleDashed,
|
|
6556
|
+
include: IconCircleCheck,
|
|
6557
|
+
exclude: IconCircleX
|
|
6558
|
+
};
|
|
6559
|
+
var FILTER_STATE_COLORS2 = {
|
|
6560
|
+
neutral: "var(--color-text-dimmed)",
|
|
6561
|
+
include: "var(--mantine-color-green-6)",
|
|
6562
|
+
exclude: "var(--mantine-color-red-6)"
|
|
6563
|
+
};
|
|
6564
|
+
var FILTER_STATE_LABELS2 = {
|
|
6565
|
+
neutral: "Not filtered",
|
|
6566
|
+
include: "Include only",
|
|
6567
|
+
exclude: "Exclude"
|
|
6568
|
+
};
|
|
6569
|
+
function getCommandViewResources(commandViewData) {
|
|
6570
|
+
if (!commandViewData) {
|
|
6571
|
+
return [];
|
|
6572
|
+
}
|
|
6573
|
+
return [
|
|
6574
|
+
...commandViewData.agents,
|
|
6575
|
+
...commandViewData.workflows,
|
|
6576
|
+
...commandViewData.triggers,
|
|
6577
|
+
...commandViewData.integrations,
|
|
6578
|
+
...commandViewData.externalResources,
|
|
6579
|
+
...commandViewData.humanCheckpoints
|
|
6580
|
+
];
|
|
6581
|
+
}
|
|
6582
|
+
function nextDomainFilterState(current) {
|
|
6583
|
+
if (current === "neutral") return "include";
|
|
6584
|
+
if (current === "include") return "exclude";
|
|
6585
|
+
return "neutral";
|
|
6586
|
+
}
|
|
6587
|
+
function FilterPanel({
|
|
6588
|
+
filters,
|
|
6589
|
+
onChangeFilters,
|
|
6590
|
+
resetValue,
|
|
6591
|
+
disabled = false,
|
|
6592
|
+
commandViewData,
|
|
6593
|
+
lens,
|
|
6594
|
+
resourcesHidden,
|
|
6595
|
+
diagnosticsHidden,
|
|
6596
|
+
onResourcesHiddenChange,
|
|
6597
|
+
onDiagnosticsHiddenChange,
|
|
6598
|
+
onRevealResources,
|
|
6599
|
+
onResetFilters,
|
|
6600
|
+
visibilityCounts,
|
|
6601
|
+
graph,
|
|
6602
|
+
baseGraph,
|
|
6603
|
+
layout = "grid"
|
|
6604
|
+
}) {
|
|
6605
|
+
const resourceFacets = collectResourceFilterFacets(getCommandViewResources(commandViewData));
|
|
6606
|
+
const Section = ({ children }) => layout === "stack" ? /* @__PURE__ */ jsx(
|
|
6607
|
+
Stack,
|
|
6608
|
+
{
|
|
6609
|
+
gap: "sm",
|
|
6610
|
+
pb: "sm",
|
|
6611
|
+
style: {
|
|
6612
|
+
borderBottom: "1px solid var(--color-border)"
|
|
6613
|
+
},
|
|
6614
|
+
children
|
|
6615
|
+
}
|
|
6616
|
+
) : /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", radius: "md", style: { background: "var(--color-surface)" }, children });
|
|
6617
|
+
const updateDomainFilter = (domainId) => {
|
|
6618
|
+
const current = filters.domainFilters[domainId] ?? "neutral";
|
|
6619
|
+
onChangeFilters({
|
|
6620
|
+
...filters,
|
|
6621
|
+
domainFilters: {
|
|
6622
|
+
...filters.domainFilters,
|
|
6623
|
+
[domainId]: nextDomainFilterState(current)
|
|
6624
|
+
}
|
|
6625
|
+
});
|
|
6626
|
+
};
|
|
6627
|
+
const handleResourceVisibilityAction = () => {
|
|
6628
|
+
if (resourcesHidden) {
|
|
6629
|
+
onRevealResources();
|
|
6630
|
+
return;
|
|
6631
|
+
}
|
|
6632
|
+
onResourcesHiddenChange(true);
|
|
6633
|
+
};
|
|
6634
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6635
|
+
/* @__PURE__ */ jsx(Section, { children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
6636
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Filters" }),
|
|
6637
|
+
/* @__PURE__ */ jsx(
|
|
6638
|
+
OrganizationGraphFilterToolbar,
|
|
6639
|
+
{
|
|
6640
|
+
value: filters,
|
|
6641
|
+
onChange: onChangeFilters,
|
|
6642
|
+
disabled,
|
|
6643
|
+
resetValue
|
|
6644
|
+
}
|
|
6645
|
+
)
|
|
6646
|
+
] }) }),
|
|
6647
|
+
/* @__PURE__ */ jsx(Section, { children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
6648
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
|
|
6649
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Visibility" }),
|
|
6650
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
|
|
6651
|
+
visibilityCounts.visibleResourceCount,
|
|
6652
|
+
"/",
|
|
6653
|
+
visibilityCounts.totalResourceCount,
|
|
6654
|
+
" resources"
|
|
6655
|
+
] })
|
|
6656
|
+
] }),
|
|
6657
|
+
lens === "command-view" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6658
|
+
/* @__PURE__ */ jsx(
|
|
6659
|
+
Checkbox,
|
|
6660
|
+
{
|
|
6661
|
+
label: "Hide resource nodes",
|
|
6662
|
+
description: "Keep the organization structure readable and reveal resource nodes as needed.",
|
|
6014
6663
|
checked: resourcesHidden,
|
|
6015
6664
|
onChange: (event) => onResourcesHiddenChange(event.currentTarget.checked),
|
|
6016
6665
|
disabled
|
|
@@ -6125,345 +6774,114 @@ function toResourceHealth(node, stats) {
|
|
|
6125
6774
|
const summaryLabel2 = checkpointStats.pendingCount > 0 ? `${checkpointStats.pendingCount} pending` : checkpointStats.expiredCount > 0 ? `${checkpointStats.expiredCount} expired` : checkpointStats.completedCount > 0 ? `${checkpointStats.completedCount} completed` : "No queue activity";
|
|
6126
6775
|
const detailLabel = checkpointStats.pendingCount > 0 ? `${checkpointStats.completedCount} resolved` : totalQueueActivity > 0 ? "Queue clear" : "No approvals in range";
|
|
6127
6776
|
return {
|
|
6128
|
-
nodeId: node.id,
|
|
6129
|
-
resourceId,
|
|
6130
|
-
label: node.label,
|
|
6131
|
-
resourceType: node.resourceType,
|
|
6132
|
-
healthLevel: healthLevel2,
|
|
6133
|
-
summaryLabel: summaryLabel2,
|
|
6134
|
-
detailLabel,
|
|
6135
|
-
successRate: null,
|
|
6136
|
-
totalRuns: 0,
|
|
6137
|
-
successCount: 0,
|
|
6138
|
-
failureCount: 0,
|
|
6139
|
-
warningCount: 0,
|
|
6140
|
-
pendingCount: checkpointStats.pendingCount,
|
|
6141
|
-
completedCount: checkpointStats.completedCount,
|
|
6142
|
-
expiredCount: checkpointStats.expiredCount,
|
|
6143
|
-
lastActivityAt: checkpointStats.lastDecisionAt,
|
|
6144
|
-
sortScore: checkpointStats.pendingCount * 100 + checkpointStats.expiredCount * 25 + checkpointStats.completedCount
|
|
6145
|
-
};
|
|
6146
|
-
}
|
|
6147
|
-
const resourceStats = stats.resources[resourceId];
|
|
6148
|
-
if (!resourceStats || resourceStats.totalRuns <= 0) {
|
|
6149
|
-
return {
|
|
6150
|
-
nodeId: node.id,
|
|
6151
|
-
resourceId,
|
|
6152
|
-
label: node.label,
|
|
6153
|
-
resourceType: node.resourceType,
|
|
6154
|
-
healthLevel: "inactive",
|
|
6155
|
-
summaryLabel: "No runs",
|
|
6156
|
-
detailLabel: "No executions in range",
|
|
6157
|
-
successRate: null,
|
|
6158
|
-
totalRuns: 0,
|
|
6159
|
-
successCount: 0,
|
|
6160
|
-
failureCount: 0,
|
|
6161
|
-
warningCount: 0,
|
|
6162
|
-
pendingCount: 0,
|
|
6163
|
-
completedCount: 0,
|
|
6164
|
-
expiredCount: 0,
|
|
6165
|
-
lastActivityAt: resourceStats?.lastRunAt ?? null,
|
|
6166
|
-
sortScore: 0
|
|
6167
|
-
};
|
|
6168
|
-
}
|
|
6169
|
-
const successfulOutcomes = resourceStats.successCount + resourceStats.warningCount;
|
|
6170
|
-
const successRate = successfulOutcomes / resourceStats.totalRuns * 100;
|
|
6171
|
-
const healthLevel = successRate >= 95 ? "healthy" : successRate >= 80 ? "warning" : "critical";
|
|
6172
|
-
const summaryLabel = resourceStats.failureCount > 0 ? `${resourceStats.failureCount} failed` : resourceStats.warningCount > 0 ? `${resourceStats.warningCount} warnings` : `${resourceStats.totalRuns} runs`;
|
|
6173
|
-
return {
|
|
6174
|
-
nodeId: node.id,
|
|
6175
|
-
resourceId,
|
|
6176
|
-
label: node.label,
|
|
6177
|
-
resourceType: node.resourceType,
|
|
6178
|
-
healthLevel,
|
|
6179
|
-
summaryLabel,
|
|
6180
|
-
detailLabel: `${Math.round(successRate)}% healthy`,
|
|
6181
|
-
successRate,
|
|
6182
|
-
totalRuns: resourceStats.totalRuns,
|
|
6183
|
-
successCount: resourceStats.successCount,
|
|
6184
|
-
failureCount: resourceStats.failureCount,
|
|
6185
|
-
warningCount: resourceStats.warningCount,
|
|
6186
|
-
pendingCount: 0,
|
|
6187
|
-
completedCount: 0,
|
|
6188
|
-
expiredCount: 0,
|
|
6189
|
-
lastActivityAt: resourceStats.lastRunAt,
|
|
6190
|
-
sortScore: resourceStats.failureCount * 100 + resourceStats.warningCount * 25 + resourceStats.totalRuns
|
|
6191
|
-
};
|
|
6192
|
-
}
|
|
6193
|
-
function getCommandViewGraphNodeHealth(node, stats) {
|
|
6194
|
-
if (node.kind !== "resource" || !stats) {
|
|
6195
|
-
return null;
|
|
6196
|
-
}
|
|
6197
|
-
return toResourceHealth(node, stats);
|
|
6198
|
-
}
|
|
6199
|
-
function getCommandViewGraphHealthMap(graph, stats) {
|
|
6200
|
-
const healthByNodeId = /* @__PURE__ */ new Map();
|
|
6201
|
-
if (!graph || !stats) {
|
|
6202
|
-
return healthByNodeId;
|
|
6203
|
-
}
|
|
6204
|
-
for (const node of graph.nodes) {
|
|
6205
|
-
const health = getCommandViewGraphNodeHealth(node, stats);
|
|
6206
|
-
if (health) {
|
|
6207
|
-
healthByNodeId.set(node.id, health);
|
|
6208
|
-
}
|
|
6209
|
-
}
|
|
6210
|
-
return healthByNodeId;
|
|
6211
|
-
}
|
|
6212
|
-
function getHealthRank(level) {
|
|
6213
|
-
switch (level) {
|
|
6214
|
-
case "critical":
|
|
6215
|
-
return 0;
|
|
6216
|
-
case "warning":
|
|
6217
|
-
return 1;
|
|
6218
|
-
case "healthy":
|
|
6219
|
-
return 2;
|
|
6220
|
-
case "inactive":
|
|
6221
|
-
default:
|
|
6222
|
-
return 3;
|
|
6223
|
-
}
|
|
6224
|
-
}
|
|
6225
|
-
function rankCommandViewHotspots(entries, limit = 3) {
|
|
6226
|
-
return [...entries].filter((entry) => entry.healthLevel === "critical" || entry.healthLevel === "warning").sort((left, right) => {
|
|
6227
|
-
const healthRankDelta = getHealthRank(left.healthLevel) - getHealthRank(right.healthLevel);
|
|
6228
|
-
if (healthRankDelta !== 0) {
|
|
6229
|
-
return healthRankDelta;
|
|
6230
|
-
}
|
|
6231
|
-
if (right.sortScore !== left.sortScore) {
|
|
6232
|
-
return right.sortScore - left.sortScore;
|
|
6233
|
-
}
|
|
6234
|
-
return left.label.localeCompare(right.label);
|
|
6235
|
-
}).slice(0, limit);
|
|
6236
|
-
}
|
|
6237
|
-
|
|
6238
|
-
// src/features/operations/organization-graph/path-tracing/trace.ts
|
|
6239
|
-
var NODE_KIND_ORDER = {
|
|
6240
|
-
organization: 0,
|
|
6241
|
-
feature: 1,
|
|
6242
|
-
surface: 2,
|
|
6243
|
-
capability: 3,
|
|
6244
|
-
entity: 4,
|
|
6245
|
-
resource: 5
|
|
6246
|
-
};
|
|
6247
|
-
var NODE_KIND_LABEL = {
|
|
6248
|
-
organization: "Organization",
|
|
6249
|
-
feature: "Feature",
|
|
6250
|
-
surface: "Surface",
|
|
6251
|
-
capability: "Capability",
|
|
6252
|
-
entity: "Entity",
|
|
6253
|
-
resource: "Resource"
|
|
6254
|
-
};
|
|
6255
|
-
function getNodeLabel(node) {
|
|
6256
|
-
return node.label || node.sourceId || node.id;
|
|
6257
|
-
}
|
|
6258
|
-
function compareTraceNodes(a, b) {
|
|
6259
|
-
const kindDelta = NODE_KIND_ORDER[a.kind] - NODE_KIND_ORDER[b.kind];
|
|
6260
|
-
if (kindDelta !== 0) {
|
|
6261
|
-
return kindDelta;
|
|
6262
|
-
}
|
|
6263
|
-
const labelDelta = getNodeLabel(a).localeCompare(getNodeLabel(b));
|
|
6264
|
-
if (labelDelta !== 0) {
|
|
6265
|
-
return labelDelta;
|
|
6266
|
-
}
|
|
6267
|
-
return a.id.localeCompare(b.id);
|
|
6268
|
-
}
|
|
6269
|
-
function buildMissingNodeMessage(selection, missingNodeIds) {
|
|
6270
|
-
if (missingNodeIds.length === 0) {
|
|
6271
|
-
return "The selected trace is not available.";
|
|
6272
|
-
}
|
|
6273
|
-
if (missingNodeIds.length === 1) {
|
|
6274
|
-
const missingId = missingNodeIds[0];
|
|
6275
|
-
return `Graph node "${missingId}" is not available.`;
|
|
6276
|
-
}
|
|
6277
|
-
return `Graph nodes "${selection.sourceId}" and "${selection.targetId}" are not available.`;
|
|
6278
|
-
}
|
|
6279
|
-
function buildPathNotFoundMessage(source, target) {
|
|
6280
|
-
return `No directed path found from "${source.label}" to "${target.label}".`;
|
|
6281
|
-
}
|
|
6282
|
-
function buildOrganizationGraphTraceIndex(graph) {
|
|
6283
|
-
const nodesById = /* @__PURE__ */ new Map();
|
|
6284
|
-
const edgesById = /* @__PURE__ */ new Map();
|
|
6285
|
-
const outgoingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
6286
|
-
const incomingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
6287
|
-
for (const node of graph.nodes) {
|
|
6288
|
-
nodesById.set(node.id, node);
|
|
6289
|
-
outgoingEdgesByNodeId.set(node.id, []);
|
|
6290
|
-
incomingEdgesByNodeId.set(node.id, []);
|
|
6291
|
-
}
|
|
6292
|
-
for (const edge of graph.edges) {
|
|
6293
|
-
edgesById.set(edge.id, edge);
|
|
6294
|
-
const outgoingEdges = outgoingEdgesByNodeId.get(edge.sourceId);
|
|
6295
|
-
if (outgoingEdges) {
|
|
6296
|
-
outgoingEdges.push(edge);
|
|
6297
|
-
}
|
|
6298
|
-
const incomingEdges = incomingEdgesByNodeId.get(edge.targetId);
|
|
6299
|
-
if (incomingEdges) {
|
|
6300
|
-
incomingEdges.push(edge);
|
|
6301
|
-
}
|
|
6302
|
-
}
|
|
6303
|
-
return {
|
|
6304
|
-
nodesById,
|
|
6305
|
-
edgesById,
|
|
6306
|
-
outgoingEdgesByNodeId,
|
|
6307
|
-
incomingEdgesByNodeId
|
|
6308
|
-
};
|
|
6309
|
-
}
|
|
6310
|
-
function getOrganizationGraphTraceNodeKindLabel(kind) {
|
|
6311
|
-
return NODE_KIND_LABEL[kind];
|
|
6312
|
-
}
|
|
6313
|
-
function formatOrganizationGraphTraceNodeOptionLabel(option) {
|
|
6314
|
-
return `${option.label} \xB7 ${getOrganizationGraphTraceNodeKindLabel(option.kind)}`;
|
|
6315
|
-
}
|
|
6316
|
-
function getOrganizationGraphTraceNodeOptions(graph) {
|
|
6317
|
-
return [...graph.nodes].sort(compareTraceNodes).map((node) => ({
|
|
6318
|
-
id: node.id,
|
|
6319
|
-
label: getNodeLabel(node),
|
|
6320
|
-
kind: node.kind,
|
|
6321
|
-
sourceId: node.sourceId,
|
|
6322
|
-
description: node.description,
|
|
6323
|
-
enabled: node.enabled
|
|
6324
|
-
}));
|
|
6325
|
-
}
|
|
6326
|
-
function resolveOrganizationGraphPathTrace(graph, selection) {
|
|
6327
|
-
const index = buildOrganizationGraphTraceIndex(graph);
|
|
6328
|
-
const source = selection.sourceId ? index.nodesById.get(selection.sourceId) ?? null : null;
|
|
6329
|
-
const target = selection.targetId ? index.nodesById.get(selection.targetId) ?? null : null;
|
|
6330
|
-
const missingNodeIds = [
|
|
6331
|
-
selection.sourceId && !source ? selection.sourceId : null,
|
|
6332
|
-
selection.targetId && !target ? selection.targetId : null
|
|
6333
|
-
].filter((value) => Boolean(value));
|
|
6334
|
-
if (!selection.sourceId && !selection.targetId) {
|
|
6335
|
-
return {
|
|
6336
|
-
status: "idle",
|
|
6337
|
-
selection,
|
|
6338
|
-
source,
|
|
6339
|
-
target,
|
|
6340
|
-
missingNodeIds: [],
|
|
6341
|
-
pathNodes: [],
|
|
6342
|
-
pathEdges: [],
|
|
6343
|
-
highlightNodeIds: [],
|
|
6344
|
-
highlightEdgeIds: [],
|
|
6345
|
-
distance: 0,
|
|
6346
|
-
message: "Select a source and target to trace a path."
|
|
6347
|
-
};
|
|
6348
|
-
}
|
|
6349
|
-
if (!selection.sourceId || !selection.targetId) {
|
|
6350
|
-
return {
|
|
6351
|
-
status: "incomplete",
|
|
6352
|
-
selection,
|
|
6353
|
-
source,
|
|
6354
|
-
target,
|
|
6355
|
-
missingNodeIds,
|
|
6356
|
-
pathNodes: [],
|
|
6357
|
-
pathEdges: [],
|
|
6358
|
-
highlightNodeIds: [],
|
|
6359
|
-
highlightEdgeIds: [],
|
|
6360
|
-
distance: 0,
|
|
6361
|
-
message: "Select both a source and a target to resolve a path."
|
|
6777
|
+
nodeId: node.id,
|
|
6778
|
+
resourceId,
|
|
6779
|
+
label: node.label,
|
|
6780
|
+
resourceType: node.resourceType,
|
|
6781
|
+
healthLevel: healthLevel2,
|
|
6782
|
+
summaryLabel: summaryLabel2,
|
|
6783
|
+
detailLabel,
|
|
6784
|
+
successRate: null,
|
|
6785
|
+
totalRuns: 0,
|
|
6786
|
+
successCount: 0,
|
|
6787
|
+
failureCount: 0,
|
|
6788
|
+
warningCount: 0,
|
|
6789
|
+
pendingCount: checkpointStats.pendingCount,
|
|
6790
|
+
completedCount: checkpointStats.completedCount,
|
|
6791
|
+
expiredCount: checkpointStats.expiredCount,
|
|
6792
|
+
lastActivityAt: checkpointStats.lastDecisionAt,
|
|
6793
|
+
sortScore: checkpointStats.pendingCount * 100 + checkpointStats.expiredCount * 25 + checkpointStats.completedCount
|
|
6362
6794
|
};
|
|
6363
6795
|
}
|
|
6364
|
-
|
|
6796
|
+
const resourceStats = stats.resources[resourceId];
|
|
6797
|
+
if (!resourceStats || resourceStats.totalRuns <= 0) {
|
|
6365
6798
|
return {
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6799
|
+
nodeId: node.id,
|
|
6800
|
+
resourceId,
|
|
6801
|
+
label: node.label,
|
|
6802
|
+
resourceType: node.resourceType,
|
|
6803
|
+
healthLevel: "inactive",
|
|
6804
|
+
summaryLabel: "No runs",
|
|
6805
|
+
detailLabel: "No executions in range",
|
|
6806
|
+
successRate: null,
|
|
6807
|
+
totalRuns: 0,
|
|
6808
|
+
successCount: 0,
|
|
6809
|
+
failureCount: 0,
|
|
6810
|
+
warningCount: 0,
|
|
6811
|
+
pendingCount: 0,
|
|
6812
|
+
completedCount: 0,
|
|
6813
|
+
expiredCount: 0,
|
|
6814
|
+
lastActivityAt: resourceStats?.lastRunAt ?? null,
|
|
6815
|
+
sortScore: 0
|
|
6377
6816
|
};
|
|
6378
6817
|
}
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6818
|
+
const successfulOutcomes = resourceStats.successCount + resourceStats.warningCount;
|
|
6819
|
+
const successRate = successfulOutcomes / resourceStats.totalRuns * 100;
|
|
6820
|
+
const healthLevel = successRate >= 95 ? "healthy" : successRate >= 80 ? "warning" : "critical";
|
|
6821
|
+
const summaryLabel = resourceStats.failureCount > 0 ? `${resourceStats.failureCount} failed` : resourceStats.warningCount > 0 ? `${resourceStats.warningCount} warnings` : `${resourceStats.totalRuns} runs`;
|
|
6822
|
+
return {
|
|
6823
|
+
nodeId: node.id,
|
|
6824
|
+
resourceId,
|
|
6825
|
+
label: node.label,
|
|
6826
|
+
resourceType: node.resourceType,
|
|
6827
|
+
healthLevel,
|
|
6828
|
+
summaryLabel,
|
|
6829
|
+
detailLabel: `${Math.round(successRate)}% healthy`,
|
|
6830
|
+
successRate,
|
|
6831
|
+
totalRuns: resourceStats.totalRuns,
|
|
6832
|
+
successCount: resourceStats.successCount,
|
|
6833
|
+
failureCount: resourceStats.failureCount,
|
|
6834
|
+
warningCount: resourceStats.warningCount,
|
|
6835
|
+
pendingCount: 0,
|
|
6836
|
+
completedCount: 0,
|
|
6837
|
+
expiredCount: 0,
|
|
6838
|
+
lastActivityAt: resourceStats.lastRunAt,
|
|
6839
|
+
sortScore: resourceStats.failureCount * 100 + resourceStats.warningCount * 25 + resourceStats.totalRuns
|
|
6840
|
+
};
|
|
6841
|
+
}
|
|
6842
|
+
function getCommandViewGraphNodeHealth(node, stats) {
|
|
6843
|
+
if (node.kind !== "resource" || !stats) {
|
|
6844
|
+
return null;
|
|
6393
6845
|
}
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
const
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
continue;
|
|
6406
|
-
}
|
|
6407
|
-
visitedNodeIds.add(edge.targetId);
|
|
6408
|
-
predecessorByNodeId.set(edge.targetId, {
|
|
6409
|
-
nodeId: currentNodeId,
|
|
6410
|
-
edgeId: edge.id
|
|
6411
|
-
});
|
|
6412
|
-
if (edge.targetId === target.id) {
|
|
6413
|
-
queue.length = 0;
|
|
6414
|
-
break;
|
|
6415
|
-
}
|
|
6416
|
-
queue.push(edge.targetId);
|
|
6846
|
+
return toResourceHealth(node, stats);
|
|
6847
|
+
}
|
|
6848
|
+
function getCommandViewGraphHealthMap(graph, stats) {
|
|
6849
|
+
const healthByNodeId = /* @__PURE__ */ new Map();
|
|
6850
|
+
if (!graph || !stats) {
|
|
6851
|
+
return healthByNodeId;
|
|
6852
|
+
}
|
|
6853
|
+
for (const node of graph.nodes) {
|
|
6854
|
+
const health = getCommandViewGraphNodeHealth(node, stats);
|
|
6855
|
+
if (health) {
|
|
6856
|
+
healthByNodeId.set(node.id, health);
|
|
6417
6857
|
}
|
|
6418
6858
|
}
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
};
|
|
6859
|
+
return healthByNodeId;
|
|
6860
|
+
}
|
|
6861
|
+
function getHealthRank(level) {
|
|
6862
|
+
switch (level) {
|
|
6863
|
+
case "critical":
|
|
6864
|
+
return 0;
|
|
6865
|
+
case "warning":
|
|
6866
|
+
return 1;
|
|
6867
|
+
case "healthy":
|
|
6868
|
+
return 2;
|
|
6869
|
+
case "inactive":
|
|
6870
|
+
default:
|
|
6871
|
+
return 3;
|
|
6433
6872
|
}
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
break;
|
|
6441
|
-
}
|
|
6442
|
-
const edge = index.edgesById.get(predecessor.edgeId);
|
|
6443
|
-
const previousNode = index.nodesById.get(predecessor.nodeId);
|
|
6444
|
-
if (edge) {
|
|
6445
|
-
pathEdges.push(edge);
|
|
6873
|
+
}
|
|
6874
|
+
function rankCommandViewHotspots(entries, limit = 3) {
|
|
6875
|
+
return [...entries].filter((entry) => entry.healthLevel === "critical" || entry.healthLevel === "warning").sort((left, right) => {
|
|
6876
|
+
const healthRankDelta = getHealthRank(left.healthLevel) - getHealthRank(right.healthLevel);
|
|
6877
|
+
if (healthRankDelta !== 0) {
|
|
6878
|
+
return healthRankDelta;
|
|
6446
6879
|
}
|
|
6447
|
-
if (
|
|
6448
|
-
|
|
6880
|
+
if (right.sortScore !== left.sortScore) {
|
|
6881
|
+
return right.sortScore - left.sortScore;
|
|
6449
6882
|
}
|
|
6450
|
-
|
|
6451
|
-
}
|
|
6452
|
-
pathNodes.reverse();
|
|
6453
|
-
pathEdges.reverse();
|
|
6454
|
-
return {
|
|
6455
|
-
status: "found",
|
|
6456
|
-
selection,
|
|
6457
|
-
source,
|
|
6458
|
-
target,
|
|
6459
|
-
missingNodeIds: [],
|
|
6460
|
-
pathNodes,
|
|
6461
|
-
pathEdges,
|
|
6462
|
-
highlightNodeIds: pathNodes.map((node) => node.id),
|
|
6463
|
-
highlightEdgeIds: pathEdges.map((edge) => edge.id),
|
|
6464
|
-
distance: pathEdges.length,
|
|
6465
|
-
message: `Path found from "${source.label}" to "${target.label}" across ${pathEdges.length} edge${pathEdges.length === 1 ? "" : "s"}.`
|
|
6466
|
-
};
|
|
6883
|
+
return left.label.localeCompare(right.label);
|
|
6884
|
+
}).slice(0, limit);
|
|
6467
6885
|
}
|
|
6468
6886
|
var STATUS_LABELS = {
|
|
6469
6887
|
idle: "Idle",
|
|
@@ -6587,6 +7005,14 @@ var EMPTY_TRACE_SELECTION = {
|
|
|
6587
7005
|
};
|
|
6588
7006
|
var EMPTY_GRAPH_HIDDEN_IDS = /* @__PURE__ */ new Set();
|
|
6589
7007
|
var EMPTY_GRAPH_HIDDEN_EDGE_IDS = /* @__PURE__ */ new Set();
|
|
7008
|
+
var EMPTY_EXPANDED_NODE_IDS = /* @__PURE__ */ new Set();
|
|
7009
|
+
var EMPTY_EXPANDED_EDGE_IDS = /* @__PURE__ */ new Set();
|
|
7010
|
+
var DEFAULT_EXPAND_AROUND_VALUE = {
|
|
7011
|
+
direction: "both",
|
|
7012
|
+
maxDepth: 1,
|
|
7013
|
+
maxResults: 25,
|
|
7014
|
+
includeHiddenResources: true
|
|
7015
|
+
};
|
|
6590
7016
|
var FALLBACK_GRAPH_THEME = {
|
|
6591
7017
|
primary: "#4a6e8e",
|
|
6592
7018
|
background: "#030507",
|
|
@@ -6994,13 +7420,31 @@ function createCytoscapeStyle(tokens) {
|
|
|
6994
7420
|
"target-arrow-color": traceBorder,
|
|
6995
7421
|
"line-style": "solid"
|
|
6996
7422
|
}
|
|
7423
|
+
},
|
|
7424
|
+
{
|
|
7425
|
+
selector: "node.is-expanded-node",
|
|
7426
|
+
style: {
|
|
7427
|
+
opacity: 1,
|
|
7428
|
+
"border-color": mixColors(tokens.primary, tokens.warning, 0.72),
|
|
7429
|
+
"border-width": 3.4,
|
|
7430
|
+
"background-opacity": 1
|
|
7431
|
+
}
|
|
7432
|
+
},
|
|
7433
|
+
{
|
|
7434
|
+
selector: "edge.is-expanded-edge",
|
|
7435
|
+
style: {
|
|
7436
|
+
opacity: 1,
|
|
7437
|
+
width: 3.4,
|
|
7438
|
+
"line-opacity": 0.94,
|
|
7439
|
+
label: "data(label)"
|
|
7440
|
+
}
|
|
6997
7441
|
}
|
|
6998
7442
|
];
|
|
6999
7443
|
}
|
|
7000
|
-
function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds) {
|
|
7444
|
+
function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds) {
|
|
7001
7445
|
cy.batch(() => {
|
|
7002
7446
|
cy.elements().removeClass(
|
|
7003
|
-
"is-hidden is-faded is-context is-selected is-connected is-trace-node is-trace-edge is-trace-endpoint"
|
|
7447
|
+
"is-hidden is-faded is-context is-selected is-connected is-trace-node is-trace-edge is-trace-endpoint is-expanded-node is-expanded-edge"
|
|
7004
7448
|
);
|
|
7005
7449
|
for (const nodeId2 of hiddenIds) {
|
|
7006
7450
|
const node = cy.getElementById(nodeId2);
|
|
@@ -7018,9 +7462,33 @@ function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdg
|
|
|
7018
7462
|
traceResult && (traceResult.highlightNodeIds.length > 0 || traceResult.highlightEdgeIds.length > 0)
|
|
7019
7463
|
);
|
|
7020
7464
|
if (!selectedElement && !hasTrace) {
|
|
7465
|
+
for (const nodeId2 of expandedNodeIds) {
|
|
7466
|
+
const node = cy.getElementById(nodeId2);
|
|
7467
|
+
if (!node.empty()) {
|
|
7468
|
+
node.addClass("is-expanded-node");
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
for (const edgeId2 of expandedEdgeIds) {
|
|
7472
|
+
const edge2 = cy.getElementById(edgeId2);
|
|
7473
|
+
if (!edge2.empty()) {
|
|
7474
|
+
edge2.addClass("is-expanded-edge");
|
|
7475
|
+
}
|
|
7476
|
+
}
|
|
7021
7477
|
return;
|
|
7022
7478
|
}
|
|
7023
7479
|
cy.elements().addClass("is-faded");
|
|
7480
|
+
for (const nodeId2 of expandedNodeIds) {
|
|
7481
|
+
const node = cy.getElementById(nodeId2);
|
|
7482
|
+
if (!node.empty()) {
|
|
7483
|
+
node.removeClass("is-faded").addClass("is-context is-expanded-node");
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
for (const edgeId2 of expandedEdgeIds) {
|
|
7487
|
+
const edge2 = cy.getElementById(edgeId2);
|
|
7488
|
+
if (!edge2.empty()) {
|
|
7489
|
+
edge2.removeClass("is-faded").addClass("is-connected is-expanded-edge");
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7024
7492
|
if (traceResult) {
|
|
7025
7493
|
for (const nodeId2 of traceResult.highlightNodeIds) {
|
|
7026
7494
|
const node = cy.getElementById(nodeId2);
|
|
@@ -7097,6 +7565,8 @@ function OrganizationGraphCanvas({
|
|
|
7097
7565
|
traceResult,
|
|
7098
7566
|
hiddenIds,
|
|
7099
7567
|
hiddenEdgeIds,
|
|
7568
|
+
expandedNodeIds,
|
|
7569
|
+
expandedEdgeIds,
|
|
7100
7570
|
themeTokens,
|
|
7101
7571
|
commandViewHealthByNodeId,
|
|
7102
7572
|
focusRequest,
|
|
@@ -7158,7 +7628,7 @@ function OrganizationGraphCanvas({
|
|
|
7158
7628
|
});
|
|
7159
7629
|
});
|
|
7160
7630
|
resizeObserver.observe(containerRef.current);
|
|
7161
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7631
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7162
7632
|
return () => {
|
|
7163
7633
|
resizeObserver.disconnect();
|
|
7164
7634
|
cy.destroy();
|
|
@@ -7172,7 +7642,7 @@ function OrganizationGraphCanvas({
|
|
|
7172
7642
|
}
|
|
7173
7643
|
syncCytoscapeElements(cy, elements);
|
|
7174
7644
|
cy.layout(getLayoutOptions(mode, selectedElement, traceResult)).run();
|
|
7175
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7645
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7176
7646
|
}, [elements]);
|
|
7177
7647
|
useEffect(() => {
|
|
7178
7648
|
const cy = cytoscapeRef.current;
|
|
@@ -7191,7 +7661,7 @@ function OrganizationGraphCanvas({
|
|
|
7191
7661
|
if (!cy) {
|
|
7192
7662
|
return;
|
|
7193
7663
|
}
|
|
7194
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7664
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7195
7665
|
if (mode === "map" && selectedElement?.type === "node") {
|
|
7196
7666
|
const node = cy.getElementById(selectedElement.id);
|
|
7197
7667
|
if (!node.empty()) {
|
|
@@ -7211,7 +7681,7 @@ function OrganizationGraphCanvas({
|
|
|
7211
7681
|
);
|
|
7212
7682
|
}
|
|
7213
7683
|
}
|
|
7214
|
-
}, [hiddenEdgeIds, hiddenIds, mode, selectedElement, traceResult]);
|
|
7684
|
+
}, [expandedEdgeIds, expandedNodeIds, hiddenEdgeIds, hiddenIds, mode, selectedElement, traceResult]);
|
|
7215
7685
|
useEffect(() => {
|
|
7216
7686
|
const cy = cytoscapeRef.current;
|
|
7217
7687
|
if (!cy || !focusRequest) {
|
|
@@ -7354,6 +7824,10 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7354
7824
|
const [selectedElement, setSelectedElement] = useState(null);
|
|
7355
7825
|
const [focusRequest, setFocusRequest] = useState(null);
|
|
7356
7826
|
const [pathTraceSelection, setPathTraceSelection] = useState(EMPTY_TRACE_SELECTION);
|
|
7827
|
+
const [expandAroundValue, setExpandAroundValue] = useState(DEFAULT_EXPAND_AROUND_VALUE);
|
|
7828
|
+
const [expandAroundPreview, setExpandAroundPreview] = useState(null);
|
|
7829
|
+
const [appliedExpandAroundNodeIds, setAppliedExpandAroundNodeIds] = useState(EMPTY_EXPANDED_NODE_IDS);
|
|
7830
|
+
const [appliedExpandAroundEdgeIds, setAppliedExpandAroundEdgeIds] = useState(EMPTY_EXPANDED_EDGE_IDS);
|
|
7357
7831
|
const { filters, resetFilters, updateFilters } = useOrganizationGraphFilters(lensConfig.initialFilters);
|
|
7358
7832
|
const toolbarResetValue = useMemo(
|
|
7359
7833
|
() => createOrganizationGraphFilters(lensConfig.initialFilters),
|
|
@@ -7385,6 +7859,12 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7385
7859
|
commandViewData
|
|
7386
7860
|
});
|
|
7387
7861
|
}, [baseGraph, commandViewData, deferredFilters]);
|
|
7862
|
+
const commandViewRevealIds = useMemo(() => {
|
|
7863
|
+
if (appliedExpandAroundNodeIds.size === 0) {
|
|
7864
|
+
return revealedIds;
|
|
7865
|
+
}
|
|
7866
|
+
return /* @__PURE__ */ new Set([...revealedIds, ...appliedExpandAroundNodeIds]);
|
|
7867
|
+
}, [appliedExpandAroundNodeIds, revealedIds]);
|
|
7388
7868
|
const visibilityProjection = useMemo(() => {
|
|
7389
7869
|
if (!graph || lens !== "command-view") {
|
|
7390
7870
|
const resourceCount = getGraphCountByKind(graph, "resource");
|
|
@@ -7403,10 +7883,10 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7403
7883
|
resourcesHidden,
|
|
7404
7884
|
diagnosticsHidden,
|
|
7405
7885
|
diagnosticCategories,
|
|
7406
|
-
revealedIds,
|
|
7886
|
+
revealedIds: commandViewRevealIds,
|
|
7407
7887
|
mode
|
|
7408
7888
|
});
|
|
7409
|
-
}, [commandViewData, diagnosticCategories, diagnosticsHidden, graph, lens, mode, resourcesHidden
|
|
7889
|
+
}, [commandViewData, commandViewRevealIds, diagnosticCategories, diagnosticsHidden, graph, lens, mode, resourcesHidden]);
|
|
7410
7890
|
const visibleGraph = useMemo(() => {
|
|
7411
7891
|
if (!graph || visibilityProjection.hiddenIds.size === 0) {
|
|
7412
7892
|
return graph;
|
|
@@ -7489,6 +7969,43 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7489
7969
|
nonce: Date.now()
|
|
7490
7970
|
});
|
|
7491
7971
|
});
|
|
7972
|
+
const clearExpandAroundState = useEffectEvent(() => {
|
|
7973
|
+
setExpandAroundPreview(null);
|
|
7974
|
+
setAppliedExpandAroundNodeIds(EMPTY_EXPANDED_NODE_IDS);
|
|
7975
|
+
setAppliedExpandAroundEdgeIds(EMPTY_EXPANDED_EDGE_IDS);
|
|
7976
|
+
});
|
|
7977
|
+
const previewExpandAround = useEffectEvent(() => {
|
|
7978
|
+
if (lens !== "command-view" || !graph || selectedElement?.type !== "node") {
|
|
7979
|
+
setExpandAroundPreview(null);
|
|
7980
|
+
return;
|
|
7981
|
+
}
|
|
7982
|
+
setExpandAroundPreview(
|
|
7983
|
+
expandAroundGraph(
|
|
7984
|
+
graph,
|
|
7985
|
+
{
|
|
7986
|
+
rootNodeId: selectedElement.id,
|
|
7987
|
+
...expandAroundValue
|
|
7988
|
+
},
|
|
7989
|
+
{
|
|
7990
|
+
alreadyVisibleNodeIds: visibleGraph?.nodes.map((node) => node.id) ?? [],
|
|
7991
|
+
hiddenResourceNodeIds: visibilityProjection.hiddenIds
|
|
7992
|
+
}
|
|
7993
|
+
)
|
|
7994
|
+
);
|
|
7995
|
+
});
|
|
7996
|
+
const applyExpandAroundPreview = useEffectEvent(() => {
|
|
7997
|
+
if (!expandAroundPreview || selectedElement?.type !== "node") {
|
|
7998
|
+
return;
|
|
7999
|
+
}
|
|
8000
|
+
setAppliedExpandAroundNodeIds(new Set(expandAroundPreview.expandedNodeIds));
|
|
8001
|
+
setAppliedExpandAroundEdgeIds(new Set(expandAroundPreview.expandedEdgeIds));
|
|
8002
|
+
setMode("map");
|
|
8003
|
+
setSelectedElement({ type: "node", id: selectedElement.id });
|
|
8004
|
+
focusGraphNode(selectedElement.id);
|
|
8005
|
+
if (expandAroundPreview.counts.hiddenResourceNodes > 0) {
|
|
8006
|
+
markVisibilityInteraction();
|
|
8007
|
+
}
|
|
8008
|
+
});
|
|
7492
8009
|
const focusCommandViewResource = useEffectEvent((resourceId) => {
|
|
7493
8010
|
const focusNode = visibleGraph?.nodes.find((node) => node.kind === "resource" && node.sourceId === resourceId);
|
|
7494
8011
|
if (!focusNode) {
|
|
@@ -7501,6 +8018,7 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7501
8018
|
const handleResetFilters = useEffectEvent(() => {
|
|
7502
8019
|
resetFilters();
|
|
7503
8020
|
clearRevealedIds();
|
|
8021
|
+
clearExpandAroundState();
|
|
7504
8022
|
setSelectedElement(null);
|
|
7505
8023
|
setPathTraceSelection(EMPTY_TRACE_SELECTION);
|
|
7506
8024
|
});
|
|
@@ -7508,6 +8026,7 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7508
8026
|
setResourcesHidden(value);
|
|
7509
8027
|
if (value) {
|
|
7510
8028
|
clearRevealedIds();
|
|
8029
|
+
clearExpandAroundState();
|
|
7511
8030
|
setSelectedElement(null);
|
|
7512
8031
|
}
|
|
7513
8032
|
});
|
|
@@ -7515,20 +8034,23 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7515
8034
|
setDiagnosticsHidden(value);
|
|
7516
8035
|
if (value) {
|
|
7517
8036
|
clearRevealedIds();
|
|
8037
|
+
clearExpandAroundState();
|
|
7518
8038
|
}
|
|
7519
8039
|
});
|
|
7520
8040
|
const revealAllResources = useEffectEvent(() => {
|
|
7521
8041
|
setResourcesHidden(false);
|
|
7522
8042
|
setDiagnosticsHidden(false);
|
|
7523
8043
|
clearRevealedIds();
|
|
8044
|
+
clearExpandAroundState();
|
|
7524
8045
|
});
|
|
7525
8046
|
const handleSelectElement = useEffectEvent((element) => {
|
|
7526
8047
|
if (!element) {
|
|
7527
|
-
if (!selectedElement && revealedIds.size === 0) {
|
|
8048
|
+
if (!selectedElement && revealedIds.size === 0 && appliedExpandAroundNodeIds.size === 0) {
|
|
7528
8049
|
return;
|
|
7529
8050
|
}
|
|
7530
8051
|
setSelectedElement(null);
|
|
7531
8052
|
clearRevealedIds();
|
|
8053
|
+
clearExpandAroundState();
|
|
7532
8054
|
return;
|
|
7533
8055
|
}
|
|
7534
8056
|
if (mode === "map" && element.type === "node" && selectedElement?.type === "node" && selectedElement.id === element.id) {
|
|
@@ -7543,7 +8065,9 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7543
8065
|
}
|
|
7544
8066
|
} else {
|
|
7545
8067
|
clearRevealedIds();
|
|
8068
|
+
clearExpandAroundState();
|
|
7546
8069
|
}
|
|
8070
|
+
setExpandAroundPreview(null);
|
|
7547
8071
|
setSelectedElement(element);
|
|
7548
8072
|
});
|
|
7549
8073
|
useEffect(() => {
|
|
@@ -7554,8 +8078,19 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7554
8078
|
if (!elementExists) {
|
|
7555
8079
|
setSelectedElement(null);
|
|
7556
8080
|
clearRevealedIds();
|
|
8081
|
+
clearExpandAroundState();
|
|
7557
8082
|
}
|
|
7558
|
-
}, [clearRevealedIds, selectedElement, visibleGraph]);
|
|
8083
|
+
}, [clearExpandAroundState, clearRevealedIds, selectedElement, visibleGraph]);
|
|
8084
|
+
useEffect(() => {
|
|
8085
|
+
if (lens !== "command-view" || !graph || appliedExpandAroundNodeIds.size === 0) {
|
|
8086
|
+
return;
|
|
8087
|
+
}
|
|
8088
|
+
const graphNodeIds = new Set(graph.nodes.map((node) => node.id));
|
|
8089
|
+
const expansionStillExists = [...appliedExpandAroundNodeIds].some((nodeId2) => graphNodeIds.has(nodeId2));
|
|
8090
|
+
if (!expansionStillExists) {
|
|
8091
|
+
clearExpandAroundState();
|
|
8092
|
+
}
|
|
8093
|
+
}, [appliedExpandAroundNodeIds, clearExpandAroundState, graph, lens]);
|
|
7559
8094
|
useEffect(() => {
|
|
7560
8095
|
if (lens !== "command-view") {
|
|
7561
8096
|
return;
|
|
@@ -7658,6 +8193,8 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7658
8193
|
traceResult: activeTraceResult,
|
|
7659
8194
|
hiddenIds: EMPTY_GRAPH_HIDDEN_IDS,
|
|
7660
8195
|
hiddenEdgeIds: EMPTY_GRAPH_HIDDEN_EDGE_IDS,
|
|
8196
|
+
expandedNodeIds: lens === "command-view" ? appliedExpandAroundNodeIds : EMPTY_EXPANDED_NODE_IDS,
|
|
8197
|
+
expandedEdgeIds: lens === "command-view" ? appliedExpandAroundEdgeIds : EMPTY_EXPANDED_EDGE_IDS,
|
|
7661
8198
|
themeTokens,
|
|
7662
8199
|
commandViewHealthByNodeId,
|
|
7663
8200
|
focusRequest,
|
|
@@ -7897,9 +8434,27 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7897
8434
|
selectedElement,
|
|
7898
8435
|
supplementalSummary: selectionOperationalSummary,
|
|
7899
8436
|
followUpSections,
|
|
8437
|
+
expandAroundPanel: lens === "command-view" ? /* @__PURE__ */ jsx(
|
|
8438
|
+
ExpandAroundPanel,
|
|
8439
|
+
{
|
|
8440
|
+
selectedNode: selectedGraphNode,
|
|
8441
|
+
value: expandAroundValue,
|
|
8442
|
+
result: expandAroundPreview,
|
|
8443
|
+
appliedNodeCount: appliedExpandAroundNodeIds.size,
|
|
8444
|
+
appliedEdgeCount: appliedExpandAroundEdgeIds.size,
|
|
8445
|
+
onChange: (next) => {
|
|
8446
|
+
setExpandAroundValue(next);
|
|
8447
|
+
setExpandAroundPreview(null);
|
|
8448
|
+
},
|
|
8449
|
+
onPreview: previewExpandAround,
|
|
8450
|
+
onApply: applyExpandAroundPreview,
|
|
8451
|
+
onClear: clearExpandAroundState
|
|
8452
|
+
}
|
|
8453
|
+
) : null,
|
|
7900
8454
|
onClearSelection: () => {
|
|
7901
8455
|
setSelectedElement(null);
|
|
7902
8456
|
clearRevealedIds();
|
|
8457
|
+
clearExpandAroundState();
|
|
7903
8458
|
}
|
|
7904
8459
|
}
|
|
7905
8460
|
) }),
|