@eventcatalog/core 3.48.4 → 4.0.0-beta.1
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/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/catalog-to-astro-content-directory.cjs +1 -1
- package/dist/chunk-BWN544LB.js +73 -0
- package/dist/{chunk-XNVSSL4W.js → chunk-JTZT2SDF.js} +1 -1
- package/dist/{chunk-JY4H7A4S.js → chunk-M2ZRT7KQ.js} +1 -1
- package/dist/{chunk-SY4XL6OQ.js → chunk-MBVTS76Q.js} +1 -1
- package/dist/{chunk-KDLSBQRP.js → chunk-TZTPGQGL.js} +1 -1
- package/dist/{chunk-FNDSHOV2.js → chunk-U5OTNDVQ.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/core-node-modules.cjs +108 -0
- package/dist/core-node-modules.d.cts +7 -0
- package/dist/core-node-modules.d.ts +7 -0
- package/dist/core-node-modules.js +8 -0
- package/dist/docs/development/components/components/15-prompt.md +5 -1
- package/dist/eventcatalog.cjs +124 -48
- package/dist/eventcatalog.js +26 -15
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/astro.config.mjs +27 -23
- package/eventcatalog/public/icons/languages/java.svg +1 -0
- package/eventcatalog/public/icons/payments/stripe.svg +1 -0
- package/eventcatalog/src/components/Badge.astro +10 -10
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +154 -0
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +207 -44
- package/eventcatalog/src/components/Grids/MessageGrid.tsx +0 -20
- package/eventcatalog/src/components/Grids/SystemGrid.tsx +185 -0
- package/eventcatalog/src/components/MDX/ADRTable/ADRTable.astro +99 -0
- package/eventcatalog/src/components/MDX/ADRTable/ADRTable.client.tsx +400 -0
- package/eventcatalog/src/components/MDX/ContextDiagram/ContextDiagramPortal.tsx +21 -0
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +1 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +42 -6
- package/eventcatalog/src/components/MDX/Prompt/Prompt.astro +62 -9
- package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +8 -1
- package/eventcatalog/src/components/MDX/SystemContextMap/SystemContextMapPortal.tsx +22 -0
- package/eventcatalog/src/components/MDX/components.tsx +7 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +1 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +67 -37
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +47 -0
- package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +10 -2
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +115 -27
- package/eventcatalog/src/components/Tables/Discover/index.ts +7 -1
- package/eventcatalog/src/components/Tables/SystemResources/SystemResourcesTable.tsx +267 -0
- package/eventcatalog/src/content.config.ts +96 -8
- package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +4 -1
- package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +12 -13
- package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +6 -0
- package/eventcatalog/src/enterprise/feature.ts +3 -1
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +96 -140
- package/eventcatalog/src/layouts/VisualiserLayout.astro +66 -0
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +4 -2
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +2 -0
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +15 -15
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/discover/[type]/index.astro +47 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +15 -14
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +13 -14
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +11 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +81 -26
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +89 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +85 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +2 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +24 -1
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +24 -1
- package/eventcatalog/src/pages/index.astro +30 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +3 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +94 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +51 -0
- package/eventcatalog/src/pages/visualiser/system-context-map/index.astro +41 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +91 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +51 -0
- package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +3 -1
- package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +3 -1
- package/eventcatalog/src/stores/sidebar-store/builders/container.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +127 -49
- package/eventcatalog/src/stores/sidebar-store/builders/message.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/service.ts +4 -2
- package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +2 -1
- package/eventcatalog/src/stores/sidebar-store/builders/system.ts +166 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +99 -6
- package/eventcatalog/src/types/index.ts +2 -0
- package/eventcatalog/src/utils/collection-colors.ts +6 -1
- package/eventcatalog/src/utils/collections/domains.ts +35 -0
- package/eventcatalog/src/utils/collections/icons.ts +4 -5
- package/eventcatalog/src/utils/collections/systems.ts +110 -0
- package/eventcatalog/src/utils/collections/teams.ts +15 -10
- package/eventcatalog/src/utils/collections/users.ts +7 -4
- package/eventcatalog/src/utils/collections/util.ts +2 -0
- package/eventcatalog/src/utils/icon-map.ts +20 -0
- package/eventcatalog/src/utils/icon.ts +11 -0
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -2
- package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +0 -170
- package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +400 -0
- package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +208 -0
- package/eventcatalog/src/utils/node-graphs/utils/utils.ts +12 -0
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +17 -14
- package/eventcatalog/src/pages/visualiser/context-map/index.astro +0 -30
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder div the Context Diagram graph is portaled into.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors NodeGraphPortal, but uses a distinct `-context-diagram-portal` id so a
|
|
5
|
+
* system page can render both its System Diagram (the default `<NodeGraph />`)
|
|
6
|
+
* and its Context Diagram (`<ContextDiagram />`) without the two graphs fighting
|
|
7
|
+
* over the same portal target.
|
|
8
|
+
*/
|
|
9
|
+
const ContextDiagramPortal = (props: any) => {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className="not-prose h-[30em] my-6 mb-12 w-full relative border! border-[rgb(var(--ec-page-border))]! rounded-md overflow-hidden"
|
|
13
|
+
id={`${props.id}-context-diagram-portal`}
|
|
14
|
+
style={{
|
|
15
|
+
maxHeight: props.maxHeight ? `${props.maxHeight}em` : `30em`,
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default ContextDiagramPortal;
|
|
@@ -7,14 +7,17 @@ import {
|
|
|
7
7
|
getNodesAndEdgesForEvents,
|
|
8
8
|
getNodesAndEdgesForQueries,
|
|
9
9
|
} from '@utils/node-graphs/message-node-graph';
|
|
10
|
-
import {
|
|
11
|
-
getNodesAndEdges as getNodesAndEdgesForDomain,
|
|
12
|
-
getNodesAndEdgesForDomainContextMap,
|
|
13
|
-
} from '@utils/node-graphs/domains-node-graph';
|
|
10
|
+
import { getNodesAndEdges as getNodesAndEdgesForDomain } from '@utils/node-graphs/domains-node-graph';
|
|
14
11
|
import { getNodesAndEdges as getNodesAndEdgesForDomainEntityMap } from '@utils/node-graphs/domain-entity-map';
|
|
15
12
|
import { getDomainsCanvasData } from '@utils/node-graphs/domains-canvas';
|
|
16
13
|
import { getNodesAndEdges as getNodesAndEdgesForFlows } from '@utils/node-graphs/flows-node-graph';
|
|
17
14
|
import { getNodesAndEdges as getNodesAndEdgesForDataProduct } from '@utils/node-graphs/data-products-node-graph';
|
|
15
|
+
import { getNodesAndEdges as getNodesAndEdgesForSystem } from '@utils/node-graphs/systems-node-graph';
|
|
16
|
+
import {
|
|
17
|
+
getNodesAndEdges as getNodesAndEdgesForSystemContext,
|
|
18
|
+
getNodesAndEdgesForDomainSystems as getNodesAndEdgesForDomainSystemsContext,
|
|
19
|
+
getNodesAndEdgesForAllSystems as getNodesAndEdgesForSystemContextMap,
|
|
20
|
+
} from '@utils/node-graphs/system-context-node-graph';
|
|
18
21
|
import { buildUrl } from '@utils/url-builder';
|
|
19
22
|
import { getVersionFromCollection } from '@utils/collections/versions';
|
|
20
23
|
import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
|
|
@@ -40,6 +43,12 @@ interface Props {
|
|
|
40
43
|
showSearch?: boolean;
|
|
41
44
|
showLegend?: boolean;
|
|
42
45
|
zoomOnScroll?: boolean;
|
|
46
|
+
// Override the DOM portal the graph mounts into. Defaults to `${id}-portal`.
|
|
47
|
+
// Needed when more than one graph for the same resource is on the page
|
|
48
|
+
// (e.g. the System Diagram and the Context Diagram on a system page).
|
|
49
|
+
portalId?: string;
|
|
50
|
+
// Disable + hide the "Simulate Messages" animation (e.g. on the Context Diagram).
|
|
51
|
+
disableMessageAnimation?: boolean;
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
const {
|
|
@@ -54,6 +63,8 @@ const {
|
|
|
54
63
|
showSearch = true,
|
|
55
64
|
showLegend = true,
|
|
56
65
|
zoomOnScroll = false,
|
|
66
|
+
portalId,
|
|
67
|
+
disableMessageAnimation,
|
|
57
68
|
} = Astro.props;
|
|
58
69
|
|
|
59
70
|
let nodes = [],
|
|
@@ -69,6 +80,7 @@ const getNodesAndEdgesFunctions = {
|
|
|
69
80
|
flows: getNodesAndEdgesForFlows,
|
|
70
81
|
containers: getNodesAndEdgesForContainer,
|
|
71
82
|
'data-products': getNodesAndEdgesForDataProduct,
|
|
83
|
+
systems: getNodesAndEdgesForSystem,
|
|
72
84
|
};
|
|
73
85
|
|
|
74
86
|
let links: { label: string; url: string }[] = [];
|
|
@@ -81,6 +93,8 @@ if (collection in getNodesAndEdgesFunctions) {
|
|
|
81
93
|
version,
|
|
82
94
|
mode,
|
|
83
95
|
channelRenderMode: config.visualiser?.channels?.renderMode === 'single' ? 'single' : 'flat',
|
|
96
|
+
// The standalone System Diagram wraps the system's nodes in one parent boundary node.
|
|
97
|
+
wrapInSystemGroup: collection === 'systems',
|
|
84
98
|
});
|
|
85
99
|
|
|
86
100
|
nodes = fetchedNodes;
|
|
@@ -111,8 +125,8 @@ if (collection in getNodesAndEdgesFunctions) {
|
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
127
|
|
|
114
|
-
if (collection === '
|
|
115
|
-
const { nodes: fetchedNodes, edges: fetchedEdges } = await
|
|
128
|
+
if (collection === 'system-context-map') {
|
|
129
|
+
const { nodes: fetchedNodes, edges: fetchedEdges } = await getNodesAndEdgesForSystemContextMap({ mode });
|
|
116
130
|
nodes = fetchedNodes;
|
|
117
131
|
edges = fetchedEdges;
|
|
118
132
|
}
|
|
@@ -123,6 +137,26 @@ if (collection === 'domains-canvas') {
|
|
|
123
137
|
edges = fetchedEdges;
|
|
124
138
|
}
|
|
125
139
|
|
|
140
|
+
if (collection === 'systems-context') {
|
|
141
|
+
const { nodes: fetchedNodes, edges: fetchedEdges } = await getNodesAndEdgesForSystemContext({
|
|
142
|
+
id,
|
|
143
|
+
version,
|
|
144
|
+
mode,
|
|
145
|
+
});
|
|
146
|
+
nodes = fetchedNodes;
|
|
147
|
+
edges = fetchedEdges;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (collection === 'domains-systems-context') {
|
|
151
|
+
const { nodes: fetchedNodes, edges: fetchedEdges } = await getNodesAndEdgesForDomainSystemsContext({
|
|
152
|
+
id,
|
|
153
|
+
version,
|
|
154
|
+
mode,
|
|
155
|
+
});
|
|
156
|
+
nodes = fetchedNodes;
|
|
157
|
+
edges = fetchedEdges;
|
|
158
|
+
}
|
|
159
|
+
|
|
126
160
|
if (collection === 'domains-entities') {
|
|
127
161
|
const { nodes: fetchedNodes, edges: fetchedEdges } = await getNodesAndEdgesForDomainEntityMap({
|
|
128
162
|
id,
|
|
@@ -179,6 +213,8 @@ const nodesWithLayout = applyLayoutToNodes(nodes as any[], savedLayout);
|
|
|
179
213
|
maxTextSize={config.mermaid?.maxTextSize}
|
|
180
214
|
isDevMode={isDevMode()}
|
|
181
215
|
resourceKey={resourceKey}
|
|
216
|
+
portalId={portalId}
|
|
217
|
+
disableMessageAnimation={disableMessageAnimation ?? collection === 'systems-context'}
|
|
182
218
|
/>
|
|
183
219
|
</div>
|
|
184
220
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { ChevronDown } from 'lucide-react';
|
|
2
3
|
import { LUCIDE_ICON_MAP } from '@utils/icon-map';
|
|
3
4
|
|
|
4
5
|
type ActionType = 'copy' | 'cursor';
|
|
@@ -37,6 +38,7 @@ const promptText = (slotHtml ?? '')
|
|
|
37
38
|
.trim();
|
|
38
39
|
|
|
39
40
|
const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(promptText)}`;
|
|
41
|
+
const promptBodyId = `ec-prompt-body-${Math.random().toString(36).slice(2)}`;
|
|
40
42
|
---
|
|
41
43
|
|
|
42
44
|
<ec-prompt
|
|
@@ -49,6 +51,20 @@ const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(prom
|
|
|
49
51
|
<div class="text-sm font-medium text-[rgb(var(--ec-page-text))] leading-snug">{description}</div>
|
|
50
52
|
</div>
|
|
51
53
|
<div class="flex items-center gap-1.5 shrink-0">
|
|
54
|
+
<button
|
|
55
|
+
type="button"
|
|
56
|
+
data-prompt-toggle
|
|
57
|
+
aria-expanded="false"
|
|
58
|
+
aria-controls={promptBodyId}
|
|
59
|
+
class="inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded-md border transition-all duration-150 border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))]"
|
|
60
|
+
>
|
|
61
|
+
<span data-prompt-toggle-text>Show prompt</span>
|
|
62
|
+
<ChevronDown
|
|
63
|
+
className="w-3.5 h-3.5 shrink-0 transition-transform duration-150 data-[expanded=true]:rotate-180"
|
|
64
|
+
data-prompt-toggle-icon
|
|
65
|
+
data-expanded="false"
|
|
66
|
+
/>
|
|
67
|
+
</button>
|
|
52
68
|
{
|
|
53
69
|
showCopy && (
|
|
54
70
|
<button
|
|
@@ -123,6 +139,15 @@ const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(prom
|
|
|
123
139
|
}
|
|
124
140
|
</div>
|
|
125
141
|
</div>
|
|
142
|
+
<div
|
|
143
|
+
id={promptBodyId}
|
|
144
|
+
data-prompt-body
|
|
145
|
+
hidden
|
|
146
|
+
class="border-t border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))]/70"
|
|
147
|
+
>
|
|
148
|
+
<pre
|
|
149
|
+
class="m-0 max-h-96 overflow-auto whitespace-pre-wrap break-words px-4 py-3 text-sm leading-6 text-[rgb(var(--ec-page-text))]"><code>{promptText}</code></pre>
|
|
150
|
+
</div>
|
|
126
151
|
<div hidden><slot /></div>
|
|
127
152
|
</ec-prompt>
|
|
128
153
|
|
|
@@ -130,16 +155,28 @@ const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(prom
|
|
|
130
155
|
if (!customElements.get('ec-prompt')) {
|
|
131
156
|
class ECPromptElement extends HTMLElement {
|
|
132
157
|
private resetTimer: number | null = null;
|
|
133
|
-
private
|
|
158
|
+
private copyButton: HTMLButtonElement | null = null;
|
|
159
|
+
private toggleButton: HTMLButtonElement | null = null;
|
|
160
|
+
private promptBody: HTMLElement | null = null;
|
|
161
|
+
private toggleText: HTMLElement | null = null;
|
|
162
|
+
private toggleIcon: HTMLElement | null = null;
|
|
134
163
|
private boundHandler = this.handleCopy.bind(this);
|
|
164
|
+
private boundToggleHandler = this.handleToggle.bind(this);
|
|
135
165
|
|
|
136
166
|
connectedCallback() {
|
|
137
|
-
this.
|
|
138
|
-
this.
|
|
167
|
+
this.copyButton = this.querySelector<HTMLButtonElement>('[data-prompt-copy]');
|
|
168
|
+
this.toggleButton = this.querySelector<HTMLButtonElement>('[data-prompt-toggle]');
|
|
169
|
+
this.promptBody = this.querySelector<HTMLElement>('[data-prompt-body]');
|
|
170
|
+
this.toggleText = this.querySelector<HTMLElement>('[data-prompt-toggle-text]');
|
|
171
|
+
this.toggleIcon = this.querySelector<HTMLElement>('[data-prompt-toggle-icon]');
|
|
172
|
+
|
|
173
|
+
this.copyButton?.addEventListener('click', this.boundHandler);
|
|
174
|
+
this.toggleButton?.addEventListener('click', this.boundToggleHandler);
|
|
139
175
|
}
|
|
140
176
|
|
|
141
177
|
disconnectedCallback() {
|
|
142
|
-
this.
|
|
178
|
+
this.copyButton?.removeEventListener('click', this.boundHandler);
|
|
179
|
+
this.toggleButton?.removeEventListener('click', this.boundToggleHandler);
|
|
143
180
|
if (this.resetTimer != null) {
|
|
144
181
|
window.clearTimeout(this.resetTimer);
|
|
145
182
|
this.resetTimer = null;
|
|
@@ -158,12 +195,28 @@ const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(prom
|
|
|
158
195
|
this.resetTimer = window.setTimeout(() => this.setCopied(false), 1500);
|
|
159
196
|
}
|
|
160
197
|
|
|
198
|
+
private handleToggle() {
|
|
199
|
+
if (!this.promptBody || !this.toggleButton) return;
|
|
200
|
+
|
|
201
|
+
const expanded = this.toggleButton.getAttribute('aria-expanded') === 'true';
|
|
202
|
+
this.setExpanded(!expanded);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private setExpanded(expanded: boolean) {
|
|
206
|
+
if (!this.promptBody || !this.toggleButton) return;
|
|
207
|
+
|
|
208
|
+
this.promptBody.hidden = !expanded;
|
|
209
|
+
this.toggleButton.setAttribute('aria-expanded', expanded ? 'true' : 'false');
|
|
210
|
+
if (this.toggleText) this.toggleText.textContent = expanded ? 'Hide prompt' : 'Show prompt';
|
|
211
|
+
if (this.toggleIcon) this.toggleIcon.dataset.expanded = expanded ? 'true' : 'false';
|
|
212
|
+
}
|
|
213
|
+
|
|
161
214
|
private setCopied(copied: boolean) {
|
|
162
|
-
if (!this.
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
165
|
-
const idle = this.
|
|
166
|
-
const done = this.
|
|
215
|
+
if (!this.copyButton) return;
|
|
216
|
+
this.copyButton.dataset.copied = copied ? 'true' : 'false';
|
|
217
|
+
this.copyButton.setAttribute('aria-label', copied ? 'Copied to clipboard' : 'Copy prompt');
|
|
218
|
+
const idle = this.copyButton.querySelector<HTMLElement>('[data-prompt-copy-idle]');
|
|
219
|
+
const done = this.copyButton.querySelector<HTMLElement>('[data-prompt-copy-done]');
|
|
167
220
|
if (idle) idle.style.display = copied ? 'none' : '';
|
|
168
221
|
if (done) done.style.display = copied ? '' : 'none';
|
|
169
222
|
}
|
|
@@ -30,9 +30,11 @@ interface Props {
|
|
|
30
30
|
| 'channel'
|
|
31
31
|
| 'diagram'
|
|
32
32
|
| 'container'
|
|
33
|
+
| 'system'
|
|
33
34
|
| 'user'
|
|
34
35
|
| 'team'
|
|
35
36
|
| 'doc'
|
|
37
|
+
| 'adr'
|
|
36
38
|
| 'data-product';
|
|
37
39
|
version?: string;
|
|
38
40
|
}
|
|
@@ -72,9 +74,11 @@ const typeLabels: Record<string, string> = {
|
|
|
72
74
|
channel: 'Channel',
|
|
73
75
|
diagram: 'Diagram',
|
|
74
76
|
container: 'Container',
|
|
77
|
+
system: 'System',
|
|
75
78
|
user: 'User',
|
|
76
79
|
team: 'Team',
|
|
77
80
|
doc: 'Custom Doc',
|
|
81
|
+
adr: 'Decision Record',
|
|
78
82
|
'data-product': 'Data Product',
|
|
79
83
|
};
|
|
80
84
|
|
|
@@ -106,6 +110,9 @@ const typeIcons: Record<string, string> = {
|
|
|
106
110
|
doc: '<path stroke-linecap="round" stroke-linejoin="round" d="M14 2v4a2 2 0 002 2h4" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7z" /><path stroke-linecap="round" stroke-linejoin="round" d="M10 9H8" /><path stroke-linecap="round" stroke-linejoin="round" d="M16 13H8" /><path stroke-linecap="round" stroke-linejoin="round" d="M16 17H8" />', // FileText
|
|
107
111
|
'data-product':
|
|
108
112
|
'<path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25M21 7.5v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />', // Cube
|
|
113
|
+
system:
|
|
114
|
+
'<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 7.125C2.25 6.504 2.754 6 3.375 6h6c.621 0 1.125.504 1.125 1.125v3.75c0 .621-.504 1.125-1.125 1.125h-6a1.125 1.125 0 01-1.125-1.125v-3.75zM14.25 8.625c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125v8.25c0 .621-.504 1.125-1.125 1.125h-5.25a1.125 1.125 0 01-1.125-1.125v-8.25zM3.75 16.125c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125v2.25c0 .621-.504 1.125-1.125 1.125h-5.25a1.125 1.125 0 01-1.125-1.125v-2.25z" />', // Group (systems)
|
|
115
|
+
adr: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /><path stroke-linecap="round" stroke-linejoin="round" d="M9 7h2" />', // ClipboardList-ish (ADR)
|
|
109
116
|
};
|
|
110
117
|
|
|
111
118
|
const label = typeLabels[type] || typeLabels.entity;
|
|
@@ -176,7 +183,7 @@ const truncatedSummary = summary.length > maxSummaryLength ? summary.slice(0, ma
|
|
|
176
183
|
const isVersionedResource = type !== 'doc';
|
|
177
184
|
|
|
178
185
|
// Only these types have visualizers
|
|
179
|
-
const hasVisualizer = ['agent', 'domain', 'service', 'event', 'query', 'command', 'container'].includes(type);
|
|
186
|
+
const hasVisualizer = ['agent', 'domain', 'service', 'event', 'query', 'command', 'container', 'system'].includes(type);
|
|
180
187
|
|
|
181
188
|
// Check deprecation status
|
|
182
189
|
const deprecation = resource ? getDeprecatedDetails(resource) : null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder div the global System Context Map graph is portaled into.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors NodeGraphPortal, but uses a fixed `system-context-map-portal` id so the
|
|
5
|
+
* homepage (and any other page) can embed the global system context map without an
|
|
6
|
+
* id/version. The matching <NodeGraph collection="system-context-map" /> renders the
|
|
7
|
+
* graph into this portal.
|
|
8
|
+
*/
|
|
9
|
+
const SystemContextMapPortal = (props: any) => {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className="not-prose my-6 mb-12 w-full relative border! border-[rgb(var(--ec-page-border))]! rounded-md overflow-hidden"
|
|
13
|
+
id="system-context-map-portal"
|
|
14
|
+
style={{
|
|
15
|
+
height: props.height ? `${props.height}em` : '36em',
|
|
16
|
+
maxHeight: props.maxHeight ? `${props.maxHeight}em` : '36em',
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default SystemContextMapPortal;
|
|
@@ -17,6 +17,7 @@ import ChannelInformation from '@components/MDX/ChannelInformation/ChannelInform
|
|
|
17
17
|
import Attachments from '@components/MDX/Attachments.astro';
|
|
18
18
|
import AgentTools from '@components/MDX/AgentTools/AgentTools.astro';
|
|
19
19
|
import MessageTable from '@components/MDX/MessageTable/MessageTable.astro';
|
|
20
|
+
import ADRTable from '@components/MDX/ADRTable/ADRTable.astro';
|
|
20
21
|
import ResourceGroupTable from '@components/MDX/ResourceGroupTable/ResourceGroupTable.astro';
|
|
21
22
|
import EntityPropertiesTable from '@components/MDX/EntityPropertiesTable/EntityPropertiesTable.astro';
|
|
22
23
|
import Tabs from '@components/MDX/Tabs/Tabs.astro';
|
|
@@ -34,6 +35,8 @@ import MermaidFileLoader from '@components/MDX/MermaidFileLoader/MermaidFileLoad
|
|
|
34
35
|
import LikeC4View from '@components/MDX/LikeC4View/LikeC4View.astro';
|
|
35
36
|
// Portals: required for server/client components
|
|
36
37
|
import NodeGraphPortal from '@components/MDX/NodeGraph/NodeGraphPortal';
|
|
38
|
+
import ContextDiagramPortal from '@components/MDX/ContextDiagram/ContextDiagramPortal';
|
|
39
|
+
import SystemContextMapPortal from '@components/MDX/SystemContextMap/SystemContextMapPortal';
|
|
37
40
|
import SchemaViewerPortal from '@components/MDX/SchemaViewer/SchemaViewerPortal';
|
|
38
41
|
import { jsx } from 'astro/jsx-runtime';
|
|
39
42
|
import RemoteSchema from '@components/MDX/RemoteSchema.astro';
|
|
@@ -54,8 +57,12 @@ const components = (props: any) => {
|
|
|
54
57
|
Flow,
|
|
55
58
|
Link: (mdxProp: any) => jsx(Link, { ...props, ...mdxProp }),
|
|
56
59
|
MessageTable: (mdxProp: any) => jsx(MessageTable, { ...props, ...mdxProp }),
|
|
60
|
+
ADRTable: (mdxProp: any) => jsx(ADRTable, { ...props, ...mdxProp }),
|
|
57
61
|
EntityPropertiesTable: (mdxProp: any) => jsx(EntityPropertiesTable, { ...props, ...mdxProp }),
|
|
58
62
|
NodeGraph: (mdxProp: any) => jsx(NodeGraphPortal, { ...props.data, ...mdxProp, props, mdxProp }),
|
|
63
|
+
ComponentDiagram: (mdxProp: any) => jsx(NodeGraphPortal, { ...props.data, ...mdxProp, props, mdxProp }),
|
|
64
|
+
ContextDiagram: (mdxProp: any) => jsx(ContextDiagramPortal, { ...props.data, ...mdxProp, props, mdxProp }),
|
|
65
|
+
SystemContextMap: (mdxProp: any) => jsx(SystemContextMapPortal, { ...mdxProp }),
|
|
59
66
|
EntityMap: (mdxProp: any) => jsx(EntityMap, { ...props, ...mdxProp }),
|
|
60
67
|
OpenAPI,
|
|
61
68
|
Prompt: (mdxProp: any) => jsx(Prompt, { ...props, ...mdxProp }),
|
|
@@ -422,7 +422,7 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
422
422
|
)}
|
|
423
423
|
</div>
|
|
424
424
|
|
|
425
|
-
{showFormatFilters && (
|
|
425
|
+
{showFormatFilters && latestMessages.length > 0 && (
|
|
426
426
|
<div className="flex-shrink-0 border-b border-[rgb(var(--ec-page-border))] px-4 py-3">
|
|
427
427
|
<div className="rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.45)] p-3">
|
|
428
428
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
4
4
|
import * as LucideIcons from 'lucide-react';
|
|
5
|
-
import { ChevronRight, ChevronLeft, ChevronDown, Home, Star
|
|
5
|
+
import { ChevronRight, ChevronLeft, ChevronDown, Home, Star } from 'lucide-react';
|
|
6
6
|
import type { NavNode, ChildRef } from '@stores/sidebar-store/state';
|
|
7
7
|
import { saveState, loadState, saveCollapsedSections, loadCollapsedSections } from './storage';
|
|
8
8
|
import { useStore } from '@nanostores/react';
|
|
@@ -218,6 +218,12 @@ export default function NestedSideBar() {
|
|
|
218
218
|
{ pattern: /^\/docs\/domains\/([^/]+)\/([^/]+)/, type: 'domain' },
|
|
219
219
|
{ pattern: /^\/visualiser\/domains\/([^/]+)\/([^/]+)/, type: 'domain' },
|
|
220
220
|
{ pattern: /^\/architecture\/domains\/([^/]+)\/([^/]+)/, type: 'domain' },
|
|
221
|
+
// Systems (key prefix is `system`, url segment is `systems`).
|
|
222
|
+
// The visualiser pattern also matches the System Diagram
|
|
223
|
+
// (/visualiser/systems/:id/:version/context) since it is not end-anchored.
|
|
224
|
+
{ pattern: /^\/docs\/systems\/([^/]+)\/([^/]+)/, type: 'system' },
|
|
225
|
+
{ pattern: /^\/visualiser\/systems\/([^/]+)\/([^/]+)/, type: 'system' },
|
|
226
|
+
{ pattern: /^\/architecture\/systems\/([^/]+)\/([^/]+)/, type: 'system' },
|
|
221
227
|
// Agents
|
|
222
228
|
{ pattern: /^\/docs\/agents\/([^/]+)\/([^/]+)/, type: 'agent' },
|
|
223
229
|
{ pattern: /^\/visualiser\/agents\/([^/]+)\/([^/]+)/, type: 'agent' },
|
|
@@ -584,6 +590,19 @@ export default function NestedSideBar() {
|
|
|
584
590
|
});
|
|
585
591
|
};
|
|
586
592
|
|
|
593
|
+
/**
|
|
594
|
+
* Count entries that actually resolve to a visible node. Some refs (e.g. unresolved
|
|
595
|
+
* `list:` aliases on an empty catalog) sit in `entries` but render nothing — those
|
|
596
|
+
* must not count, otherwise the empty state is suppressed and the rail looks blank.
|
|
597
|
+
* Mirrors the filtering in `renderEntries`.
|
|
598
|
+
*/
|
|
599
|
+
const hasVisibleEntries = currentLevel.entries.some((ref) => {
|
|
600
|
+
const node = resolveRef(ref);
|
|
601
|
+
if (!isVisible(node)) return false;
|
|
602
|
+
if (isGroup(node!)) return hasVisibleChildren(node!);
|
|
603
|
+
return true;
|
|
604
|
+
});
|
|
605
|
+
|
|
587
606
|
/**
|
|
588
607
|
* Handle drilling down into an item with children
|
|
589
608
|
*/
|
|
@@ -734,37 +753,37 @@ export default function NestedSideBar() {
|
|
|
734
753
|
const child = resolveRef(childRef);
|
|
735
754
|
return child && isVisible(child);
|
|
736
755
|
}) ?? [];
|
|
737
|
-
const shouldFlattenSubtleChildren =
|
|
738
|
-
!isSubtleGroup &&
|
|
739
|
-
visibleChildren.length > 0 &&
|
|
740
|
-
visibleChildren.every((childRef) => {
|
|
741
|
-
const child = resolveRef(childRef);
|
|
742
|
-
return !!child && isGroup(child) && child.subtle === true;
|
|
743
|
-
});
|
|
744
756
|
|
|
745
757
|
const groupId = groupKey || `group-${index}`;
|
|
746
758
|
const canCollapse = visibleChildren.length > 3;
|
|
747
759
|
const isCollapsed = collapsedSections.has(groupId);
|
|
748
760
|
|
|
761
|
+
// When a group's children are subtle subgroups (e.g. Resources > Services/Flows/Data Stores),
|
|
762
|
+
// they render flush under the parent icon instead of inside the indented border guide.
|
|
763
|
+
const hasSubtleChildren = visibleChildren.some((childRef) => {
|
|
764
|
+
const child = resolveRef(childRef);
|
|
765
|
+
return child && isGroup(child) && child.subtle === true;
|
|
766
|
+
});
|
|
767
|
+
|
|
749
768
|
const headerContent = (
|
|
750
769
|
<>
|
|
751
770
|
<div className="flex items-center gap-2">
|
|
752
771
|
{GroupIcon && (
|
|
753
772
|
<span
|
|
754
773
|
className={cn(
|
|
755
|
-
'flex items-center justify-center',
|
|
774
|
+
'flex items-center justify-center w-5 h-5 rounded',
|
|
756
775
|
isSubtleGroup
|
|
757
|
-
? '
|
|
758
|
-
: '
|
|
776
|
+
? 'bg-[rgb(var(--ec-content-hover))] text-[rgb(var(--ec-content-text-muted))]'
|
|
777
|
+
: 'bg-[rgb(var(--ec-group-icon-bg))] text-[rgb(var(--ec-group-icon-text))]'
|
|
759
778
|
)}
|
|
760
779
|
>
|
|
761
|
-
<GroupIcon className=
|
|
780
|
+
<GroupIcon className="w-3 h-3" />
|
|
762
781
|
</span>
|
|
763
782
|
)}
|
|
764
783
|
<span
|
|
765
784
|
className={cn(
|
|
766
785
|
isSubtleGroup
|
|
767
|
-
? 'text-[
|
|
786
|
+
? 'text-[9px] font-semibold uppercase tracking-[0.1em] text-[rgb(var(--ec-content-text-muted))]'
|
|
768
787
|
: 'text-[12px] font-semibold tracking-tight text-[rgb(var(--ec-content-text))]'
|
|
769
788
|
)}
|
|
770
789
|
>
|
|
@@ -791,14 +810,14 @@ export default function NestedSideBar() {
|
|
|
791
810
|
className={cn(
|
|
792
811
|
'flex items-center justify-between w-full rounded-md transition-colors cursor-pointer',
|
|
793
812
|
isSubtleGroup
|
|
794
|
-
? 'px-
|
|
813
|
+
? 'px-2 py-1 hover:bg-[rgb(var(--ec-content-hover))]/60'
|
|
795
814
|
: 'px-2 py-1.5 hover:bg-[rgb(var(--ec-content-hover))]'
|
|
796
815
|
)}
|
|
797
816
|
>
|
|
798
817
|
{headerContent}
|
|
799
818
|
</button>
|
|
800
819
|
) : (
|
|
801
|
-
<div className={cn('flex items-center justify-between', isSubtleGroup ? 'px-
|
|
820
|
+
<div className={cn('flex items-center justify-between', isSubtleGroup ? 'px-2 py-1' : 'px-2 py-1.5')}>
|
|
802
821
|
{headerContent}
|
|
803
822
|
</div>
|
|
804
823
|
)}
|
|
@@ -806,7 +825,7 @@ export default function NestedSideBar() {
|
|
|
806
825
|
<div
|
|
807
826
|
className={cn(
|
|
808
827
|
'flex flex-col gap-0.5 border-[rgb(var(--ec-content-border))]',
|
|
809
|
-
isSubtleGroup ? 'mt-
|
|
828
|
+
isSubtleGroup ? 'border-l ml-4 mt-1' : hasSubtleChildren ? 'mt-1' : 'border-l ml-4 mt-1'
|
|
810
829
|
)}
|
|
811
830
|
>
|
|
812
831
|
{visibleChildren.map((childRef, childIndex) => {
|
|
@@ -822,19 +841,16 @@ export default function NestedSideBar() {
|
|
|
822
841
|
return (
|
|
823
842
|
<div
|
|
824
843
|
key={`nested-group-${childKey || childIndex}`}
|
|
825
|
-
className={cn(
|
|
826
|
-
child.subtle
|
|
827
|
-
? shouldFlattenSubtleChildren
|
|
828
|
-
? 'ml-5 mt-0.5'
|
|
829
|
-
: 'ml-1.5 mt-1 pl-1.5'
|
|
830
|
-
: 'ml-3 mt-1.5 pl-3 border-l border-[rgb(var(--ec-content-border))]'
|
|
831
|
-
)}
|
|
844
|
+
className={cn(child.subtle ? 'mt-1' : 'ml-3 mt-1.5 pl-3 border-l border-[rgb(var(--ec-content-border))]')}
|
|
832
845
|
>
|
|
833
846
|
{renderGroup(child, childKey, childIndex)}
|
|
834
847
|
</div>
|
|
835
848
|
);
|
|
836
849
|
}
|
|
837
|
-
|
|
850
|
+
// Inside a subtle subgroup (e.g. a domain's Resources > Services list) the
|
|
851
|
+
// section header already conveys the resource type, so suppress the default
|
|
852
|
+
// per-item icon and only keep a custom icon if one is defined.
|
|
853
|
+
return renderItem(child, childKey, childIndex, isSubtleGroup);
|
|
838
854
|
})}
|
|
839
855
|
</div>
|
|
840
856
|
)}
|
|
@@ -845,14 +861,22 @@ export default function NestedSideBar() {
|
|
|
845
861
|
/**
|
|
846
862
|
* Render a single item
|
|
847
863
|
*/
|
|
848
|
-
const renderItem = (item: NavNode, itemKey: string | null, index: number) => {
|
|
864
|
+
const renderItem = (item: NavNode, itemKey: string | null, index: number, suppressDefaultIcon = false) => {
|
|
849
865
|
const itemHasChildren = hasChildren(item);
|
|
850
866
|
const isActive = urlsMatch(item.href, currentPath) || (itemKey !== null && itemKey === activeNodeKey);
|
|
851
867
|
const isFav = isFavorited(itemKey);
|
|
852
868
|
const canFavorite = itemKey !== null; // Only items with keys can be favorited
|
|
853
869
|
|
|
854
|
-
// Get icon component from lucide-react
|
|
855
|
-
|
|
870
|
+
// Get icon component from lucide-react. When suppressDefaultIcon is set (e.g. items
|
|
871
|
+
// listed under a typed subtle subgroup) the default per-collection glyph is hidden;
|
|
872
|
+
// a custom icon (item.leftIcon) is always still shown.
|
|
873
|
+
const IconComponent =
|
|
874
|
+
item.icon && !suppressDefaultIcon ? (LucideIcons as unknown as Record<string, LucideIcons.LucideIcon>)[item.icon] : null;
|
|
875
|
+
// Some glyphs fill their box more than others, so they read larger at the shared
|
|
876
|
+
// item size. Render these ~25% smaller (matching the ADR icon) to visually balance:
|
|
877
|
+
// ClipboardList (ADRs) and the message glyphs (events/commands/queries).
|
|
878
|
+
const smallerIcons = ['ClipboardList', 'Zap', 'MessageSquare', 'Search', 'Mail'];
|
|
879
|
+
const iconSizeClass = item.icon && smallerIcons.includes(item.icon) ? 'w-3 h-3' : 'w-4 h-4';
|
|
856
880
|
|
|
857
881
|
const handleStarClick = (e: React.MouseEvent) => {
|
|
858
882
|
e.preventDefault();
|
|
@@ -870,7 +894,7 @@ export default function NestedSideBar() {
|
|
|
870
894
|
isActive ? 'text-[rgb(var(--ec-accent-text))]' : 'text-[rgb(var(--ec-content-text-muted))]'
|
|
871
895
|
)}
|
|
872
896
|
>
|
|
873
|
-
<IconComponent className=
|
|
897
|
+
<IconComponent className={iconSizeClass} />
|
|
874
898
|
</span>
|
|
875
899
|
)}
|
|
876
900
|
{item.leftIcon && <img src={resolveIconUrl(item.leftIcon)} alt="" loading="lazy" className="w-4 h-4 flex-shrink-0" />}
|
|
@@ -1183,19 +1207,25 @@ export default function NestedSideBar() {
|
|
|
1183
1207
|
)}
|
|
1184
1208
|
|
|
1185
1209
|
{/* Empty State */}
|
|
1186
|
-
{
|
|
1187
|
-
<div className="flex flex-col items-center justify-center
|
|
1188
|
-
<
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1210
|
+
{!hasVisibleEntries && favorites.length === 0 && (
|
|
1211
|
+
<div className="flex min-h-full flex-col items-center justify-center p-8 text-center">
|
|
1212
|
+
<h3 className="mb-1 text-sm font-semibold text-[rgb(var(--ec-page-text))]">Your catalog is empty</h3>
|
|
1213
|
+
<p className="max-w-[220px] text-sm font-light leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
1214
|
+
Navigation will appear here when you add resources.{' '}
|
|
1215
|
+
<a
|
|
1216
|
+
href="https://www.eventcatalog.dev/docs/tutorial/install-eventcatalog"
|
|
1217
|
+
target="_blank"
|
|
1218
|
+
rel="noopener noreferrer"
|
|
1219
|
+
className="font-medium text-[rgb(var(--ec-accent))] hover:underline"
|
|
1220
|
+
>
|
|
1221
|
+
Add your first resource
|
|
1222
|
+
</a>
|
|
1223
|
+
.
|
|
1194
1224
|
</p>
|
|
1195
1225
|
</div>
|
|
1196
1226
|
)}
|
|
1197
1227
|
|
|
1198
|
-
{
|
|
1228
|
+
{hasVisibleEntries && renderEntries(currentLevel.entries)}
|
|
1199
1229
|
</nav>
|
|
1200
1230
|
|
|
1201
1231
|
{/* Animation keyframes */}
|