@elevasis/ui 2.31.0 → 2.33.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/{CoreAuthKitInner-KSEGSB67.js → CoreAuthKitInner-QC62UHTZ.js} +1 -1
- package/dist/api/index.js +3 -3
- package/dist/app/index.css +38 -0
- package/dist/app/index.d.ts +69 -9
- package/dist/app/index.js +7 -6
- package/dist/auth/context.js +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/charts/index.js +5 -6
- package/dist/{chunk-JKSUN5GN.js → chunk-2GMF5IRF.js} +81 -746
- package/dist/{chunk-XQHZBA65.js → chunk-2RJMVWFJ.js} +1 -6
- package/dist/{chunk-CW3UNAF2.js → chunk-4DYOXEH6.js} +410 -5
- package/dist/{chunk-HQGF4ATG.js → chunk-52NLZN6Z.js} +118 -141
- package/dist/chunk-AHCKOU2M.js +13 -0
- package/dist/chunk-CLDCYJQT.js +1 -0
- package/dist/chunk-DWXDNT7P.js +145 -0
- package/dist/chunk-E4T2N7P7.js +124 -0
- package/dist/{chunk-HYNYEBHM.js → chunk-E7C4XEWH.js} +3 -3
- package/dist/{chunk-L3BVJWML.js → chunk-EPTHX4VZ.js} +1 -1
- package/dist/{chunk-QDEETKYT.js → chunk-FFPHJBJC.js} +9 -9
- package/dist/chunk-GNRMB6DC.js +5126 -0
- package/dist/{chunk-DZTG5IAC.js → chunk-I2KLQ2HA.js} +1 -7
- package/dist/{chunk-Q6OYNEGR.js → chunk-IUKFNASA.js} +5 -6
- package/dist/{chunk-QHEWXU7I.js → chunk-JFL3GRD4.js} +1 -1
- package/dist/{chunk-T3IPHEYJ.js → chunk-JHT5JIJ3.js} +4410 -566
- package/dist/{chunk-L2NVFLXU.js → chunk-MHLZ4F4N.js} +4 -4
- package/dist/{chunk-XQQEKWTL.js → chunk-N55DVMAG.js} +6 -2
- package/dist/{chunk-TOIXUWR6.js → chunk-ND5TDV2J.js} +1 -1
- package/dist/{chunk-5LJAEZMA.js → chunk-NOIRGGW2.js} +5 -6
- package/dist/{chunk-7KC4P3AU.js → chunk-QNOVUCSV.js} +2 -12
- package/dist/{chunk-3BAPR3KA.js → chunk-RQA2EVN3.js} +5 -15
- package/dist/{chunk-ND42LPY4.js → chunk-TKF5S4XP.js} +6 -6
- package/dist/{chunk-DWK2QIAK.js → chunk-TYRUKGGD.js} +1 -1
- package/dist/{chunk-Y4FWCG7Y.js → chunk-UVFOURXR.js} +8 -7
- package/dist/chunk-UW7IV2Y3.js +447 -0
- package/dist/{chunk-P55BJZZW.js → chunk-V6SZ4ECN.js} +20 -5
- package/dist/{chunk-6YT4IKJ7.js → chunk-VNAZTCHA.js} +15 -0
- package/dist/chunk-XG57WXOL.js +85 -0
- package/dist/{chunk-SHQXMW4F.js → chunk-XOFSMJLF.js} +46 -28
- package/dist/{chunk-7HMCB26R.js → chunk-XZGSCABI.js} +1 -1
- package/dist/chunk-YAQ25UNM.js +2126 -0
- package/dist/chunk-ZGTDKH3P.js +467 -0
- package/dist/components/chat/index.js +1 -1
- package/dist/components/index.css +38 -0
- package/dist/components/index.d.ts +262 -51
- package/dist/components/index.js +37 -39
- package/dist/components/navigation/index.css +38 -0
- package/dist/components/navigation/index.js +5 -3
- package/dist/execution/index.d.ts +11 -2
- package/dist/execution/index.js +1 -1
- package/dist/features/auth/index.css +38 -0
- package/dist/features/auth/index.d.ts +91 -14
- package/dist/features/auth/index.js +42 -10
- package/dist/features/clients/index.css +38 -0
- package/dist/features/clients/index.d.ts +1 -1
- package/dist/features/clients/index.js +17 -15
- package/dist/features/crm/index.css +38 -0
- package/dist/features/crm/index.d.ts +80 -18
- package/dist/features/crm/index.js +17 -15
- package/dist/features/dashboard/index.css +38 -0
- package/dist/features/dashboard/index.d.ts +174 -25
- package/dist/features/dashboard/index.js +17 -16
- package/dist/features/delivery/index.css +38 -0
- package/dist/features/delivery/index.d.ts +80 -18
- package/dist/features/delivery/index.js +16 -15
- package/dist/features/knowledge/index.css +38 -0
- package/dist/features/knowledge/index.d.ts +20 -18
- package/dist/features/knowledge/index.js +114 -609
- package/dist/features/lead-gen/index.css +38 -0
- package/dist/features/lead-gen/index.d.ts +45 -43
- package/dist/features/lead-gen/index.js +17 -16
- package/dist/features/monitoring/index.css +38 -0
- package/dist/features/monitoring/index.d.ts +20 -18
- package/dist/features/monitoring/index.js +18 -17
- package/dist/features/monitoring/requests/index.css +38 -0
- package/dist/features/monitoring/requests/index.d.ts +23 -21
- package/dist/features/monitoring/requests/index.js +16 -14
- package/dist/features/operations/index.css +38 -0
- package/dist/features/operations/index.d.ts +1299 -66
- package/dist/features/operations/index.js +22 -24
- package/dist/features/seo/index.d.ts +20 -18
- package/dist/features/seo/index.js +2 -2
- package/dist/features/settings/index.css +38 -0
- package/dist/features/settings/index.d.ts +80 -18
- package/dist/features/settings/index.js +17 -15
- package/dist/graph/index.js +1 -1
- package/dist/hooks/delivery/index.css +38 -0
- package/dist/hooks/delivery/index.d.ts +60 -0
- package/dist/hooks/delivery/index.js +3 -3
- package/dist/hooks/index.css +38 -0
- package/dist/hooks/index.d.ts +492 -89
- package/dist/hooks/index.js +15 -13
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +332 -33
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.js +1 -1
- package/dist/hooks/published.css +38 -0
- package/dist/hooks/published.d.ts +492 -89
- package/dist/hooks/published.js +15 -13
- package/dist/index.css +38 -0
- package/dist/index.d.ts +1353 -1349
- package/dist/index.js +16 -14
- package/dist/initialization/index.d.ts +60 -0
- package/dist/initialization/index.js +1 -1
- package/dist/knowledge/index.d.ts +1217 -1292
- package/dist/knowledge/index.js +6538 -2198
- package/dist/knowledge-search-index-P7PR626V.js +1514 -0
- package/dist/layout/index.js +3 -4
- package/dist/organization/index.css +38 -0
- package/dist/organization/index.js +1 -1
- package/dist/profile/index.d.ts +60 -0
- package/dist/profile/index.js +1 -1
- package/dist/provider/ElevasisServiceContext.js +1 -1
- package/dist/provider/index.css +38 -0
- package/dist/provider/index.d.ts +1068 -1246
- package/dist/provider/index.js +12 -10
- package/dist/provider/published.css +38 -0
- package/dist/provider/published.d.ts +1065 -1243
- package/dist/provider/published.js +9 -7
- package/dist/router/context.js +1 -1
- package/dist/router/index.js +1 -1
- package/dist/sse/index.js +1 -1
- package/dist/supabase/index.d.ts +117 -0
- package/dist/supabase/index.js +1 -1
- package/dist/test-utils/index.d.ts +16 -9
- package/dist/test-utils/index.js +40 -33
- package/dist/test-utils/setup-integration.js +1 -1
- package/dist/test-utils/setup.js +1 -1
- package/dist/theme/index.js +3 -3
- package/dist/theme/presets/index.js +1 -1
- package/dist/typeform/index.js +1 -1
- package/dist/typeform/schemas.js +1 -1
- package/dist/types/index.d.ts +394 -35
- package/dist/utils/index.d.ts +174 -25
- package/dist/utils/index.js +2 -2
- package/dist/vite/index.js +1 -1
- package/dist/vite-plugin-knowledge/index.js +1 -1
- package/dist/zustand/index.js +1 -1
- package/package.json +10 -9
- package/src/README.md +29 -29
- package/src/api/README.md +18 -18
- package/src/app/README.md +24 -24
- package/src/auth/README.md +18 -18
- package/src/components/README.md +24 -24
- package/src/execution/README.md +16 -16
- package/src/features/README.md +28 -28
- package/src/graph/README.md +16 -16
- package/src/hooks/README.md +23 -23
- package/src/initialization/README.md +19 -19
- package/src/knowledge/README.md +31 -31
- package/src/organization/README.md +18 -18
- package/src/profile/README.md +19 -19
- package/src/provider/README.md +32 -32
- package/src/router/README.md +18 -18
- package/src/sse/README.md +13 -13
- package/src/test-utils/README.md +7 -7
- package/src/theme/README.md +23 -23
- package/src/theme/presets/README.md +19 -19
- package/src/types/README.md +16 -16
- package/src/utils/README.md +18 -18
- package/src/zustand/README.md +18 -18
- package/dist/chunk-542WPQU2.js +0 -413
- package/dist/chunk-6IXOKUBC.js +0 -347
- package/dist/chunk-CQZ3DNQY.js +0 -740
- package/dist/chunk-ECNNI3NT.js +0 -6
- package/dist/chunk-GRDLB6LM.js +0 -160
- package/dist/chunk-JDNEWB5F.js +0 -10
- package/dist/chunk-MVFCLZSK.js +0 -4337
- package/dist/chunk-O2QOPJI5.js +0 -2235
- package/dist/chunk-OAVTMITG.js +0 -13
- package/dist/chunk-TVRQ6AQI.js +0 -476
- package/dist/chunk-WF227UBV.js +0 -48
|
@@ -0,0 +1,2126 @@
|
|
|
1
|
+
import { SemanticIcon } from './chunk-DWXDNT7P.js';
|
|
2
|
+
import { buildOrganizationGraph, projectOrganizationSurfaces, compileOrganizationOntology, getSortedSidebarEntries, parseOntologyId, getSystem, resolveSystemConfig } from './chunk-GNRMB6DC.js';
|
|
3
|
+
import { useMemo, useState, useRef, useEffect } from 'react';
|
|
4
|
+
import { useTree, Text, Tree, UnstyledButton, Group, TextInput } from '@mantine/core';
|
|
5
|
+
import { useClipboard } from '@mantine/hooks';
|
|
6
|
+
import { IconChevronDown, IconChevronRight, IconX, IconSearch, IconCheck, IconCopy, IconStarFilled, IconStar } from '@tabler/icons-react';
|
|
7
|
+
import { create } from 'zustand';
|
|
8
|
+
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
9
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
// src/organization-model/getSharedOrganizationGraph.ts
|
|
12
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
13
|
+
function getSharedOrganizationGraph(organizationModel) {
|
|
14
|
+
const cached = cache.get(organizationModel);
|
|
15
|
+
if (cached) return cached;
|
|
16
|
+
const graph = buildOrganizationGraph({ organizationModel });
|
|
17
|
+
cache.set(organizationModel, graph);
|
|
18
|
+
return graph;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/knowledge/iconTokens.ts
|
|
22
|
+
var KNOWLEDGE_ICON_TOKEN_BY_KIND = {
|
|
23
|
+
playbook: "playbook",
|
|
24
|
+
strategy: "strategy",
|
|
25
|
+
reference: "reference"
|
|
26
|
+
};
|
|
27
|
+
function getKnowledgeIconToken(node) {
|
|
28
|
+
return node.icon ?? KNOWLEDGE_ICON_TOKEN_BY_KIND[node.kind];
|
|
29
|
+
}
|
|
30
|
+
var useKnowledgeFavoritesStore = create()(
|
|
31
|
+
persist(
|
|
32
|
+
(set) => ({
|
|
33
|
+
favorites: {},
|
|
34
|
+
toggleFavorite: (entry) => set((state) => {
|
|
35
|
+
const next = { ...state.favorites };
|
|
36
|
+
if (next[entry.routeId]) {
|
|
37
|
+
delete next[entry.routeId];
|
|
38
|
+
} else {
|
|
39
|
+
next[entry.routeId] = { ...entry, addedAt: Date.now() };
|
|
40
|
+
}
|
|
41
|
+
return { favorites: next };
|
|
42
|
+
}),
|
|
43
|
+
removeFavorite: (routeId) => set((state) => {
|
|
44
|
+
if (!state.favorites[routeId]) return state;
|
|
45
|
+
const next = { ...state.favorites };
|
|
46
|
+
delete next[routeId];
|
|
47
|
+
return { favorites: next };
|
|
48
|
+
}),
|
|
49
|
+
clearFavorites: () => set({ favorites: {} })
|
|
50
|
+
}),
|
|
51
|
+
{
|
|
52
|
+
name: "elevasis-knowledge-favorites",
|
|
53
|
+
storage: createJSONStorage(() => localStorage),
|
|
54
|
+
version: 1
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// src/knowledge/navigationProjection.ts
|
|
60
|
+
function collectSurfaceIds(nodes) {
|
|
61
|
+
return getSortedSidebarEntries(nodes).flatMap(
|
|
62
|
+
([id, node]) => node.type === "group" ? collectSurfaceIds(node.children) : [id]
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function collectGroups(nodes, placement, groups = []) {
|
|
66
|
+
getSortedSidebarEntries(nodes).forEach(([id, node]) => {
|
|
67
|
+
if (node.type !== "group") return;
|
|
68
|
+
groups.push({
|
|
69
|
+
id,
|
|
70
|
+
label: node.label,
|
|
71
|
+
placement,
|
|
72
|
+
surfaceIds: collectSurfaceIds(node.children)
|
|
73
|
+
});
|
|
74
|
+
collectGroups(node.children, placement, groups);
|
|
75
|
+
});
|
|
76
|
+
return groups;
|
|
77
|
+
}
|
|
78
|
+
function projectNavigationSurfaces(model) {
|
|
79
|
+
return projectOrganizationSurfaces(model);
|
|
80
|
+
}
|
|
81
|
+
function projectNavigationGroups(model) {
|
|
82
|
+
return [
|
|
83
|
+
...collectGroups(model.navigation.sidebar.primary, "primary"),
|
|
84
|
+
...collectGroups(model.navigation.sidebar.bottom, "bottom")
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/knowledge/ontologyProjection.ts
|
|
89
|
+
var DOMAIN_LABELS = {
|
|
90
|
+
"ontology-objects": "Objects",
|
|
91
|
+
"ontology-links": "Links",
|
|
92
|
+
"ontology-actions": "Actions",
|
|
93
|
+
"ontology-catalogs": "Catalogs",
|
|
94
|
+
"ontology-events": "Events",
|
|
95
|
+
"ontology-interfaces": "Interfaces",
|
|
96
|
+
"ontology-value-types": "Value Types",
|
|
97
|
+
"ontology-properties": "Shared Properties",
|
|
98
|
+
"ontology-groups": "Groups",
|
|
99
|
+
"ontology-surfaces": "Surfaces",
|
|
100
|
+
"ontology-resources": "Resources"
|
|
101
|
+
};
|
|
102
|
+
function titleFromId(id) {
|
|
103
|
+
const localId = id.includes("/") ? id.slice(id.lastIndexOf("/") + 1) : id;
|
|
104
|
+
return localId.replace(/[-_.]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w/g, (char) => char.toUpperCase());
|
|
105
|
+
}
|
|
106
|
+
function isLegacyBridgeRecord(record) {
|
|
107
|
+
return typeof record["legacyEntityId"] === "string" || typeof record["legacyActionId"] === "string" || typeof record["legacyContentId"] === "string";
|
|
108
|
+
}
|
|
109
|
+
function ontologyItem(id, record, fallbackKind) {
|
|
110
|
+
let parsed;
|
|
111
|
+
try {
|
|
112
|
+
parsed = parseOntologyId(id);
|
|
113
|
+
} catch {
|
|
114
|
+
parsed = void 0;
|
|
115
|
+
}
|
|
116
|
+
const ownerSystemId = typeof record["ownerSystemId"] === "string" ? record["ownerSystemId"] : parsed?.isGlobal === false ? parsed.scope : void 0;
|
|
117
|
+
const meta = {};
|
|
118
|
+
for (const [key, value] of Object.entries(record)) {
|
|
119
|
+
if (["id", "label", "description", "ownerSystemId", "aliases"].includes(key)) continue;
|
|
120
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
121
|
+
meta[key] = value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
id,
|
|
126
|
+
label: typeof record["label"] === "string" ? record["label"] : titleFromId(id),
|
|
127
|
+
description: typeof record["description"] === "string" ? record["description"] : void 0,
|
|
128
|
+
kind: parsed?.kind ?? fallbackKind,
|
|
129
|
+
ownerSystemId,
|
|
130
|
+
source: isLegacyBridgeRecord(record) ? "legacy-bridge" : "ontology",
|
|
131
|
+
meta
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function sortItems(items) {
|
|
135
|
+
return [...items].sort(
|
|
136
|
+
(left, right) => (left.ownerSystemId ?? "").localeCompare(right.ownerSystemId ?? "") || left.label.localeCompare(right.label) || left.id.localeCompare(right.id)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
function resourceDescription(resource) {
|
|
140
|
+
return resource.codeRefs.find((codeRef) => codeRef.description !== void 0)?.description;
|
|
141
|
+
}
|
|
142
|
+
function getKnowledgeOntologyProjection(model) {
|
|
143
|
+
const compiled = compileOrganizationOntology(model);
|
|
144
|
+
return {
|
|
145
|
+
objects: sortItems(
|
|
146
|
+
Object.entries(compiled.ontology.objectTypes).map(
|
|
147
|
+
([id, record]) => ontologyItem(id, record, "object")
|
|
148
|
+
)
|
|
149
|
+
),
|
|
150
|
+
links: sortItems(
|
|
151
|
+
Object.entries(compiled.ontology.linkTypes).map(
|
|
152
|
+
([id, record]) => ontologyItem(id, record, "link")
|
|
153
|
+
)
|
|
154
|
+
),
|
|
155
|
+
actions: sortItems(
|
|
156
|
+
Object.entries(compiled.ontology.actionTypes).map(
|
|
157
|
+
([id, record]) => ontologyItem(id, record, "action")
|
|
158
|
+
)
|
|
159
|
+
),
|
|
160
|
+
catalogs: sortItems(
|
|
161
|
+
Object.entries(compiled.ontology.catalogTypes).map(
|
|
162
|
+
([id, record]) => ontologyItem(id, record, "catalog")
|
|
163
|
+
)
|
|
164
|
+
),
|
|
165
|
+
events: sortItems(
|
|
166
|
+
Object.entries(compiled.ontology.eventTypes).map(
|
|
167
|
+
([id, record]) => ontologyItem(id, record, "event")
|
|
168
|
+
)
|
|
169
|
+
),
|
|
170
|
+
interfaces: sortItems(
|
|
171
|
+
Object.entries(compiled.ontology.interfaceTypes).map(
|
|
172
|
+
([id, record]) => ontologyItem(id, record, "interface")
|
|
173
|
+
)
|
|
174
|
+
),
|
|
175
|
+
valueTypes: sortItems(
|
|
176
|
+
Object.entries(compiled.ontology.valueTypes).map(
|
|
177
|
+
([id, record]) => ontologyItem(id, record, "value-type")
|
|
178
|
+
)
|
|
179
|
+
),
|
|
180
|
+
properties: sortItems(
|
|
181
|
+
Object.entries(compiled.ontology.sharedProperties).map(
|
|
182
|
+
([id, record]) => ontologyItem(id, record, "property")
|
|
183
|
+
)
|
|
184
|
+
),
|
|
185
|
+
groups: sortItems(
|
|
186
|
+
Object.entries(compiled.ontology.groups).map(
|
|
187
|
+
([id, record]) => ontologyItem(id, record, "group")
|
|
188
|
+
)
|
|
189
|
+
),
|
|
190
|
+
surfaces: sortItems(
|
|
191
|
+
Object.entries(compiled.ontology.surfaces).map(
|
|
192
|
+
([id, record]) => ontologyItem(id, record, "surface")
|
|
193
|
+
)
|
|
194
|
+
),
|
|
195
|
+
resources: sortItems(
|
|
196
|
+
Object.values(model.resources ?? {}).map((resource) => ({
|
|
197
|
+
id: resource.id,
|
|
198
|
+
label: resource.id,
|
|
199
|
+
description: resourceDescription(resource),
|
|
200
|
+
kind: "resource",
|
|
201
|
+
ownerSystemId: resource.systemPath,
|
|
202
|
+
source: "resource",
|
|
203
|
+
meta: { type: resource.kind, status: resource.status }
|
|
204
|
+
}))
|
|
205
|
+
),
|
|
206
|
+
diagnosticsCount: compiled.diagnostics.length
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function getOntologyItemsForDomain(projection, domainKey) {
|
|
210
|
+
switch (domainKey) {
|
|
211
|
+
case "ontology-objects":
|
|
212
|
+
return projection.objects;
|
|
213
|
+
case "ontology-links":
|
|
214
|
+
return projection.links;
|
|
215
|
+
case "ontology-actions":
|
|
216
|
+
return projection.actions;
|
|
217
|
+
case "ontology-catalogs":
|
|
218
|
+
return projection.catalogs;
|
|
219
|
+
case "ontology-events":
|
|
220
|
+
return projection.events;
|
|
221
|
+
case "ontology-interfaces":
|
|
222
|
+
return projection.interfaces;
|
|
223
|
+
case "ontology-value-types":
|
|
224
|
+
return projection.valueTypes;
|
|
225
|
+
case "ontology-properties":
|
|
226
|
+
return projection.properties;
|
|
227
|
+
case "ontology-groups":
|
|
228
|
+
return projection.groups;
|
|
229
|
+
case "ontology-surfaces":
|
|
230
|
+
return projection.surfaces;
|
|
231
|
+
case "ontology-resources":
|
|
232
|
+
return projection.resources;
|
|
233
|
+
default:
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function getPrimaryOntologyItemsForDomain(projection, domainKey) {
|
|
238
|
+
return getOntologyItemsForDomain(projection, domainKey).filter((item) => item.source !== "legacy-bridge");
|
|
239
|
+
}
|
|
240
|
+
function getOntologyDomainLabel(domainKey) {
|
|
241
|
+
return DOMAIN_LABELS[domainKey] ?? "Ontology";
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/knowledge/knowledgeCopyCommands.ts
|
|
245
|
+
function stripGraphKindPrefix(id, kind) {
|
|
246
|
+
const prefix = `${kind}:`;
|
|
247
|
+
return id.startsWith(prefix) ? id.slice(prefix.length) : id;
|
|
248
|
+
}
|
|
249
|
+
function normalizeKnowledgeNodeId(nodeId) {
|
|
250
|
+
return nodeId.startsWith("knowledge:") ? nodeId.slice("knowledge:".length) : nodeId;
|
|
251
|
+
}
|
|
252
|
+
function getKnowledgeNodeReadCommand(nodeId) {
|
|
253
|
+
return `/knowledge read ${normalizeKnowledgeNodeId(nodeId)}`;
|
|
254
|
+
}
|
|
255
|
+
function getKnowledgeNodeReadCommands(nodeIds) {
|
|
256
|
+
return [...new Set(nodeIds)].map(getKnowledgeNodeReadCommand).join("\n");
|
|
257
|
+
}
|
|
258
|
+
function getKnowledgeFolderCommand(kind, id) {
|
|
259
|
+
return `/knowledge read-folder ${kind}:${id}`;
|
|
260
|
+
}
|
|
261
|
+
function getKnowledgeTreeFolderCommand(treeValue) {
|
|
262
|
+
return `/knowledge read-folder ${treeValue}`;
|
|
263
|
+
}
|
|
264
|
+
function getKnowledgeDomainFolderCommand(domainKey) {
|
|
265
|
+
return getKnowledgeFolderCommand("domain", domainKey);
|
|
266
|
+
}
|
|
267
|
+
function getKnowledgeGraphFolderCommand(graphNodeId) {
|
|
268
|
+
return getKnowledgeFolderCommand("graph", graphNodeId);
|
|
269
|
+
}
|
|
270
|
+
function getKnowledgeSpineFolderCommand(spine, id) {
|
|
271
|
+
const bareId = stripGraphKindPrefix(id, spine);
|
|
272
|
+
if (spine === "system") return getKnowledgeFolderCommand("system", bareId);
|
|
273
|
+
if (spine === "ontology") return getKnowledgeFolderCommand("ontology", bareId);
|
|
274
|
+
return getKnowledgeGraphFolderCommand(`${spine}:${bareId}`);
|
|
275
|
+
}
|
|
276
|
+
function getKnowledgeGraphNodeCommand(node) {
|
|
277
|
+
if (node.kind === "knowledge") {
|
|
278
|
+
return getKnowledgeNodeReadCommand(node.sourceId ?? node.id);
|
|
279
|
+
}
|
|
280
|
+
if (node.kind === "system") {
|
|
281
|
+
return getKnowledgeFolderCommand("system", node.sourceId ?? stripGraphKindPrefix(node.id, "system"));
|
|
282
|
+
}
|
|
283
|
+
if (node.kind === "ontology") {
|
|
284
|
+
return getKnowledgeFolderCommand("ontology", node.sourceId ?? stripGraphKindPrefix(node.id, "ontology"));
|
|
285
|
+
}
|
|
286
|
+
return getKnowledgeGraphFolderCommand(node.id);
|
|
287
|
+
}
|
|
288
|
+
function graphKindToFallbackToken(kind) {
|
|
289
|
+
switch (kind) {
|
|
290
|
+
case "knowledge":
|
|
291
|
+
return "reference";
|
|
292
|
+
case "resource":
|
|
293
|
+
return "workflow";
|
|
294
|
+
case "action":
|
|
295
|
+
return "view";
|
|
296
|
+
case "entity":
|
|
297
|
+
case "event":
|
|
298
|
+
return "database";
|
|
299
|
+
case "policy":
|
|
300
|
+
return "shield";
|
|
301
|
+
case "system":
|
|
302
|
+
return "operations";
|
|
303
|
+
case "role":
|
|
304
|
+
return "user";
|
|
305
|
+
case "stage":
|
|
306
|
+
return "pending";
|
|
307
|
+
case "organization":
|
|
308
|
+
return "building";
|
|
309
|
+
default:
|
|
310
|
+
return "info";
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
var QUICK_ACCESS_GROUP_KEY = "quick-access";
|
|
314
|
+
var FAVORITE_PREFIX = "favorite:";
|
|
315
|
+
var QUICK_ACCESS_GROUP_VALUE = `group:${QUICK_ACCESS_GROUP_KEY}`;
|
|
316
|
+
var GROUP_ICON_TOKENS = {
|
|
317
|
+
[QUICK_ACCESS_GROUP_KEY]: "om.quick-access",
|
|
318
|
+
profile: "om.profile",
|
|
319
|
+
"business-model": "om.business-model",
|
|
320
|
+
systems: "om.systems",
|
|
321
|
+
graph: "om.graph",
|
|
322
|
+
resources: "resources",
|
|
323
|
+
knowledge: "knowledge",
|
|
324
|
+
navigation: "view",
|
|
325
|
+
"governance-wiring": "om.governance-wiring"
|
|
326
|
+
};
|
|
327
|
+
function findFavoritePathInTree(nodes, favorite) {
|
|
328
|
+
const matchesPrimary = (node) => {
|
|
329
|
+
if (favorite.kind === "knowledge") {
|
|
330
|
+
return node.nodeType === "leaf" && node.knowledgeNodeId === favorite.routeId;
|
|
331
|
+
}
|
|
332
|
+
if (favorite.kind === "graph") {
|
|
333
|
+
return node.graphNodeId === favorite.routeId;
|
|
334
|
+
}
|
|
335
|
+
return typeof node.value === "string" && node.value === favorite.routeId;
|
|
336
|
+
};
|
|
337
|
+
const matchesFallback = (node) => {
|
|
338
|
+
if (favorite.kind !== "knowledge") return false;
|
|
339
|
+
return node.nodeType === "item" && node.domainKey === "knowledge" && node.itemId === favorite.routeId;
|
|
340
|
+
};
|
|
341
|
+
function dfs(node, ancestors, match) {
|
|
342
|
+
if (node.value === QUICK_ACCESS_GROUP_VALUE) return void 0;
|
|
343
|
+
const value = typeof node.value === "string" ? node.value : "";
|
|
344
|
+
const path = [...ancestors, value];
|
|
345
|
+
if (match(node)) return path;
|
|
346
|
+
for (const child of node.children ?? []) {
|
|
347
|
+
const found = dfs(child, path, match);
|
|
348
|
+
if (found) return found;
|
|
349
|
+
}
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
for (const root of nodes) {
|
|
353
|
+
const found = dfs(root, [], matchesPrimary);
|
|
354
|
+
if (found) return found;
|
|
355
|
+
}
|
|
356
|
+
for (const root of nodes) {
|
|
357
|
+
const found = dfs(root, [], matchesFallback);
|
|
358
|
+
if (found) return found;
|
|
359
|
+
}
|
|
360
|
+
return void 0;
|
|
361
|
+
}
|
|
362
|
+
var OM_TREE_GROUPS = [
|
|
363
|
+
{ key: "profile", label: "Profile", domains: ["identity", "branding"] },
|
|
364
|
+
{ key: "business-model", label: "Business Model", domains: ["customers", "offerings", "goals"] },
|
|
365
|
+
{ key: "systems", label: "Systems", domains: ["systems", "sales", "prospecting", "projects"] },
|
|
366
|
+
{
|
|
367
|
+
key: "graph",
|
|
368
|
+
label: "Ontology",
|
|
369
|
+
domains: [
|
|
370
|
+
"ontology-objects",
|
|
371
|
+
"ontology-links",
|
|
372
|
+
"ontology-actions",
|
|
373
|
+
"ontology-catalogs",
|
|
374
|
+
"ontology-events",
|
|
375
|
+
"ontology-interfaces",
|
|
376
|
+
"ontology-value-types",
|
|
377
|
+
"ontology-properties",
|
|
378
|
+
"ontology-groups",
|
|
379
|
+
"ontology-surfaces"
|
|
380
|
+
]
|
|
381
|
+
},
|
|
382
|
+
{ key: "resources", label: "Resources", domains: ["resources"] },
|
|
383
|
+
{ key: "knowledge", label: "Knowledge", domains: ["knowledge"] },
|
|
384
|
+
{ key: "navigation", label: "Navigation", domains: ["navigation"] },
|
|
385
|
+
{ key: "governance-wiring", label: "Governance", domains: ["roles", "policies"] }
|
|
386
|
+
];
|
|
387
|
+
var DOMAIN_PREFIX = "domain:";
|
|
388
|
+
var GROUP_PREFIX = "group:";
|
|
389
|
+
var ITEM_PREFIX = "item:";
|
|
390
|
+
function domainKeyForKnowledgeTarget(targetKind) {
|
|
391
|
+
switch (targetKind) {
|
|
392
|
+
case "customer-segment":
|
|
393
|
+
return "customers";
|
|
394
|
+
case "offering":
|
|
395
|
+
return "offerings";
|
|
396
|
+
case "goal":
|
|
397
|
+
return "goals";
|
|
398
|
+
case "role":
|
|
399
|
+
return "roles";
|
|
400
|
+
default:
|
|
401
|
+
return void 0;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
function graphNodeIdForKnowledgeTarget(targetKind, targetId) {
|
|
405
|
+
switch (targetKind) {
|
|
406
|
+
case "resource":
|
|
407
|
+
case "action":
|
|
408
|
+
case "entity":
|
|
409
|
+
case "event":
|
|
410
|
+
case "policy":
|
|
411
|
+
case "role":
|
|
412
|
+
case "knowledge":
|
|
413
|
+
case "ontology":
|
|
414
|
+
case "system":
|
|
415
|
+
case "stage":
|
|
416
|
+
return `${targetKind}:${targetId}`;
|
|
417
|
+
default:
|
|
418
|
+
return void 0;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
var GRAPH_RESOURCE_TYPE_ORDER = [
|
|
422
|
+
"workflow",
|
|
423
|
+
"agent",
|
|
424
|
+
"integration",
|
|
425
|
+
"script",
|
|
426
|
+
"external",
|
|
427
|
+
"trigger",
|
|
428
|
+
"human_checkpoint"
|
|
429
|
+
];
|
|
430
|
+
var GRAPH_RESOURCE_TYPE_LABELS = {
|
|
431
|
+
workflow: "Workflows",
|
|
432
|
+
agent: "Agents",
|
|
433
|
+
integration: "Integrations",
|
|
434
|
+
script: "Scripts",
|
|
435
|
+
external: "External",
|
|
436
|
+
trigger: "Triggers",
|
|
437
|
+
human_checkpoint: "Human Checkpoints"
|
|
438
|
+
};
|
|
439
|
+
var CORE_ONTOLOGY_DOMAIN_KEYS = [
|
|
440
|
+
"ontology-objects",
|
|
441
|
+
"ontology-links",
|
|
442
|
+
"ontology-actions",
|
|
443
|
+
"ontology-catalogs",
|
|
444
|
+
"ontology-events",
|
|
445
|
+
"ontology-surfaces"
|
|
446
|
+
];
|
|
447
|
+
var OPTIONAL_ONTOLOGY_DOMAIN_KEYS = [
|
|
448
|
+
"ontology-interfaces",
|
|
449
|
+
"ontology-value-types",
|
|
450
|
+
"ontology-properties",
|
|
451
|
+
"ontology-groups"
|
|
452
|
+
];
|
|
453
|
+
var KNOWLEDGE_START_HERE_IDS = [
|
|
454
|
+
"knowledge.org-model-reference",
|
|
455
|
+
"knowledge.org-model-graph-contract",
|
|
456
|
+
"knowledge.org-model-actions",
|
|
457
|
+
"knowledge.org-model-entities",
|
|
458
|
+
"knowledge.org-model-events",
|
|
459
|
+
"knowledge.org-model-policies",
|
|
460
|
+
"knowledge.platform-command-view"
|
|
461
|
+
];
|
|
462
|
+
var SPINE_PREFIX = "spine:";
|
|
463
|
+
var LEAF_PREFIX = "leaf:";
|
|
464
|
+
var FOLDER_PREFIX = "folder:";
|
|
465
|
+
var GROUP_THRESHOLD = 8;
|
|
466
|
+
var SIDEBAR_TREE_ACCENT_COLOR = "var(--color-primary)";
|
|
467
|
+
var DEFAULT_KNOWLEDGE_FACET_STATES = { knowledge: "include" };
|
|
468
|
+
var FOLDER_ORDER = [
|
|
469
|
+
"campaigns",
|
|
470
|
+
"pipeline",
|
|
471
|
+
"targeting",
|
|
472
|
+
"channels",
|
|
473
|
+
"proof",
|
|
474
|
+
"references",
|
|
475
|
+
"playbooks",
|
|
476
|
+
"strategies"
|
|
477
|
+
];
|
|
478
|
+
var FOLDER_LABELS = {
|
|
479
|
+
campaigns: "Campaigns",
|
|
480
|
+
pipeline: "Pipeline",
|
|
481
|
+
targeting: "Targeting and Strategy",
|
|
482
|
+
channels: "Channels",
|
|
483
|
+
proof: "Proof",
|
|
484
|
+
references: "References",
|
|
485
|
+
playbooks: "Playbooks",
|
|
486
|
+
strategies: "Strategies"
|
|
487
|
+
};
|
|
488
|
+
var KNOWLEDGE_DOMAINS_WITH_PANELS = /* @__PURE__ */ new Set([
|
|
489
|
+
"identity",
|
|
490
|
+
"branding",
|
|
491
|
+
"customers",
|
|
492
|
+
"offerings",
|
|
493
|
+
"goals",
|
|
494
|
+
"roles",
|
|
495
|
+
"sales",
|
|
496
|
+
"prospecting",
|
|
497
|
+
"projects",
|
|
498
|
+
"navigation",
|
|
499
|
+
"policies",
|
|
500
|
+
"ontology-objects",
|
|
501
|
+
"ontology-links",
|
|
502
|
+
"ontology-actions",
|
|
503
|
+
"ontology-catalogs",
|
|
504
|
+
"ontology-events",
|
|
505
|
+
"ontology-interfaces",
|
|
506
|
+
"ontology-value-types",
|
|
507
|
+
"ontology-properties",
|
|
508
|
+
"ontology-groups",
|
|
509
|
+
"ontology-surfaces"
|
|
510
|
+
]);
|
|
511
|
+
var FILTERABLE_DOMAIN_KEYS = /* @__PURE__ */ new Set(["customers", "offerings", "goals", "roles", "policies"]);
|
|
512
|
+
function shouldRouteItemToDomainPanel(domainKey) {
|
|
513
|
+
return FILTERABLE_DOMAIN_KEYS.has(domainKey);
|
|
514
|
+
}
|
|
515
|
+
function toBareGraphId(graphNodeId, kind) {
|
|
516
|
+
const prefix = `${kind}:`;
|
|
517
|
+
return graphNodeId.startsWith(prefix) ? graphNodeId.slice(prefix.length) : graphNodeId;
|
|
518
|
+
}
|
|
519
|
+
function topLevelGraphIds(allBareIds) {
|
|
520
|
+
return allBareIds.filter((id) => !id.includes("."));
|
|
521
|
+
}
|
|
522
|
+
function childGraphIds(allBareIds, parentId) {
|
|
523
|
+
const prefix = `${parentId}.`;
|
|
524
|
+
return allBareIds.filter((id) => id.startsWith(prefix) && !id.slice(prefix.length).includes("."));
|
|
525
|
+
}
|
|
526
|
+
function buildTreeContext(graph, knowledgeNodes) {
|
|
527
|
+
const knowledgeByGraphId = /* @__PURE__ */ new Map();
|
|
528
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
529
|
+
for (const node of graph.nodes) {
|
|
530
|
+
nodesById.set(node.id, node);
|
|
531
|
+
if (node.kind === "knowledge") {
|
|
532
|
+
knowledgeByGraphId.set(node.id, node.sourceId ?? node.id.replace(/^knowledge:/, ""));
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const knowledgeById = new Map(knowledgeNodes.map((node) => [node.id, node]));
|
|
536
|
+
const governsRaw = /* @__PURE__ */ new Map();
|
|
537
|
+
const edgesBySource = /* @__PURE__ */ new Map();
|
|
538
|
+
const edgesByTarget = /* @__PURE__ */ new Map();
|
|
539
|
+
for (const edge of graph.edges) {
|
|
540
|
+
const src = edgesBySource.get(edge.sourceId) ?? [];
|
|
541
|
+
src.push(edge);
|
|
542
|
+
edgesBySource.set(edge.sourceId, src);
|
|
543
|
+
const tgt = edgesByTarget.get(edge.targetId) ?? [];
|
|
544
|
+
tgt.push(edge);
|
|
545
|
+
edgesByTarget.set(edge.targetId, tgt);
|
|
546
|
+
if (edge.kind === "governs") {
|
|
547
|
+
const knowledgeId = knowledgeByGraphId.get(edge.sourceId);
|
|
548
|
+
const knowledgeNode = knowledgeId ? knowledgeById.get(knowledgeId) : void 0;
|
|
549
|
+
if (knowledgeNode) {
|
|
550
|
+
const bucket = governsRaw.get(edge.targetId) ?? [];
|
|
551
|
+
bucket.push(knowledgeNode);
|
|
552
|
+
governsRaw.set(edge.targetId, bucket);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const governsEdgesByTarget = /* @__PURE__ */ new Map();
|
|
557
|
+
for (const [targetId, nodes] of governsRaw) {
|
|
558
|
+
governsEdgesByTarget.set(
|
|
559
|
+
targetId,
|
|
560
|
+
nodes.sort((a, b) => a.title.localeCompare(b.title))
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
return { governsEdgesByTarget, nodesById, edgesBySource, edgesByTarget };
|
|
564
|
+
}
|
|
565
|
+
function getKnowledgeByTarget(knowledgeNodes) {
|
|
566
|
+
const map = /* @__PURE__ */ new Map();
|
|
567
|
+
for (const node of knowledgeNodes) {
|
|
568
|
+
for (const link of node.links) {
|
|
569
|
+
const graphNodeId = graphNodeIdForKnowledgeTarget(link.target.kind, link.target.id);
|
|
570
|
+
const domainKey = domainKeyForKnowledgeTarget(link.target.kind);
|
|
571
|
+
const targetKeys = [
|
|
572
|
+
graphNodeId,
|
|
573
|
+
domainKey ? `${domainKey}:${link.target.id}` : void 0,
|
|
574
|
+
domainKey ? domainKey : void 0
|
|
575
|
+
].filter((key) => key !== void 0);
|
|
576
|
+
for (const targetKey of targetKeys) {
|
|
577
|
+
const bucket = map.get(targetKey) ?? [];
|
|
578
|
+
bucket.push(node);
|
|
579
|
+
map.set(targetKey, bucket);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return map;
|
|
584
|
+
}
|
|
585
|
+
function uniqueKnowledgeNodes(nodes) {
|
|
586
|
+
const seen = /* @__PURE__ */ new Set();
|
|
587
|
+
return nodes.sort((left, right) => left.title.localeCompare(right.title)).filter((node) => {
|
|
588
|
+
if (seen.has(node.id)) return false;
|
|
589
|
+
seen.add(node.id);
|
|
590
|
+
return true;
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
function getTargetKnowledge(knowledgeByTarget, targetKey, facetStates) {
|
|
594
|
+
if (facetStates.knowledge === "exclude") return [];
|
|
595
|
+
return uniqueKnowledgeNodes(knowledgeByTarget.get(targetKey) ?? []);
|
|
596
|
+
}
|
|
597
|
+
function sortByOrderThenLabel(items, getLabel) {
|
|
598
|
+
return [...items].sort(
|
|
599
|
+
(left, right) => (left.order ?? 0) - (right.order ?? 0) || getLabel(left).localeCompare(getLabel(right))
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
function modelRecordValues(record, getLabel) {
|
|
603
|
+
return sortByOrderThenLabel(Object.values(record ?? {}), getLabel);
|
|
604
|
+
}
|
|
605
|
+
function spineNodeHasVisibleDescendant(bareId, allBareIds, spine, facetStates, ctx, organizationModel, cache2 = /* @__PURE__ */ new Map()) {
|
|
606
|
+
const cached = cache2.get(bareId);
|
|
607
|
+
if (cached !== void 0) return cached;
|
|
608
|
+
const graphNodeId = `${spine}:${bareId}`;
|
|
609
|
+
const hasSystemModelChildren = spine === "system" && [
|
|
610
|
+
...buildOntologySubgroup(bareId, organizationModel),
|
|
611
|
+
...buildSystemResourcesSubgroup(bareId, ctx),
|
|
612
|
+
...buildSystemConfigSubgroup(bareId, organizationModel),
|
|
613
|
+
...buildSystemGovernanceSubgroup(bareId, organizationModel)
|
|
614
|
+
].length > 0;
|
|
615
|
+
let result = hasSystemModelChildren || facetStates.knowledge !== "exclude" && (ctx.governsEdgesByTarget.get(graphNodeId)?.length ?? 0) > 0 || getIncludedFacetNodes(graphNodeId, spine, facetStates, ctx).length > 0 || childGraphIds(allBareIds, bareId).some(
|
|
616
|
+
(childId) => spineNodeHasVisibleDescendant(childId, allBareIds, spine, facetStates, ctx, organizationModel, cache2)
|
|
617
|
+
);
|
|
618
|
+
cache2.set(bareId, result);
|
|
619
|
+
return result;
|
|
620
|
+
}
|
|
621
|
+
function buildSpineMetaMap(graph, spine) {
|
|
622
|
+
const map = {};
|
|
623
|
+
for (const node of graph.nodes) {
|
|
624
|
+
if (node.kind === spine) {
|
|
625
|
+
map[toBareGraphId(node.id, spine)] = { label: node.label, icon: node.icon, node };
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return map;
|
|
629
|
+
}
|
|
630
|
+
function getKnowledgeDirectoryCommand(nodeIds, fallbackCommand) {
|
|
631
|
+
const command = getKnowledgeNodeReadCommands(nodeIds ?? []);
|
|
632
|
+
return command || fallbackCommand;
|
|
633
|
+
}
|
|
634
|
+
function getKnowledgeFolderKey(node) {
|
|
635
|
+
const key = `${node.id} ${node.title}`.toLowerCase();
|
|
636
|
+
if (/\b(stage|booking|discovery|pipeline|communications?)\b/.test(key)) return "pipeline";
|
|
637
|
+
if (/\b(upwork scanning|youtube|obs|recording|reddit|social)\b/.test(key)) return "channels";
|
|
638
|
+
if (/\b(testimonials?|case stud|proof)\b/.test(key)) return "proof";
|
|
639
|
+
if (/\b(target|personalization|vertical|calibration|query|research|strategy)\b/.test(key)) return "targeting";
|
|
640
|
+
if (/\b(outreach|campaign|copy|handoff|bounce|reply|lead-gen playbook)\b/.test(key)) return "campaigns";
|
|
641
|
+
if (node.kind === "reference") return "references";
|
|
642
|
+
if (node.kind === "strategy") return "strategies";
|
|
643
|
+
return "playbooks";
|
|
644
|
+
}
|
|
645
|
+
function sortFolderKeys(left, right) {
|
|
646
|
+
const leftIndex = FOLDER_ORDER.indexOf(left);
|
|
647
|
+
const rightIndex = FOLDER_ORDER.indexOf(right);
|
|
648
|
+
if (leftIndex === -1 && rightIndex === -1) return left.localeCompare(right);
|
|
649
|
+
if (leftIndex === -1) return 1;
|
|
650
|
+
if (rightIndex === -1) return -1;
|
|
651
|
+
return leftIndex - rightIndex;
|
|
652
|
+
}
|
|
653
|
+
function formatTreeLabel(value) {
|
|
654
|
+
const spaced = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[._/-]+/g, " ").trim();
|
|
655
|
+
if (!spaced) return value;
|
|
656
|
+
return spaced.split(/\s+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
657
|
+
}
|
|
658
|
+
function treeValueSegment(value) {
|
|
659
|
+
return value.replace(/[^A-Za-z0-9_.-]/g, "-");
|
|
660
|
+
}
|
|
661
|
+
function createKnowledgeLeaf(graphNodeId, node) {
|
|
662
|
+
return {
|
|
663
|
+
value: `${LEAF_PREFIX}${graphNodeId}::${node.id}`,
|
|
664
|
+
label: node.title,
|
|
665
|
+
nodeType: "leaf",
|
|
666
|
+
knowledgeNodeId: node.id,
|
|
667
|
+
knowledgeNodeIds: [node.id]
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function createKnowledgeLeaves(graphNodeId, nodes) {
|
|
671
|
+
if (nodes.length < GROUP_THRESHOLD) {
|
|
672
|
+
return nodes.map((node) => createKnowledgeLeaf(graphNodeId, node));
|
|
673
|
+
}
|
|
674
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
675
|
+
for (const node of nodes) {
|
|
676
|
+
const folderKey = getKnowledgeFolderKey(node);
|
|
677
|
+
const folderNodes = grouped.get(folderKey) ?? [];
|
|
678
|
+
folderNodes.push(node);
|
|
679
|
+
grouped.set(folderKey, folderNodes);
|
|
680
|
+
}
|
|
681
|
+
return [...grouped.entries()].sort(([left], [right]) => sortFolderKeys(left, right)).map(([folderKey, folderNodes]) => ({
|
|
682
|
+
value: `${FOLDER_PREFIX}${graphNodeId}::${folderKey}`,
|
|
683
|
+
label: FOLDER_LABELS[folderKey] ?? folderKey,
|
|
684
|
+
nodeType: "folder",
|
|
685
|
+
icon: "playbook",
|
|
686
|
+
knowledgeNodeIds: folderNodes.map((node) => node.id),
|
|
687
|
+
children: folderNodes.map((node) => createKnowledgeLeaf(graphNodeId, node))
|
|
688
|
+
}));
|
|
689
|
+
}
|
|
690
|
+
function collectKnowledgeNodeIds(node) {
|
|
691
|
+
if (node.knowledgeNodeIds) return node.knowledgeNodeIds;
|
|
692
|
+
return (node.children ?? []).flatMap(collectKnowledgeNodeIds);
|
|
693
|
+
}
|
|
694
|
+
function createItemNode({
|
|
695
|
+
domainKey,
|
|
696
|
+
itemId,
|
|
697
|
+
label,
|
|
698
|
+
graphNodeId,
|
|
699
|
+
knowledgeNodes = [],
|
|
700
|
+
children = []
|
|
701
|
+
}) {
|
|
702
|
+
const knowledgeLeaves = knowledgeNodes.length > 0 ? createKnowledgeLeaves(`${ITEM_PREFIX}${domainKey}:${itemId}`, knowledgeNodes) : [];
|
|
703
|
+
const allChildren = [...children, ...knowledgeLeaves];
|
|
704
|
+
return {
|
|
705
|
+
value: `${ITEM_PREFIX}${domainKey}:${itemId}`,
|
|
706
|
+
label,
|
|
707
|
+
nodeType: "item",
|
|
708
|
+
domainKey,
|
|
709
|
+
itemId,
|
|
710
|
+
graphNodeId,
|
|
711
|
+
knowledgeNodeIds: [...knowledgeNodes.map((node) => node.id), ...children.flatMap(collectKnowledgeNodeIds)],
|
|
712
|
+
children: allChildren.length > 0 ? allChildren : void 0
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
function createDomainNode({
|
|
716
|
+
domainKey,
|
|
717
|
+
label,
|
|
718
|
+
knowledgeNodes = [],
|
|
719
|
+
children = []
|
|
720
|
+
}) {
|
|
721
|
+
const knowledgeLeaves = knowledgeNodes.length > 0 ? createKnowledgeLeaves(`${DOMAIN_PREFIX}${domainKey}`, knowledgeNodes) : [];
|
|
722
|
+
const allChildren = [...children, ...knowledgeLeaves];
|
|
723
|
+
return {
|
|
724
|
+
value: `${DOMAIN_PREFIX}${domainKey}`,
|
|
725
|
+
label,
|
|
726
|
+
nodeType: "domain",
|
|
727
|
+
domainKey,
|
|
728
|
+
knowledgeNodeIds: [...knowledgeNodes.map((node) => node.id), ...children.flatMap(collectKnowledgeNodeIds)],
|
|
729
|
+
children: allChildren.length > 0 ? allChildren : void 0
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
function createGroupNode({
|
|
733
|
+
groupKey,
|
|
734
|
+
label,
|
|
735
|
+
children
|
|
736
|
+
}) {
|
|
737
|
+
return {
|
|
738
|
+
value: `${GROUP_PREFIX}${groupKey}`,
|
|
739
|
+
label,
|
|
740
|
+
nodeType: "group",
|
|
741
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
742
|
+
children: children.length > 0 ? children : void 0
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
function getIncludedFacetNodes(graphNodeId, spineKind, facetStates, ctx) {
|
|
746
|
+
const includedKinds = new Set(
|
|
747
|
+
Object.entries(facetStates).filter(([kind, state]) => state === "include" && kind !== "knowledge" && kind !== spineKind).map(([kind]) => kind)
|
|
748
|
+
);
|
|
749
|
+
if (includedKinds.size === 0) return [];
|
|
750
|
+
const seen = /* @__PURE__ */ new Set();
|
|
751
|
+
const nodes = [];
|
|
752
|
+
const outgoing = ctx.edgesBySource.get(graphNodeId) ?? [];
|
|
753
|
+
const incoming = ctx.edgesByTarget.get(graphNodeId) ?? [];
|
|
754
|
+
for (const edge of [...outgoing, ...incoming]) {
|
|
755
|
+
const relatedId = edge.sourceId === graphNodeId ? edge.targetId : edge.sourceId;
|
|
756
|
+
const relatedNode = ctx.nodesById.get(relatedId);
|
|
757
|
+
if (!relatedNode || !includedKinds.has(relatedNode.kind) || seen.has(relatedNode.id)) continue;
|
|
758
|
+
seen.add(relatedNode.id);
|
|
759
|
+
nodes.push(relatedNode);
|
|
760
|
+
}
|
|
761
|
+
return nodes.sort((left, right) => left.kind.localeCompare(right.kind) || left.label.localeCompare(right.label));
|
|
762
|
+
}
|
|
763
|
+
function createFacetGraphLeaves(nodes) {
|
|
764
|
+
return nodes.map((node) => ({
|
|
765
|
+
value: `graph:${node.id}`,
|
|
766
|
+
label: node.label,
|
|
767
|
+
nodeType: "graph",
|
|
768
|
+
icon: node.icon,
|
|
769
|
+
graphNodeId: node.id,
|
|
770
|
+
knowledgeNodeIds: []
|
|
771
|
+
}));
|
|
772
|
+
}
|
|
773
|
+
function createGraphNodeItem(node, domainKey) {
|
|
774
|
+
return createItemNode({
|
|
775
|
+
domainKey,
|
|
776
|
+
itemId: node.sourceId ?? node.id,
|
|
777
|
+
label: node.label,
|
|
778
|
+
graphNodeId: node.id
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
function createCollectionNode(parentKey, collectionKey, label, children) {
|
|
782
|
+
return {
|
|
783
|
+
value: `${FOLDER_PREFIX}${parentKey}:${collectionKey}`,
|
|
784
|
+
label,
|
|
785
|
+
nodeType: "folder",
|
|
786
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
787
|
+
children: children.length > 0 ? children : void 0
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
function buildOntologySubgroup(bareId, organizationModel) {
|
|
791
|
+
if (!organizationModel) return [];
|
|
792
|
+
const projection = getKnowledgeOntologyProjection(organizationModel);
|
|
793
|
+
const domainKeys = [...CORE_ONTOLOGY_DOMAIN_KEYS, ...OPTIONAL_ONTOLOGY_DOMAIN_KEYS];
|
|
794
|
+
const domainFolders = domainKeys.map((domainKey) => {
|
|
795
|
+
const items = getPrimaryOntologyItemsForDomain(projection, domainKey).filter(
|
|
796
|
+
(item) => item.ownerSystemId === bareId
|
|
797
|
+
);
|
|
798
|
+
if (items.length === 0) return void 0;
|
|
799
|
+
return {
|
|
800
|
+
value: `${FOLDER_PREFIX}ontology:${bareId}:${domainKey}`,
|
|
801
|
+
label: getOntologyDomainLabel(domainKey),
|
|
802
|
+
nodeType: "folder",
|
|
803
|
+
knowledgeNodeIds: [],
|
|
804
|
+
children: items.map(
|
|
805
|
+
(item) => createItemNode({
|
|
806
|
+
domainKey,
|
|
807
|
+
itemId: item.id,
|
|
808
|
+
label: item.label,
|
|
809
|
+
graphNodeId: item.kind === "resource" ? `resource:${item.id}` : `ontology:${item.id}`
|
|
810
|
+
})
|
|
811
|
+
)
|
|
812
|
+
};
|
|
813
|
+
}).filter((node) => node !== void 0);
|
|
814
|
+
if (domainFolders.length === 0) return [];
|
|
815
|
+
return [
|
|
816
|
+
{
|
|
817
|
+
value: `${FOLDER_PREFIX}ontology:${bareId}`,
|
|
818
|
+
label: "Ontology",
|
|
819
|
+
nodeType: "folder",
|
|
820
|
+
knowledgeNodeIds: [],
|
|
821
|
+
children: domainFolders
|
|
822
|
+
}
|
|
823
|
+
];
|
|
824
|
+
}
|
|
825
|
+
function buildSystemResourcesSubgroup(bareId, ctx) {
|
|
826
|
+
const graphNodeId = `system:${bareId}`;
|
|
827
|
+
const resourceNodes = (ctx.edgesBySource.get(graphNodeId) ?? []).filter((edge) => edge.kind === "contains").map((edge) => ctx.nodesById.get(edge.targetId)).filter((node) => node?.kind === "resource").sort((left, right) => left.label.localeCompare(right.label) || left.id.localeCompare(right.id));
|
|
828
|
+
if (resourceNodes.length === 0) return [];
|
|
829
|
+
const children = GRAPH_RESOURCE_TYPE_ORDER.map((resourceType) => {
|
|
830
|
+
const typedResources = resourceNodes.filter((node) => node.resourceType === resourceType);
|
|
831
|
+
if (typedResources.length === 0) return void 0;
|
|
832
|
+
return createCollectionNode(
|
|
833
|
+
`system:${bareId}:resources`,
|
|
834
|
+
resourceType,
|
|
835
|
+
GRAPH_RESOURCE_TYPE_LABELS[resourceType],
|
|
836
|
+
typedResources.map((node) => createGraphNodeItem(node, "resources"))
|
|
837
|
+
);
|
|
838
|
+
}).filter((node) => node !== void 0);
|
|
839
|
+
const unclassifiedResources = resourceNodes.filter((node) => node.resourceType === void 0);
|
|
840
|
+
if (unclassifiedResources.length > 0) {
|
|
841
|
+
children.push(
|
|
842
|
+
createCollectionNode(
|
|
843
|
+
`system:${bareId}:resources`,
|
|
844
|
+
"unknown",
|
|
845
|
+
"Unclassified",
|
|
846
|
+
unclassifiedResources.map((node) => createGraphNodeItem(node, "resources"))
|
|
847
|
+
)
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
return [
|
|
851
|
+
{
|
|
852
|
+
value: `${FOLDER_PREFIX}resources:${bareId}`,
|
|
853
|
+
label: "Resources",
|
|
854
|
+
nodeType: "folder",
|
|
855
|
+
icon: "workflow",
|
|
856
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
857
|
+
children
|
|
858
|
+
}
|
|
859
|
+
];
|
|
860
|
+
}
|
|
861
|
+
function buildSystemConfigSubgroup(bareId, organizationModel) {
|
|
862
|
+
if (!organizationModel) return [];
|
|
863
|
+
const system = getSystem(organizationModel, bareId);
|
|
864
|
+
if (!system) return [];
|
|
865
|
+
const config = resolveSystemConfig(organizationModel, bareId);
|
|
866
|
+
const configKeys = Object.keys(config).sort((left, right) => left.localeCompare(right));
|
|
867
|
+
const children = [];
|
|
868
|
+
if (configKeys.length > 0) {
|
|
869
|
+
children.push({
|
|
870
|
+
value: `${FOLDER_PREFIX}config:${bareId}:defaults`,
|
|
871
|
+
label: "Defaults",
|
|
872
|
+
nodeType: "folder",
|
|
873
|
+
icon: "settings",
|
|
874
|
+
knowledgeNodeIds: [],
|
|
875
|
+
children: configKeys.map((key) => ({
|
|
876
|
+
value: `${FOLDER_PREFIX}config:${bareId}:defaults:${treeValueSegment(key)}`,
|
|
877
|
+
label: formatTreeLabel(key),
|
|
878
|
+
nodeType: "folder",
|
|
879
|
+
knowledgeNodeIds: []
|
|
880
|
+
}))
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
const hasUiConfig = system.ui !== void 0 || system.path !== void 0 || system.icon !== void 0 || system.uiPosition !== void 0 || system.enabled !== void 0 || system.devOnly !== void 0 || system.requiresAdmin !== void 0;
|
|
884
|
+
if (hasUiConfig) {
|
|
885
|
+
const uiChildren = [];
|
|
886
|
+
if (system.ui?.path !== void 0 || system.path !== void 0) {
|
|
887
|
+
uiChildren.push({
|
|
888
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui:path`,
|
|
889
|
+
label: "Path",
|
|
890
|
+
nodeType: "folder",
|
|
891
|
+
knowledgeNodeIds: []
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
if ((system.ui?.surfaces.length ?? 0) > 0) {
|
|
895
|
+
uiChildren.push({
|
|
896
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui:surfaces`,
|
|
897
|
+
label: "Surfaces",
|
|
898
|
+
nodeType: "folder",
|
|
899
|
+
knowledgeNodeIds: []
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
if (system.ui?.icon !== void 0 || system.icon !== void 0) {
|
|
903
|
+
uiChildren.push({
|
|
904
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui:icon`,
|
|
905
|
+
label: "Icon",
|
|
906
|
+
nodeType: "folder",
|
|
907
|
+
knowledgeNodeIds: []
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
if (system.uiPosition !== void 0) {
|
|
911
|
+
uiChildren.push({
|
|
912
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui:placement`,
|
|
913
|
+
label: "Placement",
|
|
914
|
+
nodeType: "folder",
|
|
915
|
+
knowledgeNodeIds: []
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
if (system.enabled !== void 0 || system.devOnly !== void 0 || system.requiresAdmin !== void 0) {
|
|
919
|
+
uiChildren.push({
|
|
920
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui:access`,
|
|
921
|
+
label: "Access",
|
|
922
|
+
nodeType: "folder",
|
|
923
|
+
knowledgeNodeIds: []
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
children.push({
|
|
927
|
+
value: `${FOLDER_PREFIX}config:${bareId}:ui`,
|
|
928
|
+
label: "UI",
|
|
929
|
+
nodeType: "folder",
|
|
930
|
+
icon: "view",
|
|
931
|
+
knowledgeNodeIds: [],
|
|
932
|
+
children: uiChildren.length > 0 ? uiChildren : void 0
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
if (children.length === 0) return [];
|
|
936
|
+
return [
|
|
937
|
+
{
|
|
938
|
+
value: `${FOLDER_PREFIX}config:${bareId}`,
|
|
939
|
+
label: "Config",
|
|
940
|
+
nodeType: "folder",
|
|
941
|
+
icon: "settings",
|
|
942
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
943
|
+
children
|
|
944
|
+
}
|
|
945
|
+
];
|
|
946
|
+
}
|
|
947
|
+
function buildSystemKnowledgeSubgroup(graphNodeId, governing) {
|
|
948
|
+
if (governing.length === 0) return [];
|
|
949
|
+
const children = createKnowledgeLeaves(graphNodeId, governing);
|
|
950
|
+
return [
|
|
951
|
+
{
|
|
952
|
+
value: `${FOLDER_PREFIX}knowledge:${graphNodeId}`,
|
|
953
|
+
label: "Knowledge",
|
|
954
|
+
nodeType: "folder",
|
|
955
|
+
icon: "reference",
|
|
956
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
957
|
+
children
|
|
958
|
+
}
|
|
959
|
+
];
|
|
960
|
+
}
|
|
961
|
+
function buildSystemGovernanceSubgroup(bareId, organizationModel) {
|
|
962
|
+
if (!organizationModel) return [];
|
|
963
|
+
const system = getSystem(organizationModel, bareId);
|
|
964
|
+
if (!system) return [];
|
|
965
|
+
const roleIds = /* @__PURE__ */ new Set();
|
|
966
|
+
if (system.responsibleRoleId !== void 0) roleIds.add(system.responsibleRoleId);
|
|
967
|
+
for (const role of Object.values(organizationModel.roles ?? {})) {
|
|
968
|
+
if (role.responsibleFor?.includes(bareId)) roleIds.add(role.id);
|
|
969
|
+
}
|
|
970
|
+
const policyIds = new Set(system.policies ?? []);
|
|
971
|
+
for (const policy of Object.values(organizationModel.policies ?? {})) {
|
|
972
|
+
if (policy.appliesTo.systemIds.includes(bareId)) policyIds.add(policy.id);
|
|
973
|
+
}
|
|
974
|
+
const roles = Object.values(organizationModel.roles ?? {}).filter((role) => roleIds.has(role.id)).sort((left, right) => (left.order ?? 0) - (right.order ?? 0) || left.title.localeCompare(right.title));
|
|
975
|
+
const policies = Object.values(organizationModel.policies ?? {}).filter((policy) => policyIds.has(policy.id)).sort((left, right) => (left.order ?? 0) - (right.order ?? 0) || left.label.localeCompare(right.label));
|
|
976
|
+
const children = [];
|
|
977
|
+
if (roles.length > 0) {
|
|
978
|
+
children.push(
|
|
979
|
+
createCollectionNode(
|
|
980
|
+
`governance:${bareId}`,
|
|
981
|
+
"roles",
|
|
982
|
+
roles.length === 1 ? "Responsible Role" : "Responsible Roles",
|
|
983
|
+
roles.map(
|
|
984
|
+
(role) => createItemNode({
|
|
985
|
+
domainKey: "roles",
|
|
986
|
+
itemId: role.id,
|
|
987
|
+
label: role.title,
|
|
988
|
+
graphNodeId: `role:${role.id}`
|
|
989
|
+
})
|
|
990
|
+
)
|
|
991
|
+
)
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
if (policies.length > 0) {
|
|
995
|
+
children.push(
|
|
996
|
+
createCollectionNode(
|
|
997
|
+
`governance:${bareId}`,
|
|
998
|
+
"policies",
|
|
999
|
+
"Policies",
|
|
1000
|
+
policies.map(
|
|
1001
|
+
(policy) => createItemNode({
|
|
1002
|
+
domainKey: "policies",
|
|
1003
|
+
itemId: policy.id,
|
|
1004
|
+
label: policy.label,
|
|
1005
|
+
graphNodeId: `policy:${policy.id}`
|
|
1006
|
+
})
|
|
1007
|
+
)
|
|
1008
|
+
)
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
if (children.length === 0) return [];
|
|
1012
|
+
return [
|
|
1013
|
+
{
|
|
1014
|
+
value: `${FOLDER_PREFIX}governance:${bareId}`,
|
|
1015
|
+
label: "Governance",
|
|
1016
|
+
nodeType: "folder",
|
|
1017
|
+
icon: "shield",
|
|
1018
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
1019
|
+
children
|
|
1020
|
+
}
|
|
1021
|
+
];
|
|
1022
|
+
}
|
|
1023
|
+
function buildSpineTreeNode(bareId, allBareIds, spineMetaMap, spine, facetStates, ctx, visibleSpineIds, organizationModel) {
|
|
1024
|
+
const graphNodeId = `${spine}:${bareId}`;
|
|
1025
|
+
const governing = facetStates.knowledge === "exclude" ? [] : ctx.governsEdgesByTarget.get(graphNodeId) ?? [];
|
|
1026
|
+
const childIds = childGraphIds(allBareIds, bareId);
|
|
1027
|
+
const systemModelChildren = spine === "system" ? [
|
|
1028
|
+
...buildOntologySubgroup(bareId, organizationModel),
|
|
1029
|
+
...buildSystemResourcesSubgroup(bareId, ctx),
|
|
1030
|
+
...buildSystemConfigSubgroup(bareId, organizationModel),
|
|
1031
|
+
...buildSystemKnowledgeSubgroup(graphNodeId, governing),
|
|
1032
|
+
...buildSystemGovernanceSubgroup(bareId, organizationModel)
|
|
1033
|
+
] : [];
|
|
1034
|
+
const childSpineNodes = childIds.filter((childId) => visibleSpineIds.has(childId)).map(
|
|
1035
|
+
(childId) => buildSpineTreeNode(childId, allBareIds, spineMetaMap, spine, facetStates, ctx, visibleSpineIds, organizationModel)
|
|
1036
|
+
);
|
|
1037
|
+
const knowledgeLeaves = spine === "system" ? [] : createKnowledgeLeaves(graphNodeId, governing);
|
|
1038
|
+
const facetLeaves = createFacetGraphLeaves(getIncludedFacetNodes(graphNodeId, spine, facetStates, ctx));
|
|
1039
|
+
const children = [...systemModelChildren, ...childSpineNodes, ...knowledgeLeaves, ...facetLeaves];
|
|
1040
|
+
const meta = spineMetaMap[bareId];
|
|
1041
|
+
return {
|
|
1042
|
+
value: `${SPINE_PREFIX}${spine}:${bareId}`,
|
|
1043
|
+
label: meta?.label ?? bareId,
|
|
1044
|
+
nodeType: "spine",
|
|
1045
|
+
icon: meta?.icon,
|
|
1046
|
+
graphNodeId,
|
|
1047
|
+
knowledgeNodeIds: children.flatMap(collectKnowledgeNodeIds),
|
|
1048
|
+
children: children.length > 0 ? children : void 0
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
function getInitialExpandedState(nodes, omRooted) {
|
|
1052
|
+
if (!omRooted) return {};
|
|
1053
|
+
const systemsValue = `${GROUP_PREFIX}systems`;
|
|
1054
|
+
const quickAccessValue = `${GROUP_PREFIX}${QUICK_ACCESS_GROUP_KEY}`;
|
|
1055
|
+
const expanded = {};
|
|
1056
|
+
for (const node of nodes) {
|
|
1057
|
+
if (node.value === systemsValue) expanded[systemsValue] = true;
|
|
1058
|
+
if (node.value === quickAccessValue) expanded[quickAccessValue] = true;
|
|
1059
|
+
}
|
|
1060
|
+
return expanded;
|
|
1061
|
+
}
|
|
1062
|
+
function buildProfileGroup(organizationModel, knowledgeByTarget, facetStates) {
|
|
1063
|
+
return createGroupNode({
|
|
1064
|
+
groupKey: "profile",
|
|
1065
|
+
label: "Profile",
|
|
1066
|
+
children: [
|
|
1067
|
+
createDomainNode({
|
|
1068
|
+
domainKey: "identity",
|
|
1069
|
+
label: "Identity",
|
|
1070
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, "identity", facetStates)
|
|
1071
|
+
}),
|
|
1072
|
+
createDomainNode({
|
|
1073
|
+
domainKey: "branding",
|
|
1074
|
+
label: "Branding",
|
|
1075
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, "branding", facetStates)
|
|
1076
|
+
})
|
|
1077
|
+
]
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
function buildBusinessModelGroup(organizationModel, knowledgeByTarget, facetStates) {
|
|
1081
|
+
return createGroupNode({
|
|
1082
|
+
groupKey: "business-model",
|
|
1083
|
+
label: "Business Model",
|
|
1084
|
+
children: [
|
|
1085
|
+
createDomainNode({
|
|
1086
|
+
domainKey: "customers",
|
|
1087
|
+
label: "Customers",
|
|
1088
|
+
children: modelRecordValues(organizationModel?.customers, (segment) => segment.name || segment.id).map(
|
|
1089
|
+
(segment) => createItemNode({
|
|
1090
|
+
domainKey: "customers",
|
|
1091
|
+
itemId: segment.id,
|
|
1092
|
+
label: segment.name || segment.id,
|
|
1093
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `customers:${segment.id}`, facetStates)
|
|
1094
|
+
})
|
|
1095
|
+
)
|
|
1096
|
+
}),
|
|
1097
|
+
createDomainNode({
|
|
1098
|
+
domainKey: "offerings",
|
|
1099
|
+
label: "Offerings",
|
|
1100
|
+
children: modelRecordValues(organizationModel?.offerings, (offering) => offering.name || offering.id).map(
|
|
1101
|
+
(offering) => createItemNode({
|
|
1102
|
+
domainKey: "offerings",
|
|
1103
|
+
itemId: offering.id,
|
|
1104
|
+
label: offering.name || offering.id,
|
|
1105
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `offerings:${offering.id}`, facetStates)
|
|
1106
|
+
})
|
|
1107
|
+
)
|
|
1108
|
+
}),
|
|
1109
|
+
createDomainNode({
|
|
1110
|
+
domainKey: "goals",
|
|
1111
|
+
label: "Goals",
|
|
1112
|
+
children: modelRecordValues(organizationModel?.goals, (goal) => goal.description || goal.id).map(
|
|
1113
|
+
(goal) => createItemNode({
|
|
1114
|
+
domainKey: "goals",
|
|
1115
|
+
itemId: goal.id,
|
|
1116
|
+
label: goal.description || goal.id,
|
|
1117
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `goals:${goal.id}`, facetStates)
|
|
1118
|
+
})
|
|
1119
|
+
)
|
|
1120
|
+
})
|
|
1121
|
+
]
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
function buildRolesDomain(graph, organizationModel, knowledgeByTarget, facetStates) {
|
|
1125
|
+
const graphNodesById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
1126
|
+
const roleItems = modelRecordValues(organizationModel?.roles, (role) => role.title || role.id).map(
|
|
1127
|
+
(role) => createItemNode({
|
|
1128
|
+
domainKey: "roles",
|
|
1129
|
+
itemId: role.id,
|
|
1130
|
+
label: role.title || role.id,
|
|
1131
|
+
graphNodeId: graphNodesById.get(`role:${role.id}`)?.id,
|
|
1132
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `role:${role.id}`, facetStates)
|
|
1133
|
+
})
|
|
1134
|
+
);
|
|
1135
|
+
return createDomainNode({ domainKey: "roles", label: "Roles", children: roleItems });
|
|
1136
|
+
}
|
|
1137
|
+
function buildSystemsGroup(graph, organizationModel, facetStates, ctx, visibleSpineIds) {
|
|
1138
|
+
const spineMetaMap = buildSpineMetaMap(graph, "system");
|
|
1139
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
1140
|
+
const topIds = topLevelGraphIds(allBareIds);
|
|
1141
|
+
const children = topIds.filter((bareId) => visibleSpineIds.has(bareId)).map(
|
|
1142
|
+
(bareId) => buildSpineTreeNode(
|
|
1143
|
+
bareId,
|
|
1144
|
+
allBareIds,
|
|
1145
|
+
spineMetaMap,
|
|
1146
|
+
"system",
|
|
1147
|
+
facetStates,
|
|
1148
|
+
ctx,
|
|
1149
|
+
visibleSpineIds,
|
|
1150
|
+
organizationModel
|
|
1151
|
+
)
|
|
1152
|
+
);
|
|
1153
|
+
return createGroupNode({ groupKey: "systems", label: "Systems", children });
|
|
1154
|
+
}
|
|
1155
|
+
function buildOntologyBranch(organizationModel, domainKey) {
|
|
1156
|
+
if (!organizationModel) return void 0;
|
|
1157
|
+
const projection = getKnowledgeOntologyProjection(organizationModel);
|
|
1158
|
+
const items = getPrimaryOntologyItemsForDomain(projection, domainKey);
|
|
1159
|
+
if (items.length === 0) return void 0;
|
|
1160
|
+
return createDomainNode({
|
|
1161
|
+
domainKey,
|
|
1162
|
+
label: getOntologyDomainLabel(domainKey),
|
|
1163
|
+
children: items.map(
|
|
1164
|
+
(item) => createItemNode({
|
|
1165
|
+
domainKey,
|
|
1166
|
+
itemId: item.id,
|
|
1167
|
+
label: item.label,
|
|
1168
|
+
children: [
|
|
1169
|
+
{
|
|
1170
|
+
value: `${FOLDER_PREFIX}${domainKey}:${item.id}:owner`,
|
|
1171
|
+
label: item.ownerSystemId ?? "global",
|
|
1172
|
+
nodeType: "folder",
|
|
1173
|
+
icon: item.kind === "resource" ? "workflow" : "info",
|
|
1174
|
+
knowledgeNodeIds: []
|
|
1175
|
+
}
|
|
1176
|
+
]
|
|
1177
|
+
})
|
|
1178
|
+
)
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function buildGraphGroup(organizationModel) {
|
|
1182
|
+
const ontologyDomains = [...CORE_ONTOLOGY_DOMAIN_KEYS, ...OPTIONAL_ONTOLOGY_DOMAIN_KEYS].map((domainKey) => buildOntologyBranch(organizationModel, domainKey)).filter((node) => node !== void 0);
|
|
1183
|
+
return createGroupNode({
|
|
1184
|
+
groupKey: "graph",
|
|
1185
|
+
label: "Ontology",
|
|
1186
|
+
children: ontologyDomains
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
function buildResourcesGroup(graph) {
|
|
1190
|
+
const resourceNodes = graph.nodes.filter((node) => node.kind === "resource").sort(
|
|
1191
|
+
(left, right) => (left.resourceType ?? "").localeCompare(right.resourceType ?? "") || left.label.localeCompare(right.label) || left.id.localeCompare(right.id)
|
|
1192
|
+
);
|
|
1193
|
+
const children = GRAPH_RESOURCE_TYPE_ORDER.map((resourceType) => {
|
|
1194
|
+
const typedResources = resourceNodes.filter((node) => node.resourceType === resourceType);
|
|
1195
|
+
if (typedResources.length === 0) return void 0;
|
|
1196
|
+
return createCollectionNode(
|
|
1197
|
+
"resources",
|
|
1198
|
+
resourceType,
|
|
1199
|
+
GRAPH_RESOURCE_TYPE_LABELS[resourceType],
|
|
1200
|
+
typedResources.map((node) => createGraphNodeItem(node, "resources"))
|
|
1201
|
+
);
|
|
1202
|
+
}).filter((node) => node !== void 0);
|
|
1203
|
+
const orderedTypes = new Set(GRAPH_RESOURCE_TYPE_ORDER);
|
|
1204
|
+
const otherResources = resourceNodes.filter(
|
|
1205
|
+
(node) => node.resourceType === void 0 || !orderedTypes.has(node.resourceType)
|
|
1206
|
+
);
|
|
1207
|
+
if (otherResources.length > 0) {
|
|
1208
|
+
children.push(
|
|
1209
|
+
createCollectionNode(
|
|
1210
|
+
"resources",
|
|
1211
|
+
"other",
|
|
1212
|
+
"Other",
|
|
1213
|
+
otherResources.map((node) => createGraphNodeItem(node, "resources"))
|
|
1214
|
+
)
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
return createGroupNode({
|
|
1218
|
+
groupKey: "resources",
|
|
1219
|
+
label: "Resources",
|
|
1220
|
+
children
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
function formatOntologyKnowledgeTargetLabel(targetId, organizationModel) {
|
|
1224
|
+
if (organizationModel) {
|
|
1225
|
+
const projection = getKnowledgeOntologyProjection(organizationModel);
|
|
1226
|
+
for (const domainKey of [...CORE_ONTOLOGY_DOMAIN_KEYS, ...OPTIONAL_ONTOLOGY_DOMAIN_KEYS]) {
|
|
1227
|
+
const item = getPrimaryOntologyItemsForDomain(projection, domainKey).find((candidate) => candidate.id === targetId);
|
|
1228
|
+
if (item) return item.label;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return formatTreeLabel(targetId.includes("/") ? targetId.slice(targetId.lastIndexOf("/") + 1) : targetId);
|
|
1232
|
+
}
|
|
1233
|
+
function createKnowledgeCollection(parentKey, collectionKey, label, nodes) {
|
|
1234
|
+
return createCollectionNode(parentKey, collectionKey, label, createKnowledgeLeaves(`knowledge:${collectionKey}`, nodes));
|
|
1235
|
+
}
|
|
1236
|
+
function buildKnowledgeTargetCollections(knowledgeNodes, targetKind, parentKey, collectionLabel, formatTargetLabel) {
|
|
1237
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
1238
|
+
for (const node of knowledgeNodes) {
|
|
1239
|
+
for (const link of node.links) {
|
|
1240
|
+
if (link.target.kind !== targetKind) continue;
|
|
1241
|
+
const bucket = grouped.get(link.target.id) ?? [];
|
|
1242
|
+
bucket.push(node);
|
|
1243
|
+
grouped.set(link.target.id, bucket);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
const children = [...grouped.entries()].sort(([left], [right]) => formatTargetLabel(left).localeCompare(formatTargetLabel(right))).map(
|
|
1247
|
+
([targetId, nodes]) => createCollectionNode(
|
|
1248
|
+
`${parentKey}:${collectionKeyForTarget(targetKind)}`,
|
|
1249
|
+
treeValueSegment(targetId),
|
|
1250
|
+
formatTargetLabel(targetId),
|
|
1251
|
+
uniqueKnowledgeNodes(nodes).map((node) => createKnowledgeLeaf(`knowledge:${targetKind}:${targetId}`, node))
|
|
1252
|
+
)
|
|
1253
|
+
);
|
|
1254
|
+
if (children.length === 0) return void 0;
|
|
1255
|
+
return createCollectionNode(parentKey, collectionKeyForTarget(targetKind), collectionLabel, children);
|
|
1256
|
+
}
|
|
1257
|
+
function collectionKeyForTarget(targetKind) {
|
|
1258
|
+
return targetKind === "system" ? "by-system" : "by-ontology";
|
|
1259
|
+
}
|
|
1260
|
+
function buildKnowledgeGroup(graph, knowledgeNodes, organizationModel) {
|
|
1261
|
+
const systemLabels = new Map(
|
|
1262
|
+
graph.nodes.filter((node) => node.kind === "system").map((node) => [node.sourceId ?? node.id.replace(/^system:/, ""), node.label])
|
|
1263
|
+
);
|
|
1264
|
+
const sortedKnowledgeNodes = uniqueKnowledgeNodes(knowledgeNodes);
|
|
1265
|
+
const startHereNodes = sortedKnowledgeNodes.filter((node) => KNOWLEDGE_START_HERE_IDS.includes(node.id));
|
|
1266
|
+
const startHereIds = new Set(startHereNodes.map((node) => node.id));
|
|
1267
|
+
const allNodes = sortedKnowledgeNodes.filter((node) => !startHereIds.has(node.id));
|
|
1268
|
+
const children = [];
|
|
1269
|
+
if (startHereNodes.length > 0) {
|
|
1270
|
+
children.push(createKnowledgeCollection("knowledge", "start-here", "Start Here", startHereNodes));
|
|
1271
|
+
}
|
|
1272
|
+
if (allNodes.length > 0) {
|
|
1273
|
+
children.push(createKnowledgeCollection("knowledge", "all", "All", allNodes));
|
|
1274
|
+
}
|
|
1275
|
+
const bySystem = buildKnowledgeTargetCollections(
|
|
1276
|
+
sortedKnowledgeNodes,
|
|
1277
|
+
"system",
|
|
1278
|
+
"knowledge",
|
|
1279
|
+
"By System",
|
|
1280
|
+
(targetId) => systemLabels.get(targetId) ?? formatTreeLabel(targetId)
|
|
1281
|
+
);
|
|
1282
|
+
if (bySystem) children.push(bySystem);
|
|
1283
|
+
const byOntology = buildKnowledgeTargetCollections(
|
|
1284
|
+
sortedKnowledgeNodes,
|
|
1285
|
+
"ontology",
|
|
1286
|
+
"knowledge",
|
|
1287
|
+
"By Ontology",
|
|
1288
|
+
(targetId) => formatOntologyKnowledgeTargetLabel(targetId, organizationModel)
|
|
1289
|
+
);
|
|
1290
|
+
if (byOntology) children.push(byOntology);
|
|
1291
|
+
return createGroupNode({
|
|
1292
|
+
groupKey: "knowledge",
|
|
1293
|
+
label: "Knowledge",
|
|
1294
|
+
children
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
function buildNavigationGroup(organizationModel) {
|
|
1298
|
+
const navigationSurfaces = (organizationModel ? projectNavigationSurfaces(organizationModel) : []).sort((left, right) => left.label.localeCompare(right.label)).map(
|
|
1299
|
+
(surface) => createItemNode({
|
|
1300
|
+
domainKey: "navigation",
|
|
1301
|
+
itemId: surface.id,
|
|
1302
|
+
label: surface.label
|
|
1303
|
+
})
|
|
1304
|
+
);
|
|
1305
|
+
return createGroupNode({
|
|
1306
|
+
groupKey: "navigation",
|
|
1307
|
+
label: "Navigation",
|
|
1308
|
+
children: [createDomainNode({ domainKey: "navigation", label: "Surfaces", children: navigationSurfaces })]
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
function buildGovernanceGroup(graph, organizationModel, knowledgeByTarget, facetStates) {
|
|
1312
|
+
const graphNodesById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
1313
|
+
const policies = modelRecordValues(organizationModel?.policies, (policy) => policy.label || policy.id).map(
|
|
1314
|
+
(policy) => createItemNode({
|
|
1315
|
+
domainKey: "policies",
|
|
1316
|
+
itemId: policy.id,
|
|
1317
|
+
label: policy.label || policy.id,
|
|
1318
|
+
graphNodeId: graphNodesById.get(`policy:${policy.id}`)?.id,
|
|
1319
|
+
knowledgeNodes: getTargetKnowledge(knowledgeByTarget, `policy:${policy.id}`, facetStates)
|
|
1320
|
+
})
|
|
1321
|
+
);
|
|
1322
|
+
const rolesDomain = buildRolesDomain(graph, organizationModel, knowledgeByTarget, facetStates);
|
|
1323
|
+
return createGroupNode({
|
|
1324
|
+
groupKey: "governance-wiring",
|
|
1325
|
+
label: "Governance",
|
|
1326
|
+
children: [
|
|
1327
|
+
rolesDomain,
|
|
1328
|
+
createDomainNode({ domainKey: "policies", label: "Policies", children: policies })
|
|
1329
|
+
]
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
function computeVisibleSpineIds(allBareIds, spine, facetStates, ctx, organizationModel) {
|
|
1333
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
1334
|
+
const visible = /* @__PURE__ */ new Set();
|
|
1335
|
+
for (const bareId of allBareIds) {
|
|
1336
|
+
if (spineNodeHasVisibleDescendant(bareId, allBareIds, spine, facetStates, ctx, organizationModel, cache2)) {
|
|
1337
|
+
visible.add(bareId);
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
return visible;
|
|
1341
|
+
}
|
|
1342
|
+
function buildOrgTreeNode(graph, knowledgeNodes, facetStates, organizationModel, favorites = []) {
|
|
1343
|
+
const ctx = buildTreeContext(graph, knowledgeNodes);
|
|
1344
|
+
const knowledgeByTarget = getKnowledgeByTarget(knowledgeNodes);
|
|
1345
|
+
const spineMetaMap = buildSpineMetaMap(graph, "system");
|
|
1346
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
1347
|
+
const visibleSpineIds = computeVisibleSpineIds(allBareIds, "system", facetStates, ctx, organizationModel);
|
|
1348
|
+
const omGroups = OM_TREE_GROUPS.map((group) => {
|
|
1349
|
+
switch (group.key) {
|
|
1350
|
+
case "profile":
|
|
1351
|
+
return buildProfileGroup(organizationModel, knowledgeByTarget, facetStates);
|
|
1352
|
+
case "business-model":
|
|
1353
|
+
return buildBusinessModelGroup(organizationModel, knowledgeByTarget, facetStates);
|
|
1354
|
+
case "systems":
|
|
1355
|
+
return buildSystemsGroup(graph, organizationModel, facetStates, ctx, visibleSpineIds);
|
|
1356
|
+
case "graph":
|
|
1357
|
+
return buildGraphGroup(organizationModel);
|
|
1358
|
+
case "resources":
|
|
1359
|
+
return buildResourcesGroup(graph);
|
|
1360
|
+
case "knowledge":
|
|
1361
|
+
return buildKnowledgeGroup(graph, knowledgeNodes, organizationModel);
|
|
1362
|
+
case "navigation":
|
|
1363
|
+
return buildNavigationGroup(organizationModel);
|
|
1364
|
+
case "governance-wiring":
|
|
1365
|
+
return buildGovernanceGroup(graph, organizationModel, knowledgeByTarget, facetStates);
|
|
1366
|
+
default:
|
|
1367
|
+
return createGroupNode({ groupKey: group.key, label: group.label, children: [] });
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
const quickAccess = buildQuickAccessGroup(favorites, knowledgeNodes, graph);
|
|
1371
|
+
return [quickAccess, ...omGroups];
|
|
1372
|
+
}
|
|
1373
|
+
function buildQuickAccessGroup(favorites, knowledgeNodes, graph) {
|
|
1374
|
+
const knowledgeIds = new Set(knowledgeNodes.map((node) => node.id));
|
|
1375
|
+
const graphIds = new Set(graph.nodes.map((node) => node.id));
|
|
1376
|
+
const children = favorites.filter((favorite) => {
|
|
1377
|
+
if (favorite.kind === "knowledge") return knowledgeIds.has(favorite.routeId);
|
|
1378
|
+
if (favorite.kind === "graph") return graphIds.has(favorite.routeId);
|
|
1379
|
+
return true;
|
|
1380
|
+
}).map((favorite) => ({
|
|
1381
|
+
value: `${FAVORITE_PREFIX}${favorite.routeId}`,
|
|
1382
|
+
label: favorite.label,
|
|
1383
|
+
nodeType: "favorite",
|
|
1384
|
+
icon: favorite.iconToken,
|
|
1385
|
+
favoriteRouteId: favorite.routeId,
|
|
1386
|
+
favoriteKind: favorite.kind,
|
|
1387
|
+
knowledgeNodeIds: []
|
|
1388
|
+
}));
|
|
1389
|
+
return {
|
|
1390
|
+
value: `${GROUP_PREFIX}${QUICK_ACCESS_GROUP_KEY}`,
|
|
1391
|
+
label: "Quick Access",
|
|
1392
|
+
nodeType: "group",
|
|
1393
|
+
knowledgeNodeIds: [],
|
|
1394
|
+
children
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
function KnowledgeTree({
|
|
1398
|
+
graph,
|
|
1399
|
+
knowledgeNodes,
|
|
1400
|
+
organizationModel,
|
|
1401
|
+
onSelectNode,
|
|
1402
|
+
onSelectGraphNode,
|
|
1403
|
+
onSelectDomain,
|
|
1404
|
+
onSelectGroup,
|
|
1405
|
+
onSelectItem,
|
|
1406
|
+
spine = "system",
|
|
1407
|
+
omRooted = false,
|
|
1408
|
+
facetStates = DEFAULT_KNOWLEDGE_FACET_STATES,
|
|
1409
|
+
selectedNodeId
|
|
1410
|
+
}) {
|
|
1411
|
+
const graphSpine = spine;
|
|
1412
|
+
const favoritesMap = useKnowledgeFavoritesStore((state) => state.favorites);
|
|
1413
|
+
const favorites = useMemo(
|
|
1414
|
+
() => Object.values(favoritesMap).sort((left, right) => right.addedAt - left.addedAt),
|
|
1415
|
+
[favoritesMap]
|
|
1416
|
+
);
|
|
1417
|
+
const treeData = useMemo(() => {
|
|
1418
|
+
if (omRooted) {
|
|
1419
|
+
return buildOrgTreeNode(graph, knowledgeNodes, facetStates, organizationModel, favorites);
|
|
1420
|
+
}
|
|
1421
|
+
const ctx = buildTreeContext(graph, knowledgeNodes);
|
|
1422
|
+
const spineMetaMap = buildSpineMetaMap(graph, graphSpine);
|
|
1423
|
+
const allBareIds = Object.keys(spineMetaMap);
|
|
1424
|
+
const topIds = topLevelGraphIds(allBareIds);
|
|
1425
|
+
const visibleSpineIds = computeVisibleSpineIds(allBareIds, graphSpine, facetStates, ctx, organizationModel);
|
|
1426
|
+
return topIds.filter((bareId) => visibleSpineIds.has(bareId)).map(
|
|
1427
|
+
(bareId) => buildSpineTreeNode(
|
|
1428
|
+
bareId,
|
|
1429
|
+
allBareIds,
|
|
1430
|
+
spineMetaMap,
|
|
1431
|
+
graphSpine,
|
|
1432
|
+
facetStates,
|
|
1433
|
+
ctx,
|
|
1434
|
+
visibleSpineIds,
|
|
1435
|
+
organizationModel
|
|
1436
|
+
)
|
|
1437
|
+
);
|
|
1438
|
+
}, [facetStates, favorites, graph, graphSpine, knowledgeNodes, omRooted, organizationModel]);
|
|
1439
|
+
const initialExpandedState = useMemo(() => getInitialExpandedState(treeData, omRooted), [treeData, omRooted]);
|
|
1440
|
+
const treeController = useTree({ initialExpandedState });
|
|
1441
|
+
const leafNodeMap = useMemo(() => {
|
|
1442
|
+
const map = /* @__PURE__ */ new Map();
|
|
1443
|
+
for (const node of knowledgeNodes) {
|
|
1444
|
+
map.set(node.id, node);
|
|
1445
|
+
}
|
|
1446
|
+
return map;
|
|
1447
|
+
}, [knowledgeNodes]);
|
|
1448
|
+
const graphNodeMap = useMemo(() => {
|
|
1449
|
+
const map = /* @__PURE__ */ new Map();
|
|
1450
|
+
for (const graphNode of graph.nodes) {
|
|
1451
|
+
map.set(graphNode.id, graphNode);
|
|
1452
|
+
}
|
|
1453
|
+
return map;
|
|
1454
|
+
}, [graph]);
|
|
1455
|
+
if (treeData.length === 0) {
|
|
1456
|
+
return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { padding: "var(--mantine-spacing-md)" }, children: omRooted ? "No OM domains in model." : `No ${spine} spine nodes in graph.` });
|
|
1457
|
+
}
|
|
1458
|
+
return /* @__PURE__ */ jsx(
|
|
1459
|
+
Tree,
|
|
1460
|
+
{
|
|
1461
|
+
data: treeData,
|
|
1462
|
+
tree: treeController,
|
|
1463
|
+
style: { padding: "var(--mantine-spacing-xs)" },
|
|
1464
|
+
renderNode: ({ node, expanded, hasChildren, elementProps }) => {
|
|
1465
|
+
const value = node.value;
|
|
1466
|
+
const typedNode = node;
|
|
1467
|
+
const decoratedElementProps = {
|
|
1468
|
+
...elementProps,
|
|
1469
|
+
"data-tree-row-value": typeof value === "string" ? value : void 0
|
|
1470
|
+
};
|
|
1471
|
+
if (typedNode.nodeType === "group") {
|
|
1472
|
+
const groupKey = typeof value === "string" ? value.slice(GROUP_PREFIX.length) : "";
|
|
1473
|
+
const isActive2 = selectedNodeId === value;
|
|
1474
|
+
const isQuickAccess = groupKey === QUICK_ACCESS_GROUP_KEY;
|
|
1475
|
+
return /* @__PURE__ */ jsx(
|
|
1476
|
+
DirectoryRow,
|
|
1477
|
+
{
|
|
1478
|
+
elementProps: decoratedElementProps,
|
|
1479
|
+
expanded,
|
|
1480
|
+
hasChildren,
|
|
1481
|
+
label: String(node.label),
|
|
1482
|
+
iconToken: GROUP_ICON_TOKENS[groupKey] ?? typedNode.icon,
|
|
1483
|
+
command: isQuickAccess ? "" : getKnowledgeDirectoryCommand(
|
|
1484
|
+
typedNode.knowledgeNodeIds,
|
|
1485
|
+
getKnowledgeTreeFolderCommand(`${GROUP_PREFIX}${groupKey}`)
|
|
1486
|
+
),
|
|
1487
|
+
isActive: isActive2,
|
|
1488
|
+
fallbackKind: "organization",
|
|
1489
|
+
uppercase: true,
|
|
1490
|
+
onSelectGraphNode: isQuickAccess ? void 0 : onSelectGroup ? () => onSelectGroup(groupKey) : void 0,
|
|
1491
|
+
favorite: isQuickAccess ? void 0 : {
|
|
1492
|
+
routeId: `${GROUP_PREFIX}${groupKey}`,
|
|
1493
|
+
label: String(node.label),
|
|
1494
|
+
kind: "group",
|
|
1495
|
+
iconToken: typedNode.icon
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
if (typedNode.nodeType === "favorite" && typedNode.favoriteRouteId && typedNode.favoriteKind) {
|
|
1501
|
+
const routeId = typedNode.favoriteRouteId;
|
|
1502
|
+
const favoriteKind = typedNode.favoriteKind;
|
|
1503
|
+
return /* @__PURE__ */ jsx(
|
|
1504
|
+
FavoriteRow,
|
|
1505
|
+
{
|
|
1506
|
+
elementProps: decoratedElementProps,
|
|
1507
|
+
label: String(node.label),
|
|
1508
|
+
routeId,
|
|
1509
|
+
kind: favoriteKind,
|
|
1510
|
+
iconToken: typedNode.icon,
|
|
1511
|
+
onActivate: () => {
|
|
1512
|
+
dispatchFavoriteSelection(routeId, favoriteKind, typedNode, {
|
|
1513
|
+
onSelectNode,
|
|
1514
|
+
onSelectGraphNode,
|
|
1515
|
+
onSelectGroup,
|
|
1516
|
+
onSelectDomain,
|
|
1517
|
+
onSelectItem,
|
|
1518
|
+
leafNodeMap,
|
|
1519
|
+
graphNodeMap
|
|
1520
|
+
});
|
|
1521
|
+
focusFavoriteInTree(treeData, treeController, { routeId, kind: favoriteKind });
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
);
|
|
1525
|
+
}
|
|
1526
|
+
if (typedNode.nodeType === "domain" && typedNode.domainKey) {
|
|
1527
|
+
const domainKey = typedNode.domainKey;
|
|
1528
|
+
const isActive2 = selectedNodeId === `${DOMAIN_PREFIX}${domainKey}`;
|
|
1529
|
+
return /* @__PURE__ */ jsx(
|
|
1530
|
+
DirectoryRow,
|
|
1531
|
+
{
|
|
1532
|
+
elementProps: decoratedElementProps,
|
|
1533
|
+
expanded,
|
|
1534
|
+
hasChildren,
|
|
1535
|
+
label: String(node.label),
|
|
1536
|
+
iconToken: void 0,
|
|
1537
|
+
command: getKnowledgeDirectoryCommand(
|
|
1538
|
+
typedNode.knowledgeNodeIds,
|
|
1539
|
+
getKnowledgeTreeFolderCommand(`${DOMAIN_PREFIX}${domainKey}`)
|
|
1540
|
+
),
|
|
1541
|
+
isActive: isActive2,
|
|
1542
|
+
fallbackKind: "organization",
|
|
1543
|
+
uppercase: true,
|
|
1544
|
+
onSelectGraphNode: onSelectDomain ? () => onSelectDomain(domainKey) : void 0,
|
|
1545
|
+
favorite: {
|
|
1546
|
+
routeId: `${DOMAIN_PREFIX}${domainKey}`,
|
|
1547
|
+
label: String(node.label),
|
|
1548
|
+
kind: "domain"
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
);
|
|
1552
|
+
}
|
|
1553
|
+
if (typedNode.nodeType === "item" && typedNode.domainKey && typedNode.itemId) {
|
|
1554
|
+
const graphNode2 = typedNode.graphNodeId ? graphNodeMap.get(typedNode.graphNodeId) : void 0;
|
|
1555
|
+
const itemRouteId = `${ITEM_PREFIX}${typedNode.domainKey}:${typedNode.itemId}`;
|
|
1556
|
+
const routeToDomainPanel = shouldRouteItemToDomainPanel(typedNode.domainKey);
|
|
1557
|
+
const fallbackCommand = graphNode2?.kind === "knowledge" && graphNode2.sourceId ? getKnowledgeNodeReadCommand(graphNode2.sourceId) : graphNode2 ? getKnowledgeGraphFolderCommand(graphNode2.id) : getKnowledgeTreeFolderCommand(itemRouteId);
|
|
1558
|
+
const isActive2 = selectedNodeId !== void 0 && (selectedNodeId === itemRouteId || selectedNodeId === typedNode.itemId || selectedNodeId === typedNode.graphNodeId || graphNode2 !== void 0 && (selectedNodeId === graphNode2.id || selectedNodeId === graphNode2.sourceId));
|
|
1559
|
+
return /* @__PURE__ */ jsx(
|
|
1560
|
+
DirectoryRow,
|
|
1561
|
+
{
|
|
1562
|
+
elementProps: decoratedElementProps,
|
|
1563
|
+
expanded,
|
|
1564
|
+
hasChildren,
|
|
1565
|
+
label: String(node.label),
|
|
1566
|
+
iconToken: typedNode.icon ?? graphNode2?.icon,
|
|
1567
|
+
command: getKnowledgeDirectoryCommand(typedNode.knowledgeNodeIds, fallbackCommand),
|
|
1568
|
+
isActive: isActive2,
|
|
1569
|
+
fallbackKind: graphNode2?.kind ?? "organization",
|
|
1570
|
+
onSelectGraphNode: routeToDomainPanel && onSelectItem ? () => onSelectItem(typedNode.domainKey ?? "", typedNode.itemId ?? "") : graphNode2 ? () => onSelectGraphNode?.(graphNode2) : onSelectItem ? () => onSelectItem(typedNode.domainKey ?? "", typedNode.itemId ?? "") : void 0,
|
|
1571
|
+
favorite: {
|
|
1572
|
+
routeId: itemRouteId,
|
|
1573
|
+
label: String(node.label),
|
|
1574
|
+
kind: "item",
|
|
1575
|
+
iconToken: typedNode.icon ?? graphNode2?.icon
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
);
|
|
1579
|
+
}
|
|
1580
|
+
if (typeof value === "string" && value.startsWith(LEAF_PREFIX)) {
|
|
1581
|
+
const knowledgeNodeId = value.split("::").at(-1);
|
|
1582
|
+
const knowledgeNode = knowledgeNodeId ? leafNodeMap.get(knowledgeNodeId) : void 0;
|
|
1583
|
+
if (!knowledgeNode) return null;
|
|
1584
|
+
return /* @__PURE__ */ jsx(
|
|
1585
|
+
KnowledgeLeafRow,
|
|
1586
|
+
{
|
|
1587
|
+
elementProps: decoratedElementProps,
|
|
1588
|
+
knowledgeNode,
|
|
1589
|
+
isActive: knowledgeNode.id === selectedNodeId,
|
|
1590
|
+
onSelectNode
|
|
1591
|
+
}
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
if (typeof value === "string" && value.startsWith(FOLDER_PREFIX)) {
|
|
1595
|
+
return /* @__PURE__ */ jsx(
|
|
1596
|
+
DirectoryRow,
|
|
1597
|
+
{
|
|
1598
|
+
elementProps: decoratedElementProps,
|
|
1599
|
+
expanded,
|
|
1600
|
+
hasChildren,
|
|
1601
|
+
label: String(node.label),
|
|
1602
|
+
iconToken: typedNode.icon,
|
|
1603
|
+
command: getKnowledgeDirectoryCommand(
|
|
1604
|
+
typedNode.knowledgeNodeIds,
|
|
1605
|
+
getKnowledgeTreeFolderCommand(String(value))
|
|
1606
|
+
),
|
|
1607
|
+
isActive: false
|
|
1608
|
+
}
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
if (typedNode.nodeType === "graph" && typedNode.graphNodeId) {
|
|
1612
|
+
const graphNode2 = graphNodeMap.get(typedNode.graphNodeId);
|
|
1613
|
+
if (!graphNode2) return null;
|
|
1614
|
+
const isActive2 = selectedNodeId !== void 0 && (selectedNodeId === graphNode2.id || selectedNodeId === graphNode2.sourceId);
|
|
1615
|
+
return /* @__PURE__ */ jsx(
|
|
1616
|
+
DirectoryRow,
|
|
1617
|
+
{
|
|
1618
|
+
elementProps: decoratedElementProps,
|
|
1619
|
+
expanded,
|
|
1620
|
+
hasChildren,
|
|
1621
|
+
label: String(node.label),
|
|
1622
|
+
iconToken: typedNode.icon,
|
|
1623
|
+
command: getKnowledgeGraphFolderCommand(graphNode2.id),
|
|
1624
|
+
isActive: isActive2,
|
|
1625
|
+
fallbackKind: graphNode2.kind,
|
|
1626
|
+
onSelectGraphNode: () => onSelectGraphNode?.(graphNode2),
|
|
1627
|
+
favorite: {
|
|
1628
|
+
routeId: graphNode2.id,
|
|
1629
|
+
label: graphNode2.label,
|
|
1630
|
+
kind: "graph",
|
|
1631
|
+
iconToken: typedNode.icon ?? graphNode2.icon
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
const graphNodeId = typedNode.graphNodeId ?? String(value).replace(SPINE_PREFIX, "");
|
|
1637
|
+
const graphNode = graphNodeMap.get(graphNodeId);
|
|
1638
|
+
const isActive = selectedNodeId !== void 0 && graphNode !== void 0 && (selectedNodeId === graphNode.id || selectedNodeId === graphNode.sourceId || selectedNodeId === graphNodeId);
|
|
1639
|
+
return /* @__PURE__ */ jsx(
|
|
1640
|
+
DirectoryRow,
|
|
1641
|
+
{
|
|
1642
|
+
elementProps: decoratedElementProps,
|
|
1643
|
+
expanded,
|
|
1644
|
+
hasChildren,
|
|
1645
|
+
label: String(node.label),
|
|
1646
|
+
iconToken: typedNode.icon,
|
|
1647
|
+
command: graphSpine ? getKnowledgeSpineFolderCommand(graphSpine, graphNode?.sourceId ?? graphNodeId) : "",
|
|
1648
|
+
isActive,
|
|
1649
|
+
fallbackKind: graphNode?.kind ?? "system",
|
|
1650
|
+
uppercase: true,
|
|
1651
|
+
onSelectGraphNode: graphNode ? () => onSelectGraphNode?.(graphNode) : void 0,
|
|
1652
|
+
favorite: graphNode ? {
|
|
1653
|
+
routeId: graphNode.id,
|
|
1654
|
+
label: graphNode.label,
|
|
1655
|
+
kind: "graph",
|
|
1656
|
+
iconToken: typedNode.icon ?? graphNode.icon
|
|
1657
|
+
} : void 0
|
|
1658
|
+
}
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
);
|
|
1663
|
+
}
|
|
1664
|
+
function FavoriteStarControl({ routeId, label, kind, iconToken, hovered }) {
|
|
1665
|
+
const isFavorited = useKnowledgeFavoritesStore((state) => Boolean(state.favorites[routeId]));
|
|
1666
|
+
const toggleFavorite = useKnowledgeFavoritesStore((state) => state.toggleFavorite);
|
|
1667
|
+
const visible = hovered || isFavorited;
|
|
1668
|
+
return /* @__PURE__ */ jsx(
|
|
1669
|
+
"span",
|
|
1670
|
+
{
|
|
1671
|
+
role: "button",
|
|
1672
|
+
tabIndex: visible ? 0 : -1,
|
|
1673
|
+
"aria-hidden": !visible,
|
|
1674
|
+
"aria-pressed": isFavorited,
|
|
1675
|
+
"aria-label": isFavorited ? `Unfavorite ${label}` : `Favorite ${label}`,
|
|
1676
|
+
onClick: (event) => {
|
|
1677
|
+
event.preventDefault();
|
|
1678
|
+
event.stopPropagation();
|
|
1679
|
+
toggleFavorite({ routeId, label, kind, iconToken });
|
|
1680
|
+
},
|
|
1681
|
+
onKeyDown: (event) => {
|
|
1682
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1683
|
+
event.preventDefault();
|
|
1684
|
+
event.stopPropagation();
|
|
1685
|
+
toggleFavorite({ routeId, label, kind, iconToken });
|
|
1686
|
+
},
|
|
1687
|
+
style: {
|
|
1688
|
+
display: "inline-flex",
|
|
1689
|
+
alignItems: "center",
|
|
1690
|
+
justifyContent: "center",
|
|
1691
|
+
width: 22,
|
|
1692
|
+
height: 22,
|
|
1693
|
+
flexShrink: 0,
|
|
1694
|
+
opacity: visible ? 1 : 0,
|
|
1695
|
+
pointerEvents: visible ? "auto" : "none",
|
|
1696
|
+
color: isFavorited ? "var(--mantine-color-yellow-5)" : "var(--color-text-subtle)",
|
|
1697
|
+
transition: "opacity 120ms ease, color 120ms ease"
|
|
1698
|
+
},
|
|
1699
|
+
children: isFavorited ? /* @__PURE__ */ jsx(IconStarFilled, { size: 14 }) : /* @__PURE__ */ jsx(IconStar, { size: 14 })
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1702
|
+
}
|
|
1703
|
+
function focusFavoriteInTree(treeData, controller, favorite) {
|
|
1704
|
+
const path = findFavoritePathInTree(treeData, favorite);
|
|
1705
|
+
if (!path || path.length === 0) return;
|
|
1706
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
1707
|
+
controller.expand(path[i]);
|
|
1708
|
+
}
|
|
1709
|
+
const targetValue = path[path.length - 1];
|
|
1710
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1711
|
+
const escape = (raw) => typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(raw) : raw.replace(/"/g, '\\"');
|
|
1712
|
+
window.requestAnimationFrame(() => {
|
|
1713
|
+
window.requestAnimationFrame(() => {
|
|
1714
|
+
const el = document.querySelector(`[data-tree-row-value="${escape(targetValue)}"]`);
|
|
1715
|
+
if (el instanceof HTMLElement) {
|
|
1716
|
+
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1717
|
+
}
|
|
1718
|
+
});
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1721
|
+
function dispatchFavoriteSelection(routeId, kind, typedNode, ctx) {
|
|
1722
|
+
if (kind === "group" && routeId.startsWith(GROUP_PREFIX)) {
|
|
1723
|
+
ctx.onSelectGroup?.(routeId.slice(GROUP_PREFIX.length));
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
if (kind === "domain" && routeId.startsWith(DOMAIN_PREFIX)) {
|
|
1727
|
+
ctx.onSelectDomain?.(routeId.slice(DOMAIN_PREFIX.length));
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
if (kind === "item" && routeId.startsWith(ITEM_PREFIX)) {
|
|
1731
|
+
const rest = routeId.slice(ITEM_PREFIX.length);
|
|
1732
|
+
const sepIndex = rest.indexOf(":");
|
|
1733
|
+
if (sepIndex > 0) {
|
|
1734
|
+
ctx.onSelectItem?.(rest.slice(0, sepIndex), rest.slice(sepIndex + 1));
|
|
1735
|
+
}
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
if (kind === "graph") {
|
|
1739
|
+
const graphNode = ctx.graphNodeMap.get(routeId);
|
|
1740
|
+
if (graphNode) ctx.onSelectGraphNode?.(graphNode);
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
if (kind === "knowledge") {
|
|
1744
|
+
const knowledgeNode = ctx.leafNodeMap.get(routeId);
|
|
1745
|
+
if (knowledgeNode) ctx.onSelectNode(knowledgeNode);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
function FavoriteRow({ elementProps, label, routeId, kind, iconToken, onActivate }) {
|
|
1749
|
+
const [hovered, setHovered] = useState(false);
|
|
1750
|
+
return /* @__PURE__ */ jsx(
|
|
1751
|
+
UnstyledButton,
|
|
1752
|
+
{
|
|
1753
|
+
...elementProps,
|
|
1754
|
+
onMouseEnter: (event) => {
|
|
1755
|
+
elementProps.onMouseEnter?.(event);
|
|
1756
|
+
setHovered(true);
|
|
1757
|
+
},
|
|
1758
|
+
onMouseLeave: (event) => {
|
|
1759
|
+
elementProps.onMouseLeave?.(event);
|
|
1760
|
+
setHovered(false);
|
|
1761
|
+
},
|
|
1762
|
+
onClick: () => onActivate(),
|
|
1763
|
+
style: {
|
|
1764
|
+
...elementProps.style ?? {},
|
|
1765
|
+
padding: "5px 8px 5px 24px",
|
|
1766
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1767
|
+
backgroundColor: hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1768
|
+
width: "100%",
|
|
1769
|
+
textAlign: "left",
|
|
1770
|
+
display: "block"
|
|
1771
|
+
},
|
|
1772
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
1773
|
+
/* @__PURE__ */ jsx(
|
|
1774
|
+
SemanticIcon,
|
|
1775
|
+
{
|
|
1776
|
+
token: iconToken ?? (kind === "knowledge" ? "reference" : "info"),
|
|
1777
|
+
size: 15,
|
|
1778
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1779
|
+
}
|
|
1780
|
+
),
|
|
1781
|
+
/* @__PURE__ */ jsx(
|
|
1782
|
+
Text,
|
|
1783
|
+
{
|
|
1784
|
+
size: "sm",
|
|
1785
|
+
c: hovered ? "var(--color-text)" : void 0,
|
|
1786
|
+
style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1787
|
+
children: label
|
|
1788
|
+
}
|
|
1789
|
+
),
|
|
1790
|
+
/* @__PURE__ */ jsx(
|
|
1791
|
+
TrailingCopySlot,
|
|
1792
|
+
{
|
|
1793
|
+
command: "",
|
|
1794
|
+
label: "",
|
|
1795
|
+
showCopy: false,
|
|
1796
|
+
favorite: { routeId, label, kind, iconToken },
|
|
1797
|
+
hovered
|
|
1798
|
+
}
|
|
1799
|
+
)
|
|
1800
|
+
] })
|
|
1801
|
+
}
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
function CopyCommandControl({ command, label, visible }) {
|
|
1805
|
+
const clipboard = useClipboard({ timeout: 1500 });
|
|
1806
|
+
if (!command) return null;
|
|
1807
|
+
return /* @__PURE__ */ jsx(
|
|
1808
|
+
"span",
|
|
1809
|
+
{
|
|
1810
|
+
role: "button",
|
|
1811
|
+
tabIndex: visible ? 0 : -1,
|
|
1812
|
+
"aria-hidden": !visible,
|
|
1813
|
+
"aria-label": label,
|
|
1814
|
+
onClick: (event) => {
|
|
1815
|
+
event.preventDefault();
|
|
1816
|
+
event.stopPropagation();
|
|
1817
|
+
clipboard.copy(command);
|
|
1818
|
+
},
|
|
1819
|
+
onKeyDown: (event) => {
|
|
1820
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1821
|
+
event.preventDefault();
|
|
1822
|
+
event.stopPropagation();
|
|
1823
|
+
clipboard.copy(command);
|
|
1824
|
+
},
|
|
1825
|
+
style: {
|
|
1826
|
+
display: "inline-flex",
|
|
1827
|
+
alignItems: "center",
|
|
1828
|
+
justifyContent: "center",
|
|
1829
|
+
width: 22,
|
|
1830
|
+
height: 22,
|
|
1831
|
+
flexShrink: 0,
|
|
1832
|
+
opacity: visible ? 1 : 0,
|
|
1833
|
+
pointerEvents: visible ? "auto" : "none",
|
|
1834
|
+
color: clipboard.copied ? "var(--color-primary)" : "var(--color-text-subtle)",
|
|
1835
|
+
transition: "opacity 120ms ease, color 120ms ease"
|
|
1836
|
+
},
|
|
1837
|
+
children: clipboard.copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 })
|
|
1838
|
+
}
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
function KnowledgeLeafRow({ elementProps, knowledgeNode, isActive, onSelectNode }) {
|
|
1842
|
+
const [hovered, setHovered] = useState(false);
|
|
1843
|
+
return /* @__PURE__ */ jsx(
|
|
1844
|
+
UnstyledButton,
|
|
1845
|
+
{
|
|
1846
|
+
...elementProps,
|
|
1847
|
+
onMouseEnter: (event) => {
|
|
1848
|
+
elementProps.onMouseEnter?.(event);
|
|
1849
|
+
setHovered(true);
|
|
1850
|
+
},
|
|
1851
|
+
onMouseLeave: (event) => {
|
|
1852
|
+
elementProps.onMouseLeave?.(event);
|
|
1853
|
+
setHovered(false);
|
|
1854
|
+
},
|
|
1855
|
+
onClick: () => onSelectNode(knowledgeNode),
|
|
1856
|
+
style: {
|
|
1857
|
+
...elementProps.style ?? {},
|
|
1858
|
+
padding: "5px 8px 5px 24px",
|
|
1859
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1860
|
+
backgroundColor: isActive ? "color-mix(in srgb, var(--color-primary) 10%, transparent)" : hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1861
|
+
width: "100%",
|
|
1862
|
+
textAlign: "left",
|
|
1863
|
+
display: "block"
|
|
1864
|
+
},
|
|
1865
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
1866
|
+
/* @__PURE__ */ jsx(
|
|
1867
|
+
SemanticIcon,
|
|
1868
|
+
{
|
|
1869
|
+
token: getKnowledgeIconToken(knowledgeNode) ?? "reference",
|
|
1870
|
+
size: 15,
|
|
1871
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1872
|
+
}
|
|
1873
|
+
),
|
|
1874
|
+
/* @__PURE__ */ jsx(
|
|
1875
|
+
Text,
|
|
1876
|
+
{
|
|
1877
|
+
size: "sm",
|
|
1878
|
+
c: isActive ? "var(--color-primary)" : hovered ? "var(--color-text)" : void 0,
|
|
1879
|
+
fw: isActive ? 600 : 400,
|
|
1880
|
+
style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1881
|
+
children: knowledgeNode.title
|
|
1882
|
+
}
|
|
1883
|
+
),
|
|
1884
|
+
/* @__PURE__ */ jsx(
|
|
1885
|
+
TrailingCopySlot,
|
|
1886
|
+
{
|
|
1887
|
+
command: getKnowledgeNodeReadCommand(knowledgeNode.id),
|
|
1888
|
+
label: "Copy knowledge command",
|
|
1889
|
+
showCopy: hovered,
|
|
1890
|
+
favorite: {
|
|
1891
|
+
routeId: knowledgeNode.id,
|
|
1892
|
+
label: knowledgeNode.title,
|
|
1893
|
+
kind: "knowledge",
|
|
1894
|
+
iconToken: getKnowledgeIconToken(knowledgeNode)
|
|
1895
|
+
},
|
|
1896
|
+
hovered
|
|
1897
|
+
}
|
|
1898
|
+
)
|
|
1899
|
+
] })
|
|
1900
|
+
}
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
function DirectoryRow({
|
|
1904
|
+
elementProps,
|
|
1905
|
+
expanded,
|
|
1906
|
+
hasChildren,
|
|
1907
|
+
label,
|
|
1908
|
+
iconToken,
|
|
1909
|
+
command,
|
|
1910
|
+
isActive,
|
|
1911
|
+
fallbackKind = "system",
|
|
1912
|
+
uppercase = false,
|
|
1913
|
+
onSelectGraphNode,
|
|
1914
|
+
favorite
|
|
1915
|
+
}) {
|
|
1916
|
+
const [hovered, setHovered] = useState(false);
|
|
1917
|
+
return /* @__PURE__ */ jsxs(
|
|
1918
|
+
Group,
|
|
1919
|
+
{
|
|
1920
|
+
...elementProps,
|
|
1921
|
+
gap: "xs",
|
|
1922
|
+
onMouseEnter: (event) => {
|
|
1923
|
+
elementProps.onMouseEnter?.(event);
|
|
1924
|
+
setHovered(true);
|
|
1925
|
+
},
|
|
1926
|
+
onMouseLeave: (event) => {
|
|
1927
|
+
elementProps.onMouseLeave?.(event);
|
|
1928
|
+
setHovered(false);
|
|
1929
|
+
},
|
|
1930
|
+
onClick: (event) => {
|
|
1931
|
+
if (onSelectGraphNode) {
|
|
1932
|
+
if (isActive && expanded) {
|
|
1933
|
+
elementProps.onClick?.(event);
|
|
1934
|
+
} else {
|
|
1935
|
+
if (!expanded) elementProps.onClick?.(event);
|
|
1936
|
+
onSelectGraphNode();
|
|
1937
|
+
}
|
|
1938
|
+
} else {
|
|
1939
|
+
elementProps.onClick?.(event);
|
|
1940
|
+
}
|
|
1941
|
+
},
|
|
1942
|
+
style: {
|
|
1943
|
+
...elementProps.style ?? {},
|
|
1944
|
+
padding: "4px 8px",
|
|
1945
|
+
borderRadius: "var(--mantine-radius-sm)",
|
|
1946
|
+
backgroundColor: isActive ? "color-mix(in srgb, var(--color-primary) 10%, transparent)" : hovered ? "var(--color-surface-hover)" : "transparent",
|
|
1947
|
+
cursor: onSelectGraphNode || hasChildren ? "pointer" : "default",
|
|
1948
|
+
userSelect: "none"
|
|
1949
|
+
},
|
|
1950
|
+
children: [
|
|
1951
|
+
hasChildren ? /* @__PURE__ */ jsx(
|
|
1952
|
+
"span",
|
|
1953
|
+
{
|
|
1954
|
+
"aria-hidden": "true",
|
|
1955
|
+
style: {
|
|
1956
|
+
display: "inline-flex",
|
|
1957
|
+
alignItems: "center",
|
|
1958
|
+
justifyContent: "center",
|
|
1959
|
+
width: 12,
|
|
1960
|
+
height: 12,
|
|
1961
|
+
color: SIDEBAR_TREE_ACCENT_COLOR,
|
|
1962
|
+
flexShrink: 0
|
|
1963
|
+
},
|
|
1964
|
+
children: expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 12, stroke: 2 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 12, stroke: 2 })
|
|
1965
|
+
}
|
|
1966
|
+
) : /* @__PURE__ */ jsx(Text, { size: "xs", style: { width: 12, flexShrink: 0 } }),
|
|
1967
|
+
/* @__PURE__ */ jsx(
|
|
1968
|
+
SemanticIcon,
|
|
1969
|
+
{
|
|
1970
|
+
token: iconToken ?? (fallbackKind !== void 0 ? graphKindToFallbackToken(fallbackKind) : "info"),
|
|
1971
|
+
size: 14,
|
|
1972
|
+
style: { color: SIDEBAR_TREE_ACCENT_COLOR }
|
|
1973
|
+
}
|
|
1974
|
+
),
|
|
1975
|
+
/* @__PURE__ */ jsx(
|
|
1976
|
+
Text,
|
|
1977
|
+
{
|
|
1978
|
+
size: "sm",
|
|
1979
|
+
fw: isActive ? 700 : 600,
|
|
1980
|
+
tt: uppercase ? "uppercase" : void 0,
|
|
1981
|
+
c: isActive ? "var(--color-primary)" : hovered ? "var(--color-text)" : void 0,
|
|
1982
|
+
style: {
|
|
1983
|
+
letterSpacing: uppercase ? "0.05em" : 0,
|
|
1984
|
+
flex: 1,
|
|
1985
|
+
minWidth: 0,
|
|
1986
|
+
overflow: "hidden",
|
|
1987
|
+
textOverflow: "ellipsis",
|
|
1988
|
+
whiteSpace: "nowrap"
|
|
1989
|
+
},
|
|
1990
|
+
children: label
|
|
1991
|
+
}
|
|
1992
|
+
),
|
|
1993
|
+
/* @__PURE__ */ jsx(
|
|
1994
|
+
TrailingCopySlot,
|
|
1995
|
+
{
|
|
1996
|
+
command,
|
|
1997
|
+
label: "Copy folder knowledge commands",
|
|
1998
|
+
showCopy: hovered,
|
|
1999
|
+
favorite,
|
|
2000
|
+
hovered
|
|
2001
|
+
}
|
|
2002
|
+
)
|
|
2003
|
+
]
|
|
2004
|
+
}
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
function TrailingCopySlot({ command, label, showCopy, favorite, hovered }) {
|
|
2008
|
+
const isFavorited = useKnowledgeFavoritesStore(
|
|
2009
|
+
(state) => favorite ? Boolean(state.favorites[favorite.routeId]) : false
|
|
2010
|
+
);
|
|
2011
|
+
const favoriteVisible = Boolean(favorite) && (hovered || isFavorited);
|
|
2012
|
+
const copyVisible = showCopy && Boolean(command);
|
|
2013
|
+
if (!favoriteVisible && !copyVisible) return null;
|
|
2014
|
+
return /* @__PURE__ */ jsxs(
|
|
2015
|
+
"span",
|
|
2016
|
+
{
|
|
2017
|
+
style: {
|
|
2018
|
+
display: "inline-flex",
|
|
2019
|
+
alignItems: "center",
|
|
2020
|
+
justifyContent: "flex-end",
|
|
2021
|
+
gap: 2,
|
|
2022
|
+
height: 22,
|
|
2023
|
+
flexShrink: 0
|
|
2024
|
+
},
|
|
2025
|
+
children: [
|
|
2026
|
+
copyVisible ? /* @__PURE__ */ jsx(CopyCommandControl, { command, label, visible: true }) : null,
|
|
2027
|
+
favoriteVisible && favorite ? /* @__PURE__ */ jsx(
|
|
2028
|
+
FavoriteStarControl,
|
|
2029
|
+
{
|
|
2030
|
+
routeId: favorite.routeId,
|
|
2031
|
+
label: favorite.label,
|
|
2032
|
+
kind: favorite.kind,
|
|
2033
|
+
iconToken: favorite.iconToken,
|
|
2034
|
+
hovered: true
|
|
2035
|
+
}
|
|
2036
|
+
) : null
|
|
2037
|
+
]
|
|
2038
|
+
}
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
var indexPromise = null;
|
|
2042
|
+
function loadSearchIndex() {
|
|
2043
|
+
if (!indexPromise) {
|
|
2044
|
+
indexPromise = import('./knowledge-search-index-P7PR626V.js').then(
|
|
2045
|
+
(mod) => buildSearchIndex(mod.default ?? mod)
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
return indexPromise;
|
|
2049
|
+
}
|
|
2050
|
+
function buildSearchIndex(entries) {
|
|
2051
|
+
return {
|
|
2052
|
+
search(query) {
|
|
2053
|
+
if (!query.trim()) return [];
|
|
2054
|
+
const q = query.trim().toLowerCase();
|
|
2055
|
+
const scored = [];
|
|
2056
|
+
for (const entry of entries) {
|
|
2057
|
+
let score = 0;
|
|
2058
|
+
if (entry.title.toLowerCase().includes(q)) score += 3;
|
|
2059
|
+
if (entry.summary.toLowerCase().includes(q)) score += 2;
|
|
2060
|
+
if (entry.bodyText.toLowerCase().includes(q)) score += 1;
|
|
2061
|
+
if (score > 0) scored.push({ id: entry.id, score });
|
|
2062
|
+
}
|
|
2063
|
+
return scored.sort((a, b) => b.score - a.score).map((s) => s.id);
|
|
2064
|
+
}
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
2067
|
+
function KnowledgeSearchBar({
|
|
2068
|
+
knowledgeNodes,
|
|
2069
|
+
onResults,
|
|
2070
|
+
placeholder = "Search knowledge\u2026"
|
|
2071
|
+
}) {
|
|
2072
|
+
const [query, setQuery] = useState("");
|
|
2073
|
+
const indexRef = useRef(null);
|
|
2074
|
+
const nodeMapRef = useRef(/* @__PURE__ */ new Map());
|
|
2075
|
+
useEffect(() => {
|
|
2076
|
+
const map = /* @__PURE__ */ new Map();
|
|
2077
|
+
for (const node of knowledgeNodes) map.set(node.id, node);
|
|
2078
|
+
nodeMapRef.current = map;
|
|
2079
|
+
}, [knowledgeNodes]);
|
|
2080
|
+
const handleChange = (value) => {
|
|
2081
|
+
setQuery(value);
|
|
2082
|
+
if (!value.trim()) {
|
|
2083
|
+
onResults(null);
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
if (indexRef.current) {
|
|
2087
|
+
runSearch(value, indexRef.current);
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
void loadSearchIndex().then((index) => {
|
|
2091
|
+
indexRef.current = index;
|
|
2092
|
+
if (query.trim() || value.trim()) runSearch(value, index);
|
|
2093
|
+
});
|
|
2094
|
+
};
|
|
2095
|
+
function runSearch(value, index) {
|
|
2096
|
+
const ids = index.search(value);
|
|
2097
|
+
const hits = ids.flatMap((id) => {
|
|
2098
|
+
const node = nodeMapRef.current.get(id);
|
|
2099
|
+
return node ? [node] : [];
|
|
2100
|
+
});
|
|
2101
|
+
onResults(hits);
|
|
2102
|
+
}
|
|
2103
|
+
const handleClear = () => {
|
|
2104
|
+
setQuery("");
|
|
2105
|
+
onResults(null);
|
|
2106
|
+
};
|
|
2107
|
+
return /* @__PURE__ */ jsx(
|
|
2108
|
+
TextInput,
|
|
2109
|
+
{
|
|
2110
|
+
value: query,
|
|
2111
|
+
onChange: (e) => handleChange(e.currentTarget.value),
|
|
2112
|
+
placeholder,
|
|
2113
|
+
leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
|
|
2114
|
+
rightSection: query ? /* @__PURE__ */ jsx(IconX, { size: 14, style: { cursor: "pointer", color: "var(--color-text-subtle)" }, onClick: handleClear }) : null,
|
|
2115
|
+
styles: {
|
|
2116
|
+
input: {
|
|
2117
|
+
backgroundColor: "var(--color-surface)",
|
|
2118
|
+
borderColor: "var(--color-border)",
|
|
2119
|
+
color: "var(--color-text)"
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
);
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
export { KNOWLEDGE_DOMAINS_WITH_PANELS, KNOWLEDGE_ICON_TOKEN_BY_KIND, KnowledgeSearchBar, KnowledgeTree, OM_TREE_GROUPS, getKnowledgeDomainFolderCommand, getKnowledgeGraphNodeCommand, getKnowledgeIconToken, getKnowledgeNodeReadCommand, getKnowledgeOntologyProjection, getKnowledgeTreeFolderCommand, getOntologyDomainLabel, getPrimaryOntologyItemsForDomain, getSharedOrganizationGraph, projectNavigationGroups, projectNavigationSurfaces };
|