@elevasis/ui 2.22.0 → 2.23.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/{chunk-LKVBEE63.js → chunk-7PGEGSUM.js} +1 -1
- package/dist/{chunk-GJ7EIABJ.js → chunk-D3KQAABP.js} +1 -1
- package/dist/{chunk-IOTLB6ND.js → chunk-EPV7NU2E.js} +22 -8
- package/dist/{chunk-WWJ6S2HQ.js → chunk-FXWETLEB.js} +1 -1
- package/dist/{chunk-B4FHWKEF.js → chunk-GUJUK6EH.js} +22 -9
- package/dist/{chunk-LVJGPE6H.js → chunk-N6WLOWOD.js} +1 -1
- package/dist/{chunk-BSZRKBAW.js → chunk-PTUOINQ2.js} +1 -1
- package/dist/{chunk-COG4ABRI.js → chunk-PXGSJNBH.js} +1 -1
- package/dist/{chunk-IBUYJXA3.js → chunk-YU6MBDVO.js} +962 -343
- package/dist/components/index.d.ts +12 -14
- package/dist/components/index.js +29 -22
- package/dist/features/auth/index.d.ts +9 -12
- package/dist/features/crm/index.d.ts +9 -12
- package/dist/features/crm/index.js +2 -2
- package/dist/features/dashboard/index.js +2 -2
- package/dist/features/delivery/index.d.ts +9 -12
- package/dist/features/delivery/index.js +2 -2
- package/dist/features/lead-gen/index.js +2 -2
- package/dist/features/monitoring/index.js +3 -3
- package/dist/features/monitoring/requests/index.js +1 -1
- package/dist/features/operations/index.js +4 -4
- package/dist/features/settings/index.d.ts +9 -12
- package/dist/features/settings/index.js +2 -2
- package/dist/hooks/delivery/index.d.ts +9 -12
- package/dist/hooks/index.d.ts +33 -28
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/published.d.ts +33 -28
- package/dist/hooks/published.js +1 -1
- package/dist/index.d.ts +33 -28
- package/dist/index.js +1 -1
- package/dist/initialization/index.d.ts +9 -12
- package/dist/profile/index.d.ts +9 -12
- package/dist/supabase/index.d.ts +18 -24
- package/dist/types/index.d.ts +9 -12
- package/package.json +4 -4
|
@@ -1,14 +1,14 @@
|
|
|
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 { ResourceHealthPanel } from './chunk-
|
|
3
|
+
import { BaseNode, useGraphTheme, BaseEdge, FormFieldRenderer, ExecutionStats, UnifiedWorkflowGraph, WorkflowExecutionTimeline, AgentExecutionVisualizer, AgentExecutionTimeline, GraphBackground, GraphFitViewButton, GraphFitViewHandler } from './chunk-7PGEGSUM.js';
|
|
4
|
+
import { ResourceHealthPanel } from './chunk-D3KQAABP.js';
|
|
5
5
|
import { useCyberColors, CyberDonut } from './chunk-TSSKOQBX.js';
|
|
6
6
|
import { AppShellLoader } from './chunk-M25JL54Z.js';
|
|
7
7
|
import { PageContainer } from './chunk-BZZCNLT6.js';
|
|
8
8
|
import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
|
|
9
9
|
import { CustomModal, ConfirmationModal } from './chunk-KVJ3LFH2.js';
|
|
10
10
|
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-
|
|
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-GUJUK6EH.js';
|
|
12
12
|
import { showApiErrorNotification, showSuccessNotification } from './chunk-Z6FAH4XV.js';
|
|
13
13
|
import { useGraphHighlighting, calculateGraphHeight, Graph_module_css_default, GRAPH_CONSTANTS } from './chunk-22UVE3RA.js';
|
|
14
14
|
import { useMergedExecution } from './chunk-3ZMAGTWF.js';
|
|
@@ -25,7 +25,7 @@ import { ResourceStatusColors, toWorkflowLogMessages } from './chunk-KRWALB24.js
|
|
|
25
25
|
import { useInitialization } from './chunk-DK2HVHCY.js';
|
|
26
26
|
import { useOrganization } from './chunk-DD3CCMCZ.js';
|
|
27
27
|
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';
|
|
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, NumberInput, MultiSelect, Switch } from '@mantine/core';
|
|
29
29
|
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
30
|
import { useForm } from '@mantine/form';
|
|
31
31
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -4684,7 +4684,7 @@ function titleCase2(value) {
|
|
|
4684
4684
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
4685
4685
|
}
|
|
4686
4686
|
function MetricCard({ metric }) {
|
|
4687
|
-
return /* @__PURE__ */ jsx(
|
|
4687
|
+
return /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
4688
4688
|
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: metric.label }),
|
|
4689
4689
|
/* @__PURE__ */ jsx(Text, { size: "lg", fw: 800, children: metric.value }),
|
|
4690
4690
|
metric.hint ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: metric.hint }) : null
|
|
@@ -4769,6 +4769,7 @@ function OrganizationGraphDetailPanel({
|
|
|
4769
4769
|
selectedElement,
|
|
4770
4770
|
supplementalSummary,
|
|
4771
4771
|
followUpSections,
|
|
4772
|
+
expandAroundPanel,
|
|
4772
4773
|
onClearSelection,
|
|
4773
4774
|
className
|
|
4774
4775
|
}) {
|
|
@@ -4806,6 +4807,7 @@ function OrganizationGraphDetailPanel({
|
|
|
4806
4807
|
onClearSelection ? /* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: onClearSelection, children: "Clear" }) : null
|
|
4807
4808
|
] }),
|
|
4808
4809
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, md: 4 }, spacing: "sm", children: state.metrics.map((metric) => /* @__PURE__ */ jsx(MetricCard, { metric }, metric.label)) }),
|
|
4810
|
+
expandAroundPanel,
|
|
4809
4811
|
supplementalSummary && (supplementalSummary.metrics.length > 0 || supplementalSummary.metadata.length > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4810
4812
|
/* @__PURE__ */ jsx(
|
|
4811
4813
|
Divider,
|
|
@@ -5833,6 +5835,717 @@ function buildCommandViewDrillDownSections({
|
|
|
5833
5835
|
}
|
|
5834
5836
|
return sections;
|
|
5835
5837
|
}
|
|
5838
|
+
|
|
5839
|
+
// src/features/operations/organization-graph/path-tracing/trace.ts
|
|
5840
|
+
var NODE_KIND_ORDER = {
|
|
5841
|
+
organization: 0,
|
|
5842
|
+
feature: 1,
|
|
5843
|
+
surface: 2,
|
|
5844
|
+
capability: 3,
|
|
5845
|
+
entity: 4,
|
|
5846
|
+
resource: 5
|
|
5847
|
+
};
|
|
5848
|
+
var NODE_KIND_LABEL = {
|
|
5849
|
+
organization: "Organization",
|
|
5850
|
+
feature: "Feature",
|
|
5851
|
+
surface: "Surface",
|
|
5852
|
+
capability: "Capability",
|
|
5853
|
+
entity: "Entity",
|
|
5854
|
+
resource: "Resource"
|
|
5855
|
+
};
|
|
5856
|
+
function getNodeLabel(node) {
|
|
5857
|
+
return node.label || node.sourceId || node.id;
|
|
5858
|
+
}
|
|
5859
|
+
function compareTraceNodes(a, b) {
|
|
5860
|
+
const kindDelta = NODE_KIND_ORDER[a.kind] - NODE_KIND_ORDER[b.kind];
|
|
5861
|
+
if (kindDelta !== 0) {
|
|
5862
|
+
return kindDelta;
|
|
5863
|
+
}
|
|
5864
|
+
const labelDelta = getNodeLabel(a).localeCompare(getNodeLabel(b));
|
|
5865
|
+
if (labelDelta !== 0) {
|
|
5866
|
+
return labelDelta;
|
|
5867
|
+
}
|
|
5868
|
+
return a.id.localeCompare(b.id);
|
|
5869
|
+
}
|
|
5870
|
+
function buildMissingNodeMessage(selection, missingNodeIds) {
|
|
5871
|
+
if (missingNodeIds.length === 0) {
|
|
5872
|
+
return "The selected trace is not available.";
|
|
5873
|
+
}
|
|
5874
|
+
if (missingNodeIds.length === 1) {
|
|
5875
|
+
const missingId = missingNodeIds[0];
|
|
5876
|
+
return `Graph node "${missingId}" is not available.`;
|
|
5877
|
+
}
|
|
5878
|
+
return `Graph nodes "${selection.sourceId}" and "${selection.targetId}" are not available.`;
|
|
5879
|
+
}
|
|
5880
|
+
function buildPathNotFoundMessage(source, target) {
|
|
5881
|
+
return `No directed path found from "${source.label}" to "${target.label}".`;
|
|
5882
|
+
}
|
|
5883
|
+
function buildOrganizationGraphTraceIndex(graph) {
|
|
5884
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
5885
|
+
const edgesById = /* @__PURE__ */ new Map();
|
|
5886
|
+
const outgoingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
5887
|
+
const incomingEdgesByNodeId = /* @__PURE__ */ new Map();
|
|
5888
|
+
for (const node of graph.nodes) {
|
|
5889
|
+
nodesById.set(node.id, node);
|
|
5890
|
+
outgoingEdgesByNodeId.set(node.id, []);
|
|
5891
|
+
incomingEdgesByNodeId.set(node.id, []);
|
|
5892
|
+
}
|
|
5893
|
+
for (const edge of graph.edges) {
|
|
5894
|
+
edgesById.set(edge.id, edge);
|
|
5895
|
+
const outgoingEdges = outgoingEdgesByNodeId.get(edge.sourceId);
|
|
5896
|
+
if (outgoingEdges) {
|
|
5897
|
+
outgoingEdges.push(edge);
|
|
5898
|
+
}
|
|
5899
|
+
const incomingEdges = incomingEdgesByNodeId.get(edge.targetId);
|
|
5900
|
+
if (incomingEdges) {
|
|
5901
|
+
incomingEdges.push(edge);
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
return {
|
|
5905
|
+
nodesById,
|
|
5906
|
+
edgesById,
|
|
5907
|
+
outgoingEdgesByNodeId,
|
|
5908
|
+
incomingEdgesByNodeId
|
|
5909
|
+
};
|
|
5910
|
+
}
|
|
5911
|
+
function getOrganizationGraphTraceNodeKindLabel(kind) {
|
|
5912
|
+
return NODE_KIND_LABEL[kind];
|
|
5913
|
+
}
|
|
5914
|
+
function formatOrganizationGraphTraceNodeOptionLabel(option) {
|
|
5915
|
+
return `${option.label} \xB7 ${getOrganizationGraphTraceNodeKindLabel(option.kind)}`;
|
|
5916
|
+
}
|
|
5917
|
+
function getOrganizationGraphTraceNodeOptions(graph) {
|
|
5918
|
+
return [...graph.nodes].sort(compareTraceNodes).map((node) => ({
|
|
5919
|
+
id: node.id,
|
|
5920
|
+
label: getNodeLabel(node),
|
|
5921
|
+
kind: node.kind,
|
|
5922
|
+
sourceId: node.sourceId,
|
|
5923
|
+
description: node.description,
|
|
5924
|
+
enabled: node.enabled
|
|
5925
|
+
}));
|
|
5926
|
+
}
|
|
5927
|
+
function resolveOrganizationGraphPathTrace(graph, selection) {
|
|
5928
|
+
const index = buildOrganizationGraphTraceIndex(graph);
|
|
5929
|
+
const source = selection.sourceId ? index.nodesById.get(selection.sourceId) ?? null : null;
|
|
5930
|
+
const target = selection.targetId ? index.nodesById.get(selection.targetId) ?? null : null;
|
|
5931
|
+
const missingNodeIds = [
|
|
5932
|
+
selection.sourceId && !source ? selection.sourceId : null,
|
|
5933
|
+
selection.targetId && !target ? selection.targetId : null
|
|
5934
|
+
].filter((value) => Boolean(value));
|
|
5935
|
+
if (!selection.sourceId && !selection.targetId) {
|
|
5936
|
+
return {
|
|
5937
|
+
status: "idle",
|
|
5938
|
+
selection,
|
|
5939
|
+
source,
|
|
5940
|
+
target,
|
|
5941
|
+
missingNodeIds: [],
|
|
5942
|
+
pathNodes: [],
|
|
5943
|
+
pathEdges: [],
|
|
5944
|
+
highlightNodeIds: [],
|
|
5945
|
+
highlightEdgeIds: [],
|
|
5946
|
+
distance: 0,
|
|
5947
|
+
message: "Select a source and target to trace a path."
|
|
5948
|
+
};
|
|
5949
|
+
}
|
|
5950
|
+
if (!selection.sourceId || !selection.targetId) {
|
|
5951
|
+
return {
|
|
5952
|
+
status: "incomplete",
|
|
5953
|
+
selection,
|
|
5954
|
+
source,
|
|
5955
|
+
target,
|
|
5956
|
+
missingNodeIds,
|
|
5957
|
+
pathNodes: [],
|
|
5958
|
+
pathEdges: [],
|
|
5959
|
+
highlightNodeIds: [],
|
|
5960
|
+
highlightEdgeIds: [],
|
|
5961
|
+
distance: 0,
|
|
5962
|
+
message: "Select both a source and a target to resolve a path."
|
|
5963
|
+
};
|
|
5964
|
+
}
|
|
5965
|
+
if (missingNodeIds.length > 0 || !source || !target) {
|
|
5966
|
+
return {
|
|
5967
|
+
status: "missing-node",
|
|
5968
|
+
selection,
|
|
5969
|
+
source,
|
|
5970
|
+
target,
|
|
5971
|
+
missingNodeIds,
|
|
5972
|
+
pathNodes: [],
|
|
5973
|
+
pathEdges: [],
|
|
5974
|
+
highlightNodeIds: [],
|
|
5975
|
+
highlightEdgeIds: [],
|
|
5976
|
+
distance: 0,
|
|
5977
|
+
message: buildMissingNodeMessage(selection, missingNodeIds)
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
if (source.id === target.id) {
|
|
5981
|
+
return {
|
|
5982
|
+
status: "found",
|
|
5983
|
+
selection,
|
|
5984
|
+
source,
|
|
5985
|
+
target,
|
|
5986
|
+
missingNodeIds: [],
|
|
5987
|
+
pathNodes: [source],
|
|
5988
|
+
pathEdges: [],
|
|
5989
|
+
highlightNodeIds: [source.id],
|
|
5990
|
+
highlightEdgeIds: [],
|
|
5991
|
+
distance: 0,
|
|
5992
|
+
message: `Source and target already point to "${source.label}".`
|
|
5993
|
+
};
|
|
5994
|
+
}
|
|
5995
|
+
const visitedNodeIds = /* @__PURE__ */ new Set([source.id]);
|
|
5996
|
+
const predecessorByNodeId = /* @__PURE__ */ new Map();
|
|
5997
|
+
const queue = [source.id];
|
|
5998
|
+
while (queue.length > 0) {
|
|
5999
|
+
const currentNodeId = queue.shift();
|
|
6000
|
+
if (!currentNodeId) {
|
|
6001
|
+
continue;
|
|
6002
|
+
}
|
|
6003
|
+
const outgoingEdges = index.outgoingEdgesByNodeId.get(currentNodeId) ?? [];
|
|
6004
|
+
for (const edge of outgoingEdges) {
|
|
6005
|
+
if (visitedNodeIds.has(edge.targetId)) {
|
|
6006
|
+
continue;
|
|
6007
|
+
}
|
|
6008
|
+
visitedNodeIds.add(edge.targetId);
|
|
6009
|
+
predecessorByNodeId.set(edge.targetId, {
|
|
6010
|
+
nodeId: currentNodeId,
|
|
6011
|
+
edgeId: edge.id
|
|
6012
|
+
});
|
|
6013
|
+
if (edge.targetId === target.id) {
|
|
6014
|
+
queue.length = 0;
|
|
6015
|
+
break;
|
|
6016
|
+
}
|
|
6017
|
+
queue.push(edge.targetId);
|
|
6018
|
+
}
|
|
6019
|
+
}
|
|
6020
|
+
if (!predecessorByNodeId.has(target.id)) {
|
|
6021
|
+
return {
|
|
6022
|
+
status: "not-found",
|
|
6023
|
+
selection,
|
|
6024
|
+
source,
|
|
6025
|
+
target,
|
|
6026
|
+
missingNodeIds: [],
|
|
6027
|
+
pathNodes: [],
|
|
6028
|
+
pathEdges: [],
|
|
6029
|
+
highlightNodeIds: [],
|
|
6030
|
+
highlightEdgeIds: [],
|
|
6031
|
+
distance: 0,
|
|
6032
|
+
message: buildPathNotFoundMessage(source, target)
|
|
6033
|
+
};
|
|
6034
|
+
}
|
|
6035
|
+
const pathNodes = [target];
|
|
6036
|
+
const pathEdges = [];
|
|
6037
|
+
let cursorNodeId = target.id;
|
|
6038
|
+
while (cursorNodeId !== source.id) {
|
|
6039
|
+
const predecessor = predecessorByNodeId.get(cursorNodeId);
|
|
6040
|
+
if (!predecessor) {
|
|
6041
|
+
break;
|
|
6042
|
+
}
|
|
6043
|
+
const edge = index.edgesById.get(predecessor.edgeId);
|
|
6044
|
+
const previousNode = index.nodesById.get(predecessor.nodeId);
|
|
6045
|
+
if (edge) {
|
|
6046
|
+
pathEdges.push(edge);
|
|
6047
|
+
}
|
|
6048
|
+
if (previousNode) {
|
|
6049
|
+
pathNodes.push(previousNode);
|
|
6050
|
+
}
|
|
6051
|
+
cursorNodeId = predecessor.nodeId;
|
|
6052
|
+
}
|
|
6053
|
+
pathNodes.reverse();
|
|
6054
|
+
pathEdges.reverse();
|
|
6055
|
+
return {
|
|
6056
|
+
status: "found",
|
|
6057
|
+
selection,
|
|
6058
|
+
source,
|
|
6059
|
+
target,
|
|
6060
|
+
missingNodeIds: [],
|
|
6061
|
+
pathNodes,
|
|
6062
|
+
pathEdges,
|
|
6063
|
+
highlightNodeIds: pathNodes.map((node) => node.id),
|
|
6064
|
+
highlightEdgeIds: pathEdges.map((edge) => edge.id),
|
|
6065
|
+
distance: pathEdges.length,
|
|
6066
|
+
message: `Path found from "${source.label}" to "${target.label}" across ${pathEdges.length} edge${pathEdges.length === 1 ? "" : "s"}.`
|
|
6067
|
+
};
|
|
6068
|
+
}
|
|
6069
|
+
|
|
6070
|
+
// src/features/operations/organization-graph/expand-around/expandAroundGraph.ts
|
|
6071
|
+
var DEFAULT_MAX_DEPTH = 1;
|
|
6072
|
+
var DEFAULT_MAX_RESULTS = 25;
|
|
6073
|
+
var ORG_MODEL_ROOT_KINDS = /* @__PURE__ */ new Set([
|
|
6074
|
+
"feature",
|
|
6075
|
+
"surface",
|
|
6076
|
+
"entity",
|
|
6077
|
+
"capability"
|
|
6078
|
+
]);
|
|
6079
|
+
var PRESET_EDGE_KINDS = {
|
|
6080
|
+
coverage: ["contains", "exposes", "operates-on", "maps_to", "references"],
|
|
6081
|
+
"operational-dependencies": ["references"],
|
|
6082
|
+
"org-context": ["contains", "exposes", "operates-on", "maps_to"],
|
|
6083
|
+
"impact-path": ["references"]
|
|
6084
|
+
};
|
|
6085
|
+
var PRESET_RELATIONSHIP_TYPES = {
|
|
6086
|
+
"operational-dependencies": ["triggers", "uses", "approval"],
|
|
6087
|
+
"impact-path": ["triggers", "uses", "approval"]
|
|
6088
|
+
};
|
|
6089
|
+
var PRESET_DIRECTIONS = {
|
|
6090
|
+
coverage: "both",
|
|
6091
|
+
"operational-dependencies": "both",
|
|
6092
|
+
"org-context": "both",
|
|
6093
|
+
"impact-path": "both"
|
|
6094
|
+
};
|
|
6095
|
+
function toSet(values) {
|
|
6096
|
+
if (!values || values.length === 0) {
|
|
6097
|
+
return null;
|
|
6098
|
+
}
|
|
6099
|
+
return new Set(values);
|
|
6100
|
+
}
|
|
6101
|
+
function clampMaxDepth(maxDepth) {
|
|
6102
|
+
if (maxDepth === 2 || maxDepth === 3) {
|
|
6103
|
+
return maxDepth;
|
|
6104
|
+
}
|
|
6105
|
+
return 1;
|
|
6106
|
+
}
|
|
6107
|
+
function resolvePreset(rootNode, preset) {
|
|
6108
|
+
if (preset) {
|
|
6109
|
+
return preset;
|
|
6110
|
+
}
|
|
6111
|
+
if (!rootNode) {
|
|
6112
|
+
return null;
|
|
6113
|
+
}
|
|
6114
|
+
if (ORG_MODEL_ROOT_KINDS.has(rootNode.kind)) {
|
|
6115
|
+
return "coverage";
|
|
6116
|
+
}
|
|
6117
|
+
if (rootNode.kind === "resource") {
|
|
6118
|
+
return "operational-dependencies";
|
|
6119
|
+
}
|
|
6120
|
+
return null;
|
|
6121
|
+
}
|
|
6122
|
+
function resolveRequest(rootNode, request) {
|
|
6123
|
+
const preset = resolvePreset(rootNode, request.preset);
|
|
6124
|
+
const maxResults = request.maxResults === void 0 || !Number.isFinite(request.maxResults) ? DEFAULT_MAX_RESULTS : Math.max(0, request.maxResults);
|
|
6125
|
+
return {
|
|
6126
|
+
rootNodeId: request.rootNodeId,
|
|
6127
|
+
direction: request.direction ?? (preset ? PRESET_DIRECTIONS[preset] : "both"),
|
|
6128
|
+
maxDepth: clampMaxDepth(request.maxDepth ?? DEFAULT_MAX_DEPTH),
|
|
6129
|
+
maxResults,
|
|
6130
|
+
edgeKinds: toSet(request.edgeKinds ?? (preset ? PRESET_EDGE_KINDS[preset] : void 0)),
|
|
6131
|
+
relationshipTypes: toSet(
|
|
6132
|
+
request.relationshipTypes ?? (preset ? PRESET_RELATIONSHIP_TYPES[preset] : void 0)
|
|
6133
|
+
),
|
|
6134
|
+
preset,
|
|
6135
|
+
nodeKinds: toSet(request.nodeKinds),
|
|
6136
|
+
resourceTypes: toSet(request.resourceTypes),
|
|
6137
|
+
includeHiddenResources: request.includeHiddenResources ?? false
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
function getOppositeNodeId(edge, currentNodeId) {
|
|
6141
|
+
if (edge.sourceId === currentNodeId) {
|
|
6142
|
+
return edge.targetId;
|
|
6143
|
+
}
|
|
6144
|
+
if (edge.targetId === currentNodeId) {
|
|
6145
|
+
return edge.sourceId;
|
|
6146
|
+
}
|
|
6147
|
+
return null;
|
|
6148
|
+
}
|
|
6149
|
+
function getCandidateEdges(index, nodeId2, direction) {
|
|
6150
|
+
if (direction === "outgoing") {
|
|
6151
|
+
return index.outgoingEdgesByNodeId.get(nodeId2) ?? [];
|
|
6152
|
+
}
|
|
6153
|
+
if (direction === "incoming") {
|
|
6154
|
+
return index.incomingEdgesByNodeId.get(nodeId2) ?? [];
|
|
6155
|
+
}
|
|
6156
|
+
const seenEdgeIds = /* @__PURE__ */ new Set();
|
|
6157
|
+
const edges = [];
|
|
6158
|
+
for (const edge of [
|
|
6159
|
+
...index.outgoingEdgesByNodeId.get(nodeId2) ?? [],
|
|
6160
|
+
...index.incomingEdgesByNodeId.get(nodeId2) ?? []
|
|
6161
|
+
]) {
|
|
6162
|
+
if (seenEdgeIds.has(edge.id)) {
|
|
6163
|
+
continue;
|
|
6164
|
+
}
|
|
6165
|
+
seenEdgeIds.add(edge.id);
|
|
6166
|
+
edges.push(edge);
|
|
6167
|
+
}
|
|
6168
|
+
return edges;
|
|
6169
|
+
}
|
|
6170
|
+
function matchesPresetTraversalDirection(edge, currentNodeId, request) {
|
|
6171
|
+
if (request.preset === "coverage" && (edge.kind === "contains" || edge.kind === "exposes")) {
|
|
6172
|
+
return edge.sourceId === currentNodeId;
|
|
6173
|
+
}
|
|
6174
|
+
return true;
|
|
6175
|
+
}
|
|
6176
|
+
function matchesEdgeFilters(edge, currentNodeId, request) {
|
|
6177
|
+
if (request.edgeKinds && !request.edgeKinds.has(edge.kind)) {
|
|
6178
|
+
return false;
|
|
6179
|
+
}
|
|
6180
|
+
if (request.relationshipTypes && (!edge.relationshipType || !request.relationshipTypes.has(edge.relationshipType))) {
|
|
6181
|
+
return false;
|
|
6182
|
+
}
|
|
6183
|
+
return matchesPresetTraversalDirection(edge, currentNodeId, request);
|
|
6184
|
+
}
|
|
6185
|
+
function matchesNodeFilters(node, request) {
|
|
6186
|
+
if (request.nodeKinds && !request.nodeKinds.has(node.kind)) {
|
|
6187
|
+
return false;
|
|
6188
|
+
}
|
|
6189
|
+
if (request.resourceTypes) {
|
|
6190
|
+
if (node.kind !== "resource") {
|
|
6191
|
+
return false;
|
|
6192
|
+
}
|
|
6193
|
+
if (!node.resourceType || !request.resourceTypes.has(node.resourceType)) {
|
|
6194
|
+
return false;
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6197
|
+
return true;
|
|
6198
|
+
}
|
|
6199
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
6200
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
6201
|
+
}
|
|
6202
|
+
function getNodeDisplayName(node) {
|
|
6203
|
+
return node.label || node.sourceId || node.id;
|
|
6204
|
+
}
|
|
6205
|
+
function buildSummaryMessages(input) {
|
|
6206
|
+
const { rootNode, preset, expandedNodes, counts, truncated } = input;
|
|
6207
|
+
if (!rootNode) {
|
|
6208
|
+
return ["Select an available node to expand around."];
|
|
6209
|
+
}
|
|
6210
|
+
if (!preset && rootNode.kind === "organization") {
|
|
6211
|
+
return ["Choose a feature, surface, capability, entity, or resource before expanding."];
|
|
6212
|
+
}
|
|
6213
|
+
if (expandedNodes.length === 0) {
|
|
6214
|
+
return [`No matching graph context found around "${getNodeDisplayName(rootNode)}".`];
|
|
6215
|
+
}
|
|
6216
|
+
const resourceCount = expandedNodes.filter((node) => node.kind === "resource").length;
|
|
6217
|
+
const semanticContextCount = expandedNodes.length - resourceCount;
|
|
6218
|
+
const rootLabel = getNodeDisplayName(rootNode);
|
|
6219
|
+
const messages = [];
|
|
6220
|
+
if (preset === "coverage" && ORG_MODEL_ROOT_KINDS.has(rootNode.kind)) {
|
|
6221
|
+
if (resourceCount > 0 && semanticContextCount > 0) {
|
|
6222
|
+
messages.push(
|
|
6223
|
+
`${pluralize(resourceCount, "resource")} and ${pluralize(
|
|
6224
|
+
semanticContextCount,
|
|
6225
|
+
"semantic context node"
|
|
6226
|
+
)} support "${rootLabel}".`
|
|
6227
|
+
);
|
|
6228
|
+
} else if (resourceCount > 0) {
|
|
6229
|
+
messages.push(`${pluralize(resourceCount, "resource")} support "${rootLabel}".`);
|
|
6230
|
+
} else {
|
|
6231
|
+
messages.push(
|
|
6232
|
+
`${pluralize(semanticContextCount, "semantic context node")} found around "${rootLabel}"; no mapped resources matched this coverage preset.`
|
|
6233
|
+
);
|
|
6234
|
+
}
|
|
6235
|
+
} else if (preset === "operational-dependencies") {
|
|
6236
|
+
messages.push(`${pluralize(resourceCount, "operational dependency resource")} found around "${rootLabel}".`);
|
|
6237
|
+
} else if (preset === "org-context") {
|
|
6238
|
+
messages.push(`${pluralize(expandedNodes.length, "semantic context node")} found around "${rootLabel}".`);
|
|
6239
|
+
} else if (preset === "impact-path") {
|
|
6240
|
+
messages.push(`${pluralize(resourceCount, "resource")} can call or be affected by "${rootLabel}".`);
|
|
6241
|
+
} else {
|
|
6242
|
+
messages.push(`${pluralize(expandedNodes.length, "node")} found around "${rootLabel}".`);
|
|
6243
|
+
}
|
|
6244
|
+
if (counts.hiddenResourceNodes > 0) {
|
|
6245
|
+
messages.push(`${pluralize(counts.hiddenResourceNodes, "hidden resource")} matched current visibility settings.`);
|
|
6246
|
+
}
|
|
6247
|
+
if (counts.alreadyVisibleNodes > 0) {
|
|
6248
|
+
messages.push(`${pluralize(counts.alreadyVisibleNodes, "node")} already visible in the graph.`);
|
|
6249
|
+
}
|
|
6250
|
+
if (truncated) {
|
|
6251
|
+
messages.push(`Results were limited to ${pluralize(expandedNodes.length, "node")}.`);
|
|
6252
|
+
}
|
|
6253
|
+
return messages;
|
|
6254
|
+
}
|
|
6255
|
+
function expandAroundGraph(graph, request, options = {}) {
|
|
6256
|
+
const index = buildOrganizationGraphTraceIndex(graph);
|
|
6257
|
+
const rootNode = index.nodesById.get(request.rootNodeId) ?? null;
|
|
6258
|
+
const resolved = resolveRequest(rootNode, request);
|
|
6259
|
+
const alreadyVisibleNodeIds = new Set(options.alreadyVisibleNodeIds ?? []);
|
|
6260
|
+
const hiddenResourceNodeIds = new Set(options.hiddenResourceNodeIds ?? []);
|
|
6261
|
+
const expandedNodeIds = /* @__PURE__ */ new Set();
|
|
6262
|
+
const expandedEdgeIds = /* @__PURE__ */ new Set();
|
|
6263
|
+
const frontierNodeIds = /* @__PURE__ */ new Set();
|
|
6264
|
+
const visitedDepthByNodeId = /* @__PURE__ */ new Map([[resolved.rootNodeId, 0]]);
|
|
6265
|
+
const hasExplicitTraversalFilter = Boolean(
|
|
6266
|
+
request.preset || request.edgeKinds?.length || request.relationshipTypes?.length || request.nodeKinds?.length || request.resourceTypes?.length
|
|
6267
|
+
);
|
|
6268
|
+
const queue = rootNode && (resolved.preset || hasExplicitTraversalFilter) ? [{ nodeId: rootNode.id, depth: 0 }] : [];
|
|
6269
|
+
let truncated = false;
|
|
6270
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex += 1) {
|
|
6271
|
+
const current = queue[queueIndex];
|
|
6272
|
+
if (current.depth >= resolved.maxDepth) {
|
|
6273
|
+
if (current.nodeId !== resolved.rootNodeId) {
|
|
6274
|
+
frontierNodeIds.add(current.nodeId);
|
|
6275
|
+
}
|
|
6276
|
+
continue;
|
|
6277
|
+
}
|
|
6278
|
+
for (const edge of getCandidateEdges(index, current.nodeId, resolved.direction)) {
|
|
6279
|
+
if (!matchesEdgeFilters(edge, current.nodeId, resolved)) {
|
|
6280
|
+
continue;
|
|
6281
|
+
}
|
|
6282
|
+
const nextNodeId = getOppositeNodeId(edge, current.nodeId);
|
|
6283
|
+
if (!nextNodeId) {
|
|
6284
|
+
continue;
|
|
6285
|
+
}
|
|
6286
|
+
const nextNode = index.nodesById.get(nextNodeId);
|
|
6287
|
+
if (!nextNode || !matchesNodeFilters(nextNode, resolved)) {
|
|
6288
|
+
continue;
|
|
6289
|
+
}
|
|
6290
|
+
if (!resolved.includeHiddenResources && hiddenResourceNodeIds.has(nextNode.id)) {
|
|
6291
|
+
continue;
|
|
6292
|
+
}
|
|
6293
|
+
const nextDepth = current.depth + 1;
|
|
6294
|
+
const previousDepth = visitedDepthByNodeId.get(nextNode.id);
|
|
6295
|
+
if (previousDepth !== void 0) {
|
|
6296
|
+
if (nextNode.id === resolved.rootNodeId || expandedNodeIds.has(nextNode.id)) {
|
|
6297
|
+
expandedEdgeIds.add(edge.id);
|
|
6298
|
+
}
|
|
6299
|
+
continue;
|
|
6300
|
+
}
|
|
6301
|
+
if (expandedNodeIds.size >= resolved.maxResults) {
|
|
6302
|
+
truncated = true;
|
|
6303
|
+
frontierNodeIds.add(nextNode.id);
|
|
6304
|
+
continue;
|
|
6305
|
+
}
|
|
6306
|
+
visitedDepthByNodeId.set(nextNode.id, nextDepth);
|
|
6307
|
+
expandedNodeIds.add(nextNode.id);
|
|
6308
|
+
expandedEdgeIds.add(edge.id);
|
|
6309
|
+
if (nextDepth >= resolved.maxDepth) {
|
|
6310
|
+
frontierNodeIds.add(nextNode.id);
|
|
6311
|
+
continue;
|
|
6312
|
+
}
|
|
6313
|
+
queue.push({ nodeId: nextNode.id, depth: nextDepth });
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
const expandedNodes = [...expandedNodeIds].map((nodeId2) => index.nodesById.get(nodeId2)).filter((node) => Boolean(node));
|
|
6317
|
+
const hiddenResourceNodes = expandedNodes.filter((node) => hiddenResourceNodeIds.has(node.id)).length;
|
|
6318
|
+
const alreadyVisibleNodes = expandedNodes.filter((node) => alreadyVisibleNodeIds.has(node.id)).length;
|
|
6319
|
+
const newNodes = expandedNodes.filter(
|
|
6320
|
+
(node) => !hiddenResourceNodeIds.has(node.id) && !alreadyVisibleNodeIds.has(node.id)
|
|
6321
|
+
).length;
|
|
6322
|
+
const counts = {
|
|
6323
|
+
newNodes,
|
|
6324
|
+
newEdges: expandedEdgeIds.size,
|
|
6325
|
+
alreadyVisibleNodes,
|
|
6326
|
+
hiddenResourceNodes
|
|
6327
|
+
};
|
|
6328
|
+
const summaryMessages = buildSummaryMessages({
|
|
6329
|
+
rootNode,
|
|
6330
|
+
preset: resolved.preset,
|
|
6331
|
+
expandedNodes,
|
|
6332
|
+
counts,
|
|
6333
|
+
truncated
|
|
6334
|
+
});
|
|
6335
|
+
return {
|
|
6336
|
+
rootNodeId: request.rootNodeId,
|
|
6337
|
+
rootNode,
|
|
6338
|
+
preset: resolved.preset,
|
|
6339
|
+
direction: resolved.direction,
|
|
6340
|
+
maxDepth: resolved.maxDepth,
|
|
6341
|
+
maxResults: resolved.maxResults,
|
|
6342
|
+
expandedNodeIds: [...expandedNodeIds],
|
|
6343
|
+
expandedEdgeIds: [...expandedEdgeIds],
|
|
6344
|
+
frontierNodeIds: [...frontierNodeIds].filter((nodeId2) => nodeId2 !== resolved.rootNodeId),
|
|
6345
|
+
truncated,
|
|
6346
|
+
counts,
|
|
6347
|
+
summaryMessages,
|
|
6348
|
+
message: summaryMessages[0] ?? ""
|
|
6349
|
+
};
|
|
6350
|
+
}
|
|
6351
|
+
var PRESET_OPTIONS = [
|
|
6352
|
+
{ value: "coverage", label: "Coverage" },
|
|
6353
|
+
{ value: "operational-dependencies", label: "Operational dependencies" },
|
|
6354
|
+
{ value: "org-context", label: "Org context" },
|
|
6355
|
+
{ value: "impact-path", label: "Impact path" }
|
|
6356
|
+
];
|
|
6357
|
+
var DIRECTION_OPTIONS = [
|
|
6358
|
+
{ value: "both", label: "Both" },
|
|
6359
|
+
{ value: "outgoing", label: "Outgoing" },
|
|
6360
|
+
{ value: "incoming", label: "Incoming" }
|
|
6361
|
+
];
|
|
6362
|
+
var EDGE_KIND_OPTIONS = [
|
|
6363
|
+
{ value: "contains", label: "Containment" },
|
|
6364
|
+
{ value: "references", label: "References" },
|
|
6365
|
+
{ value: "exposes", label: "Exposes" },
|
|
6366
|
+
{ value: "maps_to", label: "Maps to" },
|
|
6367
|
+
{ value: "operates-on", label: "Operates on" },
|
|
6368
|
+
{ value: "uses", label: "Uses" }
|
|
6369
|
+
];
|
|
6370
|
+
var RELATIONSHIP_OPTIONS = [
|
|
6371
|
+
{ value: "triggers", label: "Triggers" },
|
|
6372
|
+
{ value: "uses", label: "Uses" },
|
|
6373
|
+
{ value: "approval", label: "Approval" }
|
|
6374
|
+
];
|
|
6375
|
+
var RESOURCE_TYPE_OPTIONS = [
|
|
6376
|
+
{ value: "workflow", label: "Workflow" },
|
|
6377
|
+
{ value: "agent", label: "Agent" },
|
|
6378
|
+
{ value: "trigger", label: "Trigger" },
|
|
6379
|
+
{ value: "integration", label: "Integration" },
|
|
6380
|
+
{ value: "external", label: "External" },
|
|
6381
|
+
{ value: "human_checkpoint", label: "Human checkpoint" }
|
|
6382
|
+
];
|
|
6383
|
+
function updateValue(value, key, nextValue, onChange) {
|
|
6384
|
+
onChange({
|
|
6385
|
+
...value,
|
|
6386
|
+
[key]: nextValue
|
|
6387
|
+
});
|
|
6388
|
+
}
|
|
6389
|
+
function toOptionalArray(values) {
|
|
6390
|
+
return values.length > 0 ? values : void 0;
|
|
6391
|
+
}
|
|
6392
|
+
function toMaxDepth(value) {
|
|
6393
|
+
const numeric = typeof value === "number" ? value : Number.parseInt(value, 10);
|
|
6394
|
+
if (numeric === 3) return 3;
|
|
6395
|
+
if (numeric === 2) return 2;
|
|
6396
|
+
return 1;
|
|
6397
|
+
}
|
|
6398
|
+
function ExpandAroundPanel({
|
|
6399
|
+
selectedNode,
|
|
6400
|
+
value,
|
|
6401
|
+
result,
|
|
6402
|
+
appliedNodeCount,
|
|
6403
|
+
appliedEdgeCount,
|
|
6404
|
+
onChange,
|
|
6405
|
+
onPreview,
|
|
6406
|
+
onApply,
|
|
6407
|
+
onClear
|
|
6408
|
+
}) {
|
|
6409
|
+
const disabled = !selectedNode;
|
|
6410
|
+
const canApply = Boolean(result && result.expandedNodeIds.length > 0);
|
|
6411
|
+
const rootIsTooBroad = selectedNode?.kind === "organization" && !value.preset;
|
|
6412
|
+
return /* @__PURE__ */ jsx(Paper, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
6413
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", wrap: "wrap", children: [
|
|
6414
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
6415
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 800, children: "Expand Around" }),
|
|
6416
|
+
/* @__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." })
|
|
6417
|
+
] }),
|
|
6418
|
+
appliedNodeCount > 0 || appliedEdgeCount > 0 ? /* @__PURE__ */ jsxs(Badge, { variant: "light", color: "blue", children: [
|
|
6419
|
+
appliedNodeCount,
|
|
6420
|
+
" nodes / ",
|
|
6421
|
+
appliedEdgeCount,
|
|
6422
|
+
" edges applied"
|
|
6423
|
+
] }) : null
|
|
6424
|
+
] }),
|
|
6425
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "sm", children: [
|
|
6426
|
+
/* @__PURE__ */ jsx(
|
|
6427
|
+
Select,
|
|
6428
|
+
{
|
|
6429
|
+
label: "Preset",
|
|
6430
|
+
placeholder: "Auto",
|
|
6431
|
+
data: PRESET_OPTIONS,
|
|
6432
|
+
value: value.preset ?? null,
|
|
6433
|
+
onChange: (preset) => updateValue(value, "preset", preset ?? void 0, onChange),
|
|
6434
|
+
disabled,
|
|
6435
|
+
clearable: true
|
|
6436
|
+
}
|
|
6437
|
+
),
|
|
6438
|
+
/* @__PURE__ */ jsx(
|
|
6439
|
+
Select,
|
|
6440
|
+
{
|
|
6441
|
+
label: "Direction",
|
|
6442
|
+
data: DIRECTION_OPTIONS,
|
|
6443
|
+
value: value.direction ?? "both",
|
|
6444
|
+
onChange: (direction) => updateValue(value, "direction", direction ?? "both", onChange),
|
|
6445
|
+
disabled
|
|
6446
|
+
}
|
|
6447
|
+
),
|
|
6448
|
+
/* @__PURE__ */ jsx(
|
|
6449
|
+
NumberInput,
|
|
6450
|
+
{
|
|
6451
|
+
label: "Depth",
|
|
6452
|
+
min: 1,
|
|
6453
|
+
max: 3,
|
|
6454
|
+
value: value.maxDepth ?? 1,
|
|
6455
|
+
onChange: (maxDepth) => updateValue(value, "maxDepth", toMaxDepth(maxDepth), onChange),
|
|
6456
|
+
disabled
|
|
6457
|
+
}
|
|
6458
|
+
),
|
|
6459
|
+
/* @__PURE__ */ jsx(
|
|
6460
|
+
NumberInput,
|
|
6461
|
+
{
|
|
6462
|
+
label: "Max results",
|
|
6463
|
+
min: 1,
|
|
6464
|
+
max: 100,
|
|
6465
|
+
value: value.maxResults ?? 25,
|
|
6466
|
+
onChange: (maxResults) => updateValue(
|
|
6467
|
+
value,
|
|
6468
|
+
"maxResults",
|
|
6469
|
+
Math.max(1, typeof maxResults === "number" ? maxResults : Number.parseInt(maxResults, 10) || 25),
|
|
6470
|
+
onChange
|
|
6471
|
+
),
|
|
6472
|
+
disabled
|
|
6473
|
+
}
|
|
6474
|
+
)
|
|
6475
|
+
] }),
|
|
6476
|
+
/* @__PURE__ */ jsx(
|
|
6477
|
+
MultiSelect,
|
|
6478
|
+
{
|
|
6479
|
+
label: "Relationship filters",
|
|
6480
|
+
placeholder: "Preset defaults",
|
|
6481
|
+
data: RELATIONSHIP_OPTIONS,
|
|
6482
|
+
value: value.relationshipTypes ?? [],
|
|
6483
|
+
onChange: (relationshipTypes) => updateValue(value, "relationshipTypes", toOptionalArray(relationshipTypes), onChange),
|
|
6484
|
+
disabled,
|
|
6485
|
+
clearable: true
|
|
6486
|
+
}
|
|
6487
|
+
),
|
|
6488
|
+
/* @__PURE__ */ jsx(
|
|
6489
|
+
MultiSelect,
|
|
6490
|
+
{
|
|
6491
|
+
label: "Edge kind filters",
|
|
6492
|
+
placeholder: "Preset defaults",
|
|
6493
|
+
data: EDGE_KIND_OPTIONS,
|
|
6494
|
+
value: value.edgeKinds ?? [],
|
|
6495
|
+
onChange: (edgeKinds) => updateValue(value, "edgeKinds", toOptionalArray(edgeKinds), onChange),
|
|
6496
|
+
disabled,
|
|
6497
|
+
clearable: true
|
|
6498
|
+
}
|
|
6499
|
+
),
|
|
6500
|
+
/* @__PURE__ */ jsx(
|
|
6501
|
+
MultiSelect,
|
|
6502
|
+
{
|
|
6503
|
+
label: "Resource type filters",
|
|
6504
|
+
placeholder: "All resource types",
|
|
6505
|
+
data: RESOURCE_TYPE_OPTIONS,
|
|
6506
|
+
value: value.resourceTypes ?? [],
|
|
6507
|
+
onChange: (resourceTypes) => updateValue(value, "resourceTypes", toOptionalArray(resourceTypes), onChange),
|
|
6508
|
+
disabled,
|
|
6509
|
+
clearable: true
|
|
6510
|
+
}
|
|
6511
|
+
),
|
|
6512
|
+
/* @__PURE__ */ jsx(
|
|
6513
|
+
Switch,
|
|
6514
|
+
{
|
|
6515
|
+
label: "Include hidden resources",
|
|
6516
|
+
checked: value.includeHiddenResources ?? true,
|
|
6517
|
+
onChange: (event) => updateValue(value, "includeHiddenResources", event.currentTarget.checked, onChange),
|
|
6518
|
+
disabled
|
|
6519
|
+
}
|
|
6520
|
+
),
|
|
6521
|
+
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,
|
|
6522
|
+
result ? /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
6523
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "wrap", children: [
|
|
6524
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
|
|
6525
|
+
result.counts.newNodes,
|
|
6526
|
+
" new"
|
|
6527
|
+
] }),
|
|
6528
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
|
|
6529
|
+
result.counts.alreadyVisibleNodes,
|
|
6530
|
+
" visible"
|
|
6531
|
+
] }),
|
|
6532
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "light", color: result.counts.hiddenResourceNodes > 0 ? "orange" : "gray", children: [
|
|
6533
|
+
result.counts.hiddenResourceNodes,
|
|
6534
|
+
" hidden"
|
|
6535
|
+
] }),
|
|
6536
|
+
result.truncated ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: "yellow", children: "Truncated" }) : null
|
|
6537
|
+
] }),
|
|
6538
|
+
result.summaryMessages.map((message) => /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: message }, message))
|
|
6539
|
+
] }) }) : null,
|
|
6540
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "wrap", children: [
|
|
6541
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6542
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "light", onClick: onPreview, disabled: disabled || rootIsTooBroad, children: "Preview" }),
|
|
6543
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", onClick: onApply, disabled: !canApply, children: "Apply" })
|
|
6544
|
+
] }),
|
|
6545
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: onClear, disabled: !result && appliedNodeCount === 0, children: "Clear expansion" })
|
|
6546
|
+
] })
|
|
6547
|
+
] }) });
|
|
6548
|
+
}
|
|
5836
6549
|
var cellStyle = {
|
|
5837
6550
|
padding: "var(--mantine-spacing-sm) var(--mantine-spacing-md)",
|
|
5838
6551
|
display: "flex",
|
|
@@ -6125,345 +6838,114 @@ function toResourceHealth(node, stats) {
|
|
|
6125
6838
|
const summaryLabel2 = checkpointStats.pendingCount > 0 ? `${checkpointStats.pendingCount} pending` : checkpointStats.expiredCount > 0 ? `${checkpointStats.expiredCount} expired` : checkpointStats.completedCount > 0 ? `${checkpointStats.completedCount} completed` : "No queue activity";
|
|
6126
6839
|
const detailLabel = checkpointStats.pendingCount > 0 ? `${checkpointStats.completedCount} resolved` : totalQueueActivity > 0 ? "Queue clear" : "No approvals in range";
|
|
6127
6840
|
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."
|
|
6841
|
+
nodeId: node.id,
|
|
6842
|
+
resourceId,
|
|
6843
|
+
label: node.label,
|
|
6844
|
+
resourceType: node.resourceType,
|
|
6845
|
+
healthLevel: healthLevel2,
|
|
6846
|
+
summaryLabel: summaryLabel2,
|
|
6847
|
+
detailLabel,
|
|
6848
|
+
successRate: null,
|
|
6849
|
+
totalRuns: 0,
|
|
6850
|
+
successCount: 0,
|
|
6851
|
+
failureCount: 0,
|
|
6852
|
+
warningCount: 0,
|
|
6853
|
+
pendingCount: checkpointStats.pendingCount,
|
|
6854
|
+
completedCount: checkpointStats.completedCount,
|
|
6855
|
+
expiredCount: checkpointStats.expiredCount,
|
|
6856
|
+
lastActivityAt: checkpointStats.lastDecisionAt,
|
|
6857
|
+
sortScore: checkpointStats.pendingCount * 100 + checkpointStats.expiredCount * 25 + checkpointStats.completedCount
|
|
6362
6858
|
};
|
|
6363
6859
|
}
|
|
6364
|
-
|
|
6860
|
+
const resourceStats = stats.resources[resourceId];
|
|
6861
|
+
if (!resourceStats || resourceStats.totalRuns <= 0) {
|
|
6365
6862
|
return {
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6863
|
+
nodeId: node.id,
|
|
6864
|
+
resourceId,
|
|
6865
|
+
label: node.label,
|
|
6866
|
+
resourceType: node.resourceType,
|
|
6867
|
+
healthLevel: "inactive",
|
|
6868
|
+
summaryLabel: "No runs",
|
|
6869
|
+
detailLabel: "No executions in range",
|
|
6870
|
+
successRate: null,
|
|
6871
|
+
totalRuns: 0,
|
|
6872
|
+
successCount: 0,
|
|
6873
|
+
failureCount: 0,
|
|
6874
|
+
warningCount: 0,
|
|
6875
|
+
pendingCount: 0,
|
|
6876
|
+
completedCount: 0,
|
|
6877
|
+
expiredCount: 0,
|
|
6878
|
+
lastActivityAt: resourceStats?.lastRunAt ?? null,
|
|
6879
|
+
sortScore: 0
|
|
6377
6880
|
};
|
|
6378
6881
|
}
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6882
|
+
const successfulOutcomes = resourceStats.successCount + resourceStats.warningCount;
|
|
6883
|
+
const successRate = successfulOutcomes / resourceStats.totalRuns * 100;
|
|
6884
|
+
const healthLevel = successRate >= 95 ? "healthy" : successRate >= 80 ? "warning" : "critical";
|
|
6885
|
+
const summaryLabel = resourceStats.failureCount > 0 ? `${resourceStats.failureCount} failed` : resourceStats.warningCount > 0 ? `${resourceStats.warningCount} warnings` : `${resourceStats.totalRuns} runs`;
|
|
6886
|
+
return {
|
|
6887
|
+
nodeId: node.id,
|
|
6888
|
+
resourceId,
|
|
6889
|
+
label: node.label,
|
|
6890
|
+
resourceType: node.resourceType,
|
|
6891
|
+
healthLevel,
|
|
6892
|
+
summaryLabel,
|
|
6893
|
+
detailLabel: `${Math.round(successRate)}% healthy`,
|
|
6894
|
+
successRate,
|
|
6895
|
+
totalRuns: resourceStats.totalRuns,
|
|
6896
|
+
successCount: resourceStats.successCount,
|
|
6897
|
+
failureCount: resourceStats.failureCount,
|
|
6898
|
+
warningCount: resourceStats.warningCount,
|
|
6899
|
+
pendingCount: 0,
|
|
6900
|
+
completedCount: 0,
|
|
6901
|
+
expiredCount: 0,
|
|
6902
|
+
lastActivityAt: resourceStats.lastRunAt,
|
|
6903
|
+
sortScore: resourceStats.failureCount * 100 + resourceStats.warningCount * 25 + resourceStats.totalRuns
|
|
6904
|
+
};
|
|
6905
|
+
}
|
|
6906
|
+
function getCommandViewGraphNodeHealth(node, stats) {
|
|
6907
|
+
if (node.kind !== "resource" || !stats) {
|
|
6908
|
+
return null;
|
|
6393
6909
|
}
|
|
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);
|
|
6910
|
+
return toResourceHealth(node, stats);
|
|
6911
|
+
}
|
|
6912
|
+
function getCommandViewGraphHealthMap(graph, stats) {
|
|
6913
|
+
const healthByNodeId = /* @__PURE__ */ new Map();
|
|
6914
|
+
if (!graph || !stats) {
|
|
6915
|
+
return healthByNodeId;
|
|
6916
|
+
}
|
|
6917
|
+
for (const node of graph.nodes) {
|
|
6918
|
+
const health = getCommandViewGraphNodeHealth(node, stats);
|
|
6919
|
+
if (health) {
|
|
6920
|
+
healthByNodeId.set(node.id, health);
|
|
6417
6921
|
}
|
|
6418
6922
|
}
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
};
|
|
6923
|
+
return healthByNodeId;
|
|
6924
|
+
}
|
|
6925
|
+
function getHealthRank(level) {
|
|
6926
|
+
switch (level) {
|
|
6927
|
+
case "critical":
|
|
6928
|
+
return 0;
|
|
6929
|
+
case "warning":
|
|
6930
|
+
return 1;
|
|
6931
|
+
case "healthy":
|
|
6932
|
+
return 2;
|
|
6933
|
+
case "inactive":
|
|
6934
|
+
default:
|
|
6935
|
+
return 3;
|
|
6433
6936
|
}
|
|
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);
|
|
6937
|
+
}
|
|
6938
|
+
function rankCommandViewHotspots(entries, limit = 3) {
|
|
6939
|
+
return [...entries].filter((entry) => entry.healthLevel === "critical" || entry.healthLevel === "warning").sort((left, right) => {
|
|
6940
|
+
const healthRankDelta = getHealthRank(left.healthLevel) - getHealthRank(right.healthLevel);
|
|
6941
|
+
if (healthRankDelta !== 0) {
|
|
6942
|
+
return healthRankDelta;
|
|
6446
6943
|
}
|
|
6447
|
-
if (
|
|
6448
|
-
|
|
6944
|
+
if (right.sortScore !== left.sortScore) {
|
|
6945
|
+
return right.sortScore - left.sortScore;
|
|
6449
6946
|
}
|
|
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
|
-
};
|
|
6947
|
+
return left.label.localeCompare(right.label);
|
|
6948
|
+
}).slice(0, limit);
|
|
6467
6949
|
}
|
|
6468
6950
|
var STATUS_LABELS = {
|
|
6469
6951
|
idle: "Idle",
|
|
@@ -6587,6 +7069,14 @@ var EMPTY_TRACE_SELECTION = {
|
|
|
6587
7069
|
};
|
|
6588
7070
|
var EMPTY_GRAPH_HIDDEN_IDS = /* @__PURE__ */ new Set();
|
|
6589
7071
|
var EMPTY_GRAPH_HIDDEN_EDGE_IDS = /* @__PURE__ */ new Set();
|
|
7072
|
+
var EMPTY_EXPANDED_NODE_IDS = /* @__PURE__ */ new Set();
|
|
7073
|
+
var EMPTY_EXPANDED_EDGE_IDS = /* @__PURE__ */ new Set();
|
|
7074
|
+
var DEFAULT_EXPAND_AROUND_VALUE = {
|
|
7075
|
+
direction: "both",
|
|
7076
|
+
maxDepth: 1,
|
|
7077
|
+
maxResults: 25,
|
|
7078
|
+
includeHiddenResources: true
|
|
7079
|
+
};
|
|
6590
7080
|
var FALLBACK_GRAPH_THEME = {
|
|
6591
7081
|
primary: "#4a6e8e",
|
|
6592
7082
|
background: "#030507",
|
|
@@ -6994,13 +7484,31 @@ function createCytoscapeStyle(tokens) {
|
|
|
6994
7484
|
"target-arrow-color": traceBorder,
|
|
6995
7485
|
"line-style": "solid"
|
|
6996
7486
|
}
|
|
7487
|
+
},
|
|
7488
|
+
{
|
|
7489
|
+
selector: "node.is-expanded-node",
|
|
7490
|
+
style: {
|
|
7491
|
+
opacity: 1,
|
|
7492
|
+
"border-color": mixColors(tokens.primary, tokens.warning, 0.72),
|
|
7493
|
+
"border-width": 3.4,
|
|
7494
|
+
"background-opacity": 1
|
|
7495
|
+
}
|
|
7496
|
+
},
|
|
7497
|
+
{
|
|
7498
|
+
selector: "edge.is-expanded-edge",
|
|
7499
|
+
style: {
|
|
7500
|
+
opacity: 1,
|
|
7501
|
+
width: 3.4,
|
|
7502
|
+
"line-opacity": 0.94,
|
|
7503
|
+
label: "data(label)"
|
|
7504
|
+
}
|
|
6997
7505
|
}
|
|
6998
7506
|
];
|
|
6999
7507
|
}
|
|
7000
|
-
function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds) {
|
|
7508
|
+
function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds) {
|
|
7001
7509
|
cy.batch(() => {
|
|
7002
7510
|
cy.elements().removeClass(
|
|
7003
|
-
"is-hidden is-faded is-context is-selected is-connected is-trace-node is-trace-edge is-trace-endpoint"
|
|
7511
|
+
"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
7512
|
);
|
|
7005
7513
|
for (const nodeId2 of hiddenIds) {
|
|
7006
7514
|
const node = cy.getElementById(nodeId2);
|
|
@@ -7018,9 +7526,33 @@ function syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdg
|
|
|
7018
7526
|
traceResult && (traceResult.highlightNodeIds.length > 0 || traceResult.highlightEdgeIds.length > 0)
|
|
7019
7527
|
);
|
|
7020
7528
|
if (!selectedElement && !hasTrace) {
|
|
7529
|
+
for (const nodeId2 of expandedNodeIds) {
|
|
7530
|
+
const node = cy.getElementById(nodeId2);
|
|
7531
|
+
if (!node.empty()) {
|
|
7532
|
+
node.addClass("is-expanded-node");
|
|
7533
|
+
}
|
|
7534
|
+
}
|
|
7535
|
+
for (const edgeId2 of expandedEdgeIds) {
|
|
7536
|
+
const edge2 = cy.getElementById(edgeId2);
|
|
7537
|
+
if (!edge2.empty()) {
|
|
7538
|
+
edge2.addClass("is-expanded-edge");
|
|
7539
|
+
}
|
|
7540
|
+
}
|
|
7021
7541
|
return;
|
|
7022
7542
|
}
|
|
7023
7543
|
cy.elements().addClass("is-faded");
|
|
7544
|
+
for (const nodeId2 of expandedNodeIds) {
|
|
7545
|
+
const node = cy.getElementById(nodeId2);
|
|
7546
|
+
if (!node.empty()) {
|
|
7547
|
+
node.removeClass("is-faded").addClass("is-context is-expanded-node");
|
|
7548
|
+
}
|
|
7549
|
+
}
|
|
7550
|
+
for (const edgeId2 of expandedEdgeIds) {
|
|
7551
|
+
const edge2 = cy.getElementById(edgeId2);
|
|
7552
|
+
if (!edge2.empty()) {
|
|
7553
|
+
edge2.removeClass("is-faded").addClass("is-connected is-expanded-edge");
|
|
7554
|
+
}
|
|
7555
|
+
}
|
|
7024
7556
|
if (traceResult) {
|
|
7025
7557
|
for (const nodeId2 of traceResult.highlightNodeIds) {
|
|
7026
7558
|
const node = cy.getElementById(nodeId2);
|
|
@@ -7097,6 +7629,8 @@ function OrganizationGraphCanvas({
|
|
|
7097
7629
|
traceResult,
|
|
7098
7630
|
hiddenIds,
|
|
7099
7631
|
hiddenEdgeIds,
|
|
7632
|
+
expandedNodeIds,
|
|
7633
|
+
expandedEdgeIds,
|
|
7100
7634
|
themeTokens,
|
|
7101
7635
|
commandViewHealthByNodeId,
|
|
7102
7636
|
focusRequest,
|
|
@@ -7158,7 +7692,7 @@ function OrganizationGraphCanvas({
|
|
|
7158
7692
|
});
|
|
7159
7693
|
});
|
|
7160
7694
|
resizeObserver.observe(containerRef.current);
|
|
7161
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7695
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7162
7696
|
return () => {
|
|
7163
7697
|
resizeObserver.disconnect();
|
|
7164
7698
|
cy.destroy();
|
|
@@ -7172,7 +7706,7 @@ function OrganizationGraphCanvas({
|
|
|
7172
7706
|
}
|
|
7173
7707
|
syncCytoscapeElements(cy, elements);
|
|
7174
7708
|
cy.layout(getLayoutOptions(mode, selectedElement, traceResult)).run();
|
|
7175
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7709
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7176
7710
|
}, [elements]);
|
|
7177
7711
|
useEffect(() => {
|
|
7178
7712
|
const cy = cytoscapeRef.current;
|
|
@@ -7191,7 +7725,7 @@ function OrganizationGraphCanvas({
|
|
|
7191
7725
|
if (!cy) {
|
|
7192
7726
|
return;
|
|
7193
7727
|
}
|
|
7194
|
-
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds);
|
|
7728
|
+
syncGraphClasses(cy, selectedElement, traceResult, hiddenIds, hiddenEdgeIds, expandedNodeIds, expandedEdgeIds);
|
|
7195
7729
|
if (mode === "map" && selectedElement?.type === "node") {
|
|
7196
7730
|
const node = cy.getElementById(selectedElement.id);
|
|
7197
7731
|
if (!node.empty()) {
|
|
@@ -7211,7 +7745,7 @@ function OrganizationGraphCanvas({
|
|
|
7211
7745
|
);
|
|
7212
7746
|
}
|
|
7213
7747
|
}
|
|
7214
|
-
}, [hiddenEdgeIds, hiddenIds, mode, selectedElement, traceResult]);
|
|
7748
|
+
}, [expandedEdgeIds, expandedNodeIds, hiddenEdgeIds, hiddenIds, mode, selectedElement, traceResult]);
|
|
7215
7749
|
useEffect(() => {
|
|
7216
7750
|
const cy = cytoscapeRef.current;
|
|
7217
7751
|
if (!cy || !focusRequest) {
|
|
@@ -7354,6 +7888,10 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7354
7888
|
const [selectedElement, setSelectedElement] = useState(null);
|
|
7355
7889
|
const [focusRequest, setFocusRequest] = useState(null);
|
|
7356
7890
|
const [pathTraceSelection, setPathTraceSelection] = useState(EMPTY_TRACE_SELECTION);
|
|
7891
|
+
const [expandAroundValue, setExpandAroundValue] = useState(DEFAULT_EXPAND_AROUND_VALUE);
|
|
7892
|
+
const [expandAroundPreview, setExpandAroundPreview] = useState(null);
|
|
7893
|
+
const [appliedExpandAroundNodeIds, setAppliedExpandAroundNodeIds] = useState(EMPTY_EXPANDED_NODE_IDS);
|
|
7894
|
+
const [appliedExpandAroundEdgeIds, setAppliedExpandAroundEdgeIds] = useState(EMPTY_EXPANDED_EDGE_IDS);
|
|
7357
7895
|
const { filters, resetFilters, updateFilters } = useOrganizationGraphFilters(lensConfig.initialFilters);
|
|
7358
7896
|
const toolbarResetValue = useMemo(
|
|
7359
7897
|
() => createOrganizationGraphFilters(lensConfig.initialFilters),
|
|
@@ -7385,6 +7923,12 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7385
7923
|
commandViewData
|
|
7386
7924
|
});
|
|
7387
7925
|
}, [baseGraph, commandViewData, deferredFilters]);
|
|
7926
|
+
const commandViewRevealIds = useMemo(() => {
|
|
7927
|
+
if (appliedExpandAroundNodeIds.size === 0) {
|
|
7928
|
+
return revealedIds;
|
|
7929
|
+
}
|
|
7930
|
+
return /* @__PURE__ */ new Set([...revealedIds, ...appliedExpandAroundNodeIds]);
|
|
7931
|
+
}, [appliedExpandAroundNodeIds, revealedIds]);
|
|
7388
7932
|
const visibilityProjection = useMemo(() => {
|
|
7389
7933
|
if (!graph || lens !== "command-view") {
|
|
7390
7934
|
const resourceCount = getGraphCountByKind(graph, "resource");
|
|
@@ -7403,10 +7947,10 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7403
7947
|
resourcesHidden,
|
|
7404
7948
|
diagnosticsHidden,
|
|
7405
7949
|
diagnosticCategories,
|
|
7406
|
-
revealedIds,
|
|
7950
|
+
revealedIds: commandViewRevealIds,
|
|
7407
7951
|
mode
|
|
7408
7952
|
});
|
|
7409
|
-
}, [commandViewData, diagnosticCategories, diagnosticsHidden, graph, lens, mode, resourcesHidden
|
|
7953
|
+
}, [commandViewData, commandViewRevealIds, diagnosticCategories, diagnosticsHidden, graph, lens, mode, resourcesHidden]);
|
|
7410
7954
|
const visibleGraph = useMemo(() => {
|
|
7411
7955
|
if (!graph || visibilityProjection.hiddenIds.size === 0) {
|
|
7412
7956
|
return graph;
|
|
@@ -7489,6 +8033,43 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7489
8033
|
nonce: Date.now()
|
|
7490
8034
|
});
|
|
7491
8035
|
});
|
|
8036
|
+
const clearExpandAroundState = useEffectEvent(() => {
|
|
8037
|
+
setExpandAroundPreview(null);
|
|
8038
|
+
setAppliedExpandAroundNodeIds(EMPTY_EXPANDED_NODE_IDS);
|
|
8039
|
+
setAppliedExpandAroundEdgeIds(EMPTY_EXPANDED_EDGE_IDS);
|
|
8040
|
+
});
|
|
8041
|
+
const previewExpandAround = useEffectEvent(() => {
|
|
8042
|
+
if (lens !== "command-view" || !graph || selectedElement?.type !== "node") {
|
|
8043
|
+
setExpandAroundPreview(null);
|
|
8044
|
+
return;
|
|
8045
|
+
}
|
|
8046
|
+
setExpandAroundPreview(
|
|
8047
|
+
expandAroundGraph(
|
|
8048
|
+
graph,
|
|
8049
|
+
{
|
|
8050
|
+
rootNodeId: selectedElement.id,
|
|
8051
|
+
...expandAroundValue
|
|
8052
|
+
},
|
|
8053
|
+
{
|
|
8054
|
+
alreadyVisibleNodeIds: visibleGraph?.nodes.map((node) => node.id) ?? [],
|
|
8055
|
+
hiddenResourceNodeIds: visibilityProjection.hiddenIds
|
|
8056
|
+
}
|
|
8057
|
+
)
|
|
8058
|
+
);
|
|
8059
|
+
});
|
|
8060
|
+
const applyExpandAroundPreview = useEffectEvent(() => {
|
|
8061
|
+
if (!expandAroundPreview || selectedElement?.type !== "node") {
|
|
8062
|
+
return;
|
|
8063
|
+
}
|
|
8064
|
+
setAppliedExpandAroundNodeIds(new Set(expandAroundPreview.expandedNodeIds));
|
|
8065
|
+
setAppliedExpandAroundEdgeIds(new Set(expandAroundPreview.expandedEdgeIds));
|
|
8066
|
+
setMode("map");
|
|
8067
|
+
setSelectedElement({ type: "node", id: selectedElement.id });
|
|
8068
|
+
focusGraphNode(selectedElement.id);
|
|
8069
|
+
if (expandAroundPreview.counts.hiddenResourceNodes > 0) {
|
|
8070
|
+
markVisibilityInteraction();
|
|
8071
|
+
}
|
|
8072
|
+
});
|
|
7492
8073
|
const focusCommandViewResource = useEffectEvent((resourceId) => {
|
|
7493
8074
|
const focusNode = visibleGraph?.nodes.find((node) => node.kind === "resource" && node.sourceId === resourceId);
|
|
7494
8075
|
if (!focusNode) {
|
|
@@ -7501,6 +8082,7 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7501
8082
|
const handleResetFilters = useEffectEvent(() => {
|
|
7502
8083
|
resetFilters();
|
|
7503
8084
|
clearRevealedIds();
|
|
8085
|
+
clearExpandAroundState();
|
|
7504
8086
|
setSelectedElement(null);
|
|
7505
8087
|
setPathTraceSelection(EMPTY_TRACE_SELECTION);
|
|
7506
8088
|
});
|
|
@@ -7508,6 +8090,7 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7508
8090
|
setResourcesHidden(value);
|
|
7509
8091
|
if (value) {
|
|
7510
8092
|
clearRevealedIds();
|
|
8093
|
+
clearExpandAroundState();
|
|
7511
8094
|
setSelectedElement(null);
|
|
7512
8095
|
}
|
|
7513
8096
|
});
|
|
@@ -7515,20 +8098,23 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7515
8098
|
setDiagnosticsHidden(value);
|
|
7516
8099
|
if (value) {
|
|
7517
8100
|
clearRevealedIds();
|
|
8101
|
+
clearExpandAroundState();
|
|
7518
8102
|
}
|
|
7519
8103
|
});
|
|
7520
8104
|
const revealAllResources = useEffectEvent(() => {
|
|
7521
8105
|
setResourcesHidden(false);
|
|
7522
8106
|
setDiagnosticsHidden(false);
|
|
7523
8107
|
clearRevealedIds();
|
|
8108
|
+
clearExpandAroundState();
|
|
7524
8109
|
});
|
|
7525
8110
|
const handleSelectElement = useEffectEvent((element) => {
|
|
7526
8111
|
if (!element) {
|
|
7527
|
-
if (!selectedElement && revealedIds.size === 0) {
|
|
8112
|
+
if (!selectedElement && revealedIds.size === 0 && appliedExpandAroundNodeIds.size === 0) {
|
|
7528
8113
|
return;
|
|
7529
8114
|
}
|
|
7530
8115
|
setSelectedElement(null);
|
|
7531
8116
|
clearRevealedIds();
|
|
8117
|
+
clearExpandAroundState();
|
|
7532
8118
|
return;
|
|
7533
8119
|
}
|
|
7534
8120
|
if (mode === "map" && element.type === "node" && selectedElement?.type === "node" && selectedElement.id === element.id) {
|
|
@@ -7543,7 +8129,9 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7543
8129
|
}
|
|
7544
8130
|
} else {
|
|
7545
8131
|
clearRevealedIds();
|
|
8132
|
+
clearExpandAroundState();
|
|
7546
8133
|
}
|
|
8134
|
+
setExpandAroundPreview(null);
|
|
7547
8135
|
setSelectedElement(element);
|
|
7548
8136
|
});
|
|
7549
8137
|
useEffect(() => {
|
|
@@ -7554,8 +8142,19 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7554
8142
|
if (!elementExists) {
|
|
7555
8143
|
setSelectedElement(null);
|
|
7556
8144
|
clearRevealedIds();
|
|
8145
|
+
clearExpandAroundState();
|
|
7557
8146
|
}
|
|
7558
|
-
}, [clearRevealedIds, selectedElement, visibleGraph]);
|
|
8147
|
+
}, [clearExpandAroundState, clearRevealedIds, selectedElement, visibleGraph]);
|
|
8148
|
+
useEffect(() => {
|
|
8149
|
+
if (lens !== "command-view" || !graph || appliedExpandAroundNodeIds.size === 0) {
|
|
8150
|
+
return;
|
|
8151
|
+
}
|
|
8152
|
+
const graphNodeIds = new Set(graph.nodes.map((node) => node.id));
|
|
8153
|
+
const expansionStillExists = [...appliedExpandAroundNodeIds].some((nodeId2) => graphNodeIds.has(nodeId2));
|
|
8154
|
+
if (!expansionStillExists) {
|
|
8155
|
+
clearExpandAroundState();
|
|
8156
|
+
}
|
|
8157
|
+
}, [appliedExpandAroundNodeIds, clearExpandAroundState, graph, lens]);
|
|
7559
8158
|
useEffect(() => {
|
|
7560
8159
|
if (lens !== "command-view") {
|
|
7561
8160
|
return;
|
|
@@ -7658,6 +8257,8 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7658
8257
|
traceResult: activeTraceResult,
|
|
7659
8258
|
hiddenIds: EMPTY_GRAPH_HIDDEN_IDS,
|
|
7660
8259
|
hiddenEdgeIds: EMPTY_GRAPH_HIDDEN_EDGE_IDS,
|
|
8260
|
+
expandedNodeIds: lens === "command-view" ? appliedExpandAroundNodeIds : EMPTY_EXPANDED_NODE_IDS,
|
|
8261
|
+
expandedEdgeIds: lens === "command-view" ? appliedExpandAroundEdgeIds : EMPTY_EXPANDED_EDGE_IDS,
|
|
7661
8262
|
themeTokens,
|
|
7662
8263
|
commandViewHealthByNodeId,
|
|
7663
8264
|
focusRequest,
|
|
@@ -7897,9 +8498,27 @@ function OrganizationGraphPage({ lens = "default", timeRange = "30d" }) {
|
|
|
7897
8498
|
selectedElement,
|
|
7898
8499
|
supplementalSummary: selectionOperationalSummary,
|
|
7899
8500
|
followUpSections,
|
|
8501
|
+
expandAroundPanel: lens === "command-view" ? /* @__PURE__ */ jsx(
|
|
8502
|
+
ExpandAroundPanel,
|
|
8503
|
+
{
|
|
8504
|
+
selectedNode: selectedGraphNode,
|
|
8505
|
+
value: expandAroundValue,
|
|
8506
|
+
result: expandAroundPreview,
|
|
8507
|
+
appliedNodeCount: appliedExpandAroundNodeIds.size,
|
|
8508
|
+
appliedEdgeCount: appliedExpandAroundEdgeIds.size,
|
|
8509
|
+
onChange: (next) => {
|
|
8510
|
+
setExpandAroundValue(next);
|
|
8511
|
+
setExpandAroundPreview(null);
|
|
8512
|
+
},
|
|
8513
|
+
onPreview: previewExpandAround,
|
|
8514
|
+
onApply: applyExpandAroundPreview,
|
|
8515
|
+
onClear: clearExpandAroundState
|
|
8516
|
+
}
|
|
8517
|
+
) : null,
|
|
7900
8518
|
onClearSelection: () => {
|
|
7901
8519
|
setSelectedElement(null);
|
|
7902
8520
|
clearRevealedIds();
|
|
8521
|
+
clearExpandAroundState();
|
|
7903
8522
|
}
|
|
7904
8523
|
}
|
|
7905
8524
|
) }),
|