@eventcatalog/core 5.0.0-beta.3 → 5.0.0-beta.31
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/LICENSE +234 -134
- package/README.md +5 -5
- package/dist/analytics/analytics.cjs +18 -3
- package/dist/analytics/analytics.d.cts +1 -1
- package/dist/analytics/analytics.d.ts +1 -1
- package/dist/analytics/analytics.js +3 -2
- package/dist/analytics/log-build.cjs +160 -77
- package/dist/analytics/log-build.d.cts +2 -2
- package/dist/analytics/log-build.d.ts +2 -2
- package/dist/analytics/log-build.js +7 -5
- package/dist/analytics/studio-usage.cjs +90 -0
- package/dist/analytics/studio-usage.d.cts +5 -0
- package/dist/analytics/studio-usage.d.ts +5 -0
- package/dist/analytics/studio-usage.js +10 -0
- package/dist/analytics/telemetry.cjs +42 -0
- package/dist/analytics/telemetry.d.cts +20 -0
- package/dist/analytics/telemetry.d.ts +20 -0
- package/dist/analytics/telemetry.js +8 -0
- package/dist/catalog-runtime.cjs +1 -1
- package/dist/{chunk-BH2F5WPN.js → chunk-2UCCTEIH.js} +1 -1
- package/dist/{chunk-RFIXKATC.js → chunk-4G7FSRPN.js} +35 -42
- package/dist/{chunk-TQLRG35T.js → chunk-AD7CL772.js} +78 -45
- package/dist/{chunk-NDJOAITI.js → chunk-BNSLGNQI.js} +9 -3
- package/dist/chunk-CA6WCQ2T.js +54 -0
- package/dist/chunk-CPW6G62V.js +17 -0
- package/dist/{chunk-MDWB5HLO.js → chunk-NKNOXQ62.js} +1 -1
- package/dist/{chunk-423S2KHN.js → chunk-OUEGYMBA.js} +4 -2
- package/dist/{chunk-3PKS2IIP.js → chunk-OX6TSVHY.js} +1 -1
- package/dist/{chunk-36RYTYT5.js → chunk-PD7KTSYN.js} +1 -1
- package/dist/chunk-S5GWAUG5.js +29 -0
- package/dist/{chunk-GYIVJXOJ.js → chunk-WADZVNCA.js} +1 -1
- package/dist/{chunk-6OC46WQJ.js → chunk-XRFL642Z.js} +66 -35
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog-config-file-utils.cjs +34 -41
- package/dist/eventcatalog-config-file-utils.d.cts +56 -58
- package/dist/eventcatalog-config-file-utils.d.ts +56 -58
- package/dist/eventcatalog-config-file-utils.js +1 -1
- package/dist/eventcatalog.cjs +531 -356
- package/dist/eventcatalog.config.d.cts +59 -1
- package/dist/eventcatalog.config.d.ts +59 -1
- package/dist/eventcatalog.js +63 -25
- package/dist/features.cjs +34 -41
- package/dist/features.js +2 -2
- package/dist/federation/federate.cjs +37 -44
- package/dist/federation/federate.js +2 -2
- package/dist/generate.cjs +37 -42
- package/dist/generate.js +4 -4
- package/dist/resolve-catalog-dependencies.cjs +34 -41
- package/dist/resolve-catalog-dependencies.js +2 -2
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio-fonts.css.mjs +3 -0
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.css.mjs +3 -0
- package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.mjs +3 -0
- package/dist/runtime-dependencies/@hocuspocus__provider.mjs +3 -0
- package/dist/runtime-dependencies/@hocuspocus__server.mjs +3 -0
- package/dist/runtime-dependencies/@mcp-b__webmcp-local-relay.mjs +3 -0
- package/dist/runtime-dependencies/@mcp-b__webmcp-polyfill.mjs +3 -0
- package/dist/runtime-dependencies/htmlparser2.mjs +3 -0
- package/dist/runtime-dependencies/manifest.json +13 -1
- package/dist/runtime-dependencies/react-hotkeys-hook.mjs +3 -0
- package/dist/runtime-dependencies/react-syntax-highlighter__dist__cjs__create-element.js.mjs +3 -0
- package/dist/runtime-dependencies/y-protocols.mjs +3 -0
- package/dist/runtime-dependencies/y-protocols__awareness.mjs +3 -0
- package/dist/runtime-dependencies/yjs.mjs +3 -0
- package/dist/utils/child-process-signals.cjs +53 -0
- package/dist/utils/child-process-signals.d.cts +19 -0
- package/dist/utils/child-process-signals.d.ts +19 -0
- package/dist/utils/child-process-signals.js +6 -0
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/dist/utils/license-status.cjs +78 -45
- package/dist/utils/license-status.d.cts +15 -5
- package/dist/utils/license-status.d.ts +15 -5
- package/dist/utils/license-status.js +1 -1
- package/eventcatalog/astro.config.mjs +23 -1
- package/eventcatalog/integrations/config-loader.mjs +56 -58
- package/eventcatalog/integrations/skip-startup-reload.mjs +31 -0
- package/eventcatalog/integrations/stable-dependency-order.mjs +29 -0
- package/eventcatalog/integrations/storage.mjs +20 -0
- package/eventcatalog/integrations/studio-server.mjs +32 -0
- package/eventcatalog/src/components/CatalogGraph/CatalogForceGraph.tsx +39 -0
- package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +2 -0
- package/eventcatalog/src/components/Header.astro +3 -3
- package/eventcatalog/src/components/Homepage/CatalogDashboard.astro +342 -0
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +60 -4
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -1
- package/eventcatalog/src/components/NavigationProgress.astro +7 -0
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaCodeModal.tsx +2 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -0
- package/eventcatalog/src/components/Search/SearchDataLoader.astro +16 -28
- package/eventcatalog/src/components/Search/SearchModal.tsx +2 -10
- package/eventcatalog/src/components/Search/search-utils.ts +26 -0
- package/eventcatalog/src/components/Seo.astro +5 -1
- package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +53 -48
- package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +183 -178
- package/eventcatalog/src/components/Settings/LicenseSettings.tsx +140 -31
- package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +40 -35
- package/eventcatalog/src/components/Settings/LogoUpload.tsx +1 -1
- package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +9 -8
- package/eventcatalog/src/components/Settings/Row.tsx +7 -4
- package/eventcatalog/src/components/Settings/SettingsShared.tsx +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +53 -83
- package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +2 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +131 -0
- package/eventcatalog/src/components/SideNav/SideNav.astro +9 -1
- package/eventcatalog/src/components/TrialBadge.astro +20 -9
- package/eventcatalog/src/content.config.ts +19 -2
- package/eventcatalog/src/features/auth/error.astro +4 -2
- package/eventcatalog/src/features/auth/login.astro +2 -1
- package/eventcatalog/src/features/auth/middleware/middleware-auth.ts +10 -0
- package/eventcatalog/src/features/auth/unauthorized.astro +1 -1
- package/eventcatalog/src/features/fields/pages/fields.astro +1 -1
- package/eventcatalog/src/features/integrations/eventcatalog-features.ts +34 -1
- package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +6 -45
- package/eventcatalog/src/features/mcp/apps/canvas/shared.ts +47 -0
- package/eventcatalog/src/features/mcp/apps/canvas/styles.css +24 -0
- package/eventcatalog/src/features/mcp/apps/canvas/view.tsx +278 -0
- package/eventcatalog/src/features/mcp/apps/generated/canvas.html +272 -0
- package/eventcatalog/src/features/mcp/apps/generated/viewer.html +65 -65
- package/eventcatalog/src/features/mcp/apps/shared/app-view.tsx +2 -1
- package/eventcatalog/src/features/mcp/mcp-apps.ts +6 -3
- package/eventcatalog/src/features/mcp/mcp-server.ts +36 -5
- package/eventcatalog/src/features/server/start.ts +25 -0
- package/eventcatalog/src/features/storage/database.ts +88 -0
- package/eventcatalog/src/features/storage/migrations.ts +85 -0
- package/eventcatalog/src/features/storage/sql/database.sql +5 -0
- package/eventcatalog/src/features/storage/sql/migrations/0001-studio-canvases.sql +12 -0
- package/eventcatalog/src/features/storage/sql/migrations.sql +15 -0
- package/eventcatalog/src/features/storage/sql.ts +28 -0
- package/eventcatalog/src/features/studio/agent-choreography.ts +384 -0
- package/eventcatalog/src/features/studio/agents.ts +28 -0
- package/eventcatalog/src/features/studio/api/canvases-api.ts +219 -0
- package/eventcatalog/src/features/studio/api/canvases.ts +25 -0
- package/eventcatalog/src/features/studio/api/client.ts +40 -0
- package/eventcatalog/src/features/studio/canvas-actions.ts +540 -0
- package/eventcatalog/src/features/studio/canvas-preview.ts +52 -0
- package/eventcatalog/src/features/studio/catalog-resources.ts +155 -0
- package/eventcatalog/src/features/studio/catalog.ts +173 -0
- package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +518 -0
- package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +118 -0
- package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +434 -0
- package/eventcatalog/src/features/studio/components/ConnectionsChooser.tsx +143 -0
- package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +65 -0
- package/eventcatalog/src/features/studio/components/Dialog.tsx +60 -0
- package/eventcatalog/src/features/studio/components/JoinForm.tsx +109 -0
- package/eventcatalog/src/features/studio/components/LeftPanel.tsx +206 -0
- package/eventcatalog/src/features/studio/components/NodeDetails.tsx +183 -0
- package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +79 -0
- package/eventcatalog/src/features/studio/components/Presence.tsx +293 -0
- package/eventcatalog/src/features/studio/components/ShareDialog.tsx +396 -0
- package/eventcatalog/src/features/studio/components/ShortcutsDialog.tsx +41 -0
- package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +2091 -0
- package/eventcatalog/src/features/studio/components/StudioNotice.astro +24 -0
- package/eventcatalog/src/features/studio/document-name.ts +7 -0
- package/eventcatalog/src/features/studio/from-visualiser.ts +138 -0
- package/eventcatalog/src/features/studio/hooks/presence-sender.ts +63 -0
- package/eventcatalog/src/features/studio/hooks/presence-store.ts +119 -0
- package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +353 -0
- package/eventcatalog/src/features/studio/hooks/use-comments.ts +54 -0
- package/eventcatalog/src/features/studio/hooks/use-follow-camera.ts +109 -0
- package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +782 -0
- package/eventcatalog/src/features/studio/identity.ts +59 -0
- package/eventcatalog/src/features/studio/limits.ts +2 -0
- package/eventcatalog/src/features/studio/pages/[id].astro +69 -0
- package/eventcatalog/src/features/studio/pages/index.astro +784 -0
- package/eventcatalog/src/features/studio/pages/webmcp-relay.ts +27 -0
- package/eventcatalog/src/features/studio/server/canvas-mcp.ts +495 -0
- package/eventcatalog/src/features/studio/server/runtime.ts +498 -0
- package/eventcatalog/src/features/studio/server/sign-in.ts +18 -0
- package/eventcatalog/src/features/studio/server/sql/storage.sql +18 -0
- package/eventcatalog/src/features/studio/server/storage.ts +90 -0
- package/eventcatalog/src/features/studio/server/tool-icons.ts +30 -0
- package/eventcatalog/src/features/studio/tool-sync.ts +75 -0
- package/eventcatalog/src/layouts/BaseLayout.astro +4 -4
- package/eventcatalog/src/layouts/SettingsLayout.astro +2 -2
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +13 -5
- package/eventcatalog/src/pages/_index.astro +5 -342
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.spec.ts +2 -3
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -1
- package/eventcatalog/src/pages/diagrams/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/diagrams/[id]/[version]/embed.astro +1 -0
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/directory/[type]/_index.data.ts +5 -7
- package/eventcatalog/src/pages/directory/[type]/index.astro +3 -1
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -7
- package/eventcatalog/src/pages/discover/[type]/index.astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/_[...filename].data.ts +0 -4
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.spec.ts +2 -3
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/_[filename].data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +2 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +1 -0
- package/eventcatalog/src/pages/docs/custom/[...path]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/[version]/resources/index.astro +1 -0
- package/eventcatalog/src/pages/docs/services/[id]/asyncapi/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/changelog/index.astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/graphql/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/services/[id]/spec/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/index.astro +4 -2
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +0 -7
- package/eventcatalog/src/pages/schemas/explorer/index.astro +4 -2
- package/eventcatalog/src/pages/settings/license.astro +9 -1
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/_index.data.ts +38 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +18 -41
- package/eventcatalog/src/pages/visualiser/designs/[id]/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -1
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +0 -7
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/types/react-syntax-highlighter.d.ts +10 -0
- package/eventcatalog/src/utils/collections/util.ts +8 -4
- package/eventcatalog/src/utils/feature.ts +8 -0
- package/eventcatalog/src/utils/git.ts +22 -5
- package/eventcatalog/src/utils/homepage-dashboard.ts +143 -0
- package/eventcatalog/src/utils/license.ts +1 -1
- package/eventcatalog/src/utils/link-validation.ts +25 -19
- package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +3 -1
- package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +3 -3
- package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +0 -2
- package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +4 -2
- package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +20 -1
- package/eventcatalog/src/utils/node-graphs/node-resource.ts +67 -0
- package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +1 -1
- package/eventcatalog/src/utils/page-loaders/hybrid-page.ts +4 -15
- package/eventcatalog/src/utils/page-title.ts +15 -0
- package/eventcatalog/src/utils/syntax-highlighter-renderer.ts +64 -0
- package/eventcatalog/src/utils/trial.ts +14 -1
- package/package.json +19 -13
- package/dist/runtime-dependencies/shelljs.mjs +0 -3
- package/eventcatalog/public/studio-bg.png +0 -0
- package/eventcatalog/src/components/Studio/StudioPageModal.tsx +0 -150
- package/eventcatalog/src/pages/studio.astro +0 -316
|
@@ -94,16 +94,16 @@ const providerName = user?.provider ? providerNames[user.provider] || user.provi
|
|
|
94
94
|
<img
|
|
95
95
|
src={userImage}
|
|
96
96
|
alt=""
|
|
97
|
-
class="h-
|
|
97
|
+
class="h-7 w-7 rounded-full object-cover ring-1 ring-[rgb(var(--ec-page-border))]"
|
|
98
98
|
/>
|
|
99
99
|
) : (
|
|
100
|
-
<span class="h-
|
|
100
|
+
<span class="h-7 w-7 rounded-full bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))] ring-1 ring-[rgb(var(--ec-page-border))] flex items-center justify-center text-[11px] font-semibold">
|
|
101
101
|
{userInitials}
|
|
102
102
|
</span>
|
|
103
103
|
)}
|
|
104
104
|
<svg
|
|
105
105
|
viewBox="0 0 24 24"
|
|
106
|
-
class="h-
|
|
106
|
+
class="h-3.5 w-3.5 transition-transform group-aria-expanded:rotate-180"
|
|
107
107
|
fill="none"
|
|
108
108
|
stroke="currentColor"
|
|
109
109
|
stroke-width="2"
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
---
|
|
2
|
+
import config from '@config';
|
|
3
|
+
import { buildUrl } from '@utils/url-builder';
|
|
4
|
+
import { getColorForCollection } from '@utils/collection-colors';
|
|
5
|
+
import { isArchitectureGraphEnabled, isEventCatalogChatEnabled } from '@utils/feature';
|
|
6
|
+
import CatalogForceGraph from '@components/CatalogGraph/CatalogForceGraph';
|
|
7
|
+
import { getCatalogForceGraph, toCatalogForceGraphWire } from '@utils/node-graphs/catalog-force-graph';
|
|
8
|
+
import { getDashboard, type DashboardCollection } from '@utils/homepage-dashboard';
|
|
9
|
+
import { Boxes, Clock, FileJson, Mail, Network, Search, Server, Sparkles, Users, Waypoints } from 'lucide-react';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
/** The heading, the catalog's title by default */
|
|
13
|
+
title?: string;
|
|
14
|
+
/** Under the heading, the catalog's tagline by default */
|
|
15
|
+
description?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
title = config?.title || config?.organizationName || 'EventCatalog',
|
|
20
|
+
description = config?.tagline || 'Explore and understand your event-driven architecture.',
|
|
21
|
+
} = Astro.props;
|
|
22
|
+
|
|
23
|
+
const dashboard = await getDashboard();
|
|
24
|
+
const { counts, recentlyUpdated } = dashboard;
|
|
25
|
+
const chatEnabled = isEventCatalogChatEnabled();
|
|
26
|
+
// The architecture graph leads the dashboard; it's opt-in while in beta, and without it the dashboard shows what changed recently
|
|
27
|
+
const graph = isArchitectureGraphEnabled() ? toCatalogForceGraphWire(await getCatalogForceGraph()) : undefined;
|
|
28
|
+
|
|
29
|
+
const TYPE_LABELS: Record<DashboardCollection, string> = {
|
|
30
|
+
domains: 'Domain',
|
|
31
|
+
services: 'Service',
|
|
32
|
+
events: 'Event',
|
|
33
|
+
commands: 'Command',
|
|
34
|
+
queries: 'Query',
|
|
35
|
+
flows: 'Flow',
|
|
36
|
+
};
|
|
37
|
+
// The colour each kind of resource has across the catalog, from the theme's badge colours
|
|
38
|
+
const badgeStyle = (collection: string) => {
|
|
39
|
+
const color = getColorForCollection(collection);
|
|
40
|
+
return `color: rgb(var(--ec-badge-color-${color}-text)); background: rgb(var(--ec-badge-color-${color}-background));`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const stats = [
|
|
44
|
+
{ label: 'Domains', value: counts.domains, href: buildUrl('/discover/domains'), icon: Boxes },
|
|
45
|
+
{ label: 'Services', value: counts.services, href: buildUrl('/discover/services'), icon: Server },
|
|
46
|
+
{ label: 'Messages', value: counts.messages, href: buildUrl('/discover/events'), icon: Mail },
|
|
47
|
+
{ label: 'Flows', value: counts.flows, href: buildUrl('/discover/flows'), icon: Waypoints },
|
|
48
|
+
{ label: 'Schemas', value: counts.schemas, href: buildUrl('/schemas/explorer'), icon: FileJson },
|
|
49
|
+
{ label: 'Teams', value: counts.teams, href: buildUrl('/directory/teams'), icon: Users },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const formatDate = (timestamp: number) =>
|
|
53
|
+
new Date(timestamp).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
<div class="ec-dashboard">
|
|
57
|
+
<!-- Header -->
|
|
58
|
+
<header class="flex flex-col gap-5 lg:flex-row lg:items-end lg:justify-between">
|
|
59
|
+
<div class="min-w-0">
|
|
60
|
+
<h1 class="text-[26px] font-semibold leading-tight tracking-tight text-[rgb(var(--ec-page-text))] md:text-[30px]">
|
|
61
|
+
{title}
|
|
62
|
+
</h1>
|
|
63
|
+
<p class="mt-1.5 max-w-2xl text-[14px] leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
64
|
+
{description}
|
|
65
|
+
</p>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="flex w-full items-center gap-2 lg:w-auto">
|
|
68
|
+
<button type="button" data-dashboard-search class="ec-dashboard-search group">
|
|
69
|
+
<Search className="h-4 w-4 text-[rgb(var(--ec-page-text-muted))]" />
|
|
70
|
+
<span class="flex-1 text-left">Search the catalog</span>
|
|
71
|
+
<kbd class="ec-dashboard-kbd">⌘K</kbd>
|
|
72
|
+
</button>
|
|
73
|
+
{
|
|
74
|
+
chatEnabled && (
|
|
75
|
+
<button type="button" data-dashboard-ask class="ec-dashboard-button">
|
|
76
|
+
<Sparkles className="h-4 w-4" />
|
|
77
|
+
Ask
|
|
78
|
+
</button>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
</div>
|
|
82
|
+
</header>
|
|
83
|
+
|
|
84
|
+
<!-- Counts -->
|
|
85
|
+
<section class="ec-dashboard-stats mt-8" aria-label="Catalog at a glance">
|
|
86
|
+
{
|
|
87
|
+
stats.map((stat) => (
|
|
88
|
+
<a href={stat.href} class="ec-dashboard-card ec-dashboard-stat group">
|
|
89
|
+
<div class="flex items-center justify-between">
|
|
90
|
+
<span class="text-[12px] font-medium text-[rgb(var(--ec-page-text-muted))]">{stat.label}</span>
|
|
91
|
+
<stat.icon className="h-4 w-4 text-[rgb(var(--ec-page-text-muted))] transition-colors group-hover:text-[rgb(var(--ec-page-text))]" />
|
|
92
|
+
</div>
|
|
93
|
+
<span class="mt-2 block text-[28px] font-semibold leading-none tracking-tight tabular-nums text-[rgb(var(--ec-page-text))]">
|
|
94
|
+
{stat.value}
|
|
95
|
+
</span>
|
|
96
|
+
</a>
|
|
97
|
+
))
|
|
98
|
+
}
|
|
99
|
+
</section>
|
|
100
|
+
|
|
101
|
+
<!-- The architecture graph, or what changed recently without it -->
|
|
102
|
+
<div class="mt-6">
|
|
103
|
+
{
|
|
104
|
+
graph ? (
|
|
105
|
+
<section class="ec-dashboard-card overflow-hidden">
|
|
106
|
+
<div class="ec-dashboard-card-header">
|
|
107
|
+
<h2 class="ec-dashboard-title">
|
|
108
|
+
<Network className="h-4 w-4" /> Architecture
|
|
109
|
+
</h2>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="relative h-[34rem] border-t border-[rgb(var(--ec-page-border))]">
|
|
112
|
+
<CatalogForceGraph
|
|
113
|
+
client:only="react"
|
|
114
|
+
nodes={graph.nodes}
|
|
115
|
+
links={graph.links}
|
|
116
|
+
linkLabels={graph.linkLabels}
|
|
117
|
+
initialLens="domains"
|
|
118
|
+
showSearch
|
|
119
|
+
showLegend
|
|
120
|
+
showLensPicker
|
|
121
|
+
syncUrl={false}
|
|
122
|
+
zoomOnScroll={false}
|
|
123
|
+
openInGraphUrl={buildUrl('/visualiser/graph')}
|
|
124
|
+
openInGraphLabel="Open full screen"
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
</section>
|
|
128
|
+
) : (
|
|
129
|
+
<section class="ec-dashboard-card">
|
|
130
|
+
<div class="ec-dashboard-card-header">
|
|
131
|
+
<h2 class="ec-dashboard-title">
|
|
132
|
+
<Clock className="h-4 w-4" /> Recently updated
|
|
133
|
+
</h2>
|
|
134
|
+
</div>
|
|
135
|
+
{recentlyUpdated.length === 0 ? (
|
|
136
|
+
<p class="px-5 pb-5 text-[13px] text-[rgb(var(--ec-page-text-muted))]">Nothing to show yet.</p>
|
|
137
|
+
) : (
|
|
138
|
+
<ul class="divide-y divide-[rgb(var(--ec-page-border))]">
|
|
139
|
+
{recentlyUpdated.map((resource) => (
|
|
140
|
+
<li>
|
|
141
|
+
<a href={resource.href} class="ec-dashboard-row">
|
|
142
|
+
<span class="ec-dashboard-type" style={badgeStyle(resource.collection)}>
|
|
143
|
+
{TYPE_LABELS[resource.collection]}
|
|
144
|
+
</span>
|
|
145
|
+
<span class="min-w-0 flex-1">
|
|
146
|
+
<span class="block truncate text-[13.5px] font-medium text-[rgb(var(--ec-page-text))]">
|
|
147
|
+
{resource.name}
|
|
148
|
+
<span class="ml-1.5 font-mono text-[11.5px] font-normal text-[rgb(var(--ec-page-text-muted))]">
|
|
149
|
+
v{resource.version}
|
|
150
|
+
</span>
|
|
151
|
+
</span>
|
|
152
|
+
{resource.summary && (
|
|
153
|
+
<span class="block truncate text-[12.5px] text-[rgb(var(--ec-page-text-muted))]">{resource.summary}</span>
|
|
154
|
+
)}
|
|
155
|
+
</span>
|
|
156
|
+
{resource.owners[0] && (
|
|
157
|
+
<span class="hidden shrink-0 text-[12px] text-[rgb(var(--ec-page-text-muted))] md:block">
|
|
158
|
+
{resource.owners[0].name}
|
|
159
|
+
</span>
|
|
160
|
+
)}
|
|
161
|
+
<time
|
|
162
|
+
class="w-24 shrink-0 text-right text-[12px] tabular-nums text-[rgb(var(--ec-page-text-muted))]"
|
|
163
|
+
datetime={new Date(resource.updatedAt!).toISOString()}
|
|
164
|
+
data-relative-time
|
|
165
|
+
>
|
|
166
|
+
{formatDate(resource.updatedAt!)}
|
|
167
|
+
</time>
|
|
168
|
+
</a>
|
|
169
|
+
</li>
|
|
170
|
+
))}
|
|
171
|
+
</ul>
|
|
172
|
+
)}
|
|
173
|
+
</section>
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
|
|
179
|
+
<script>
|
|
180
|
+
// The search bar and Ask button open the catalog's search and assistant
|
|
181
|
+
const bind = () => {
|
|
182
|
+
document.querySelector('[data-dashboard-search]')?.addEventListener('click', () => {
|
|
183
|
+
(window as any).searchModalState?.open();
|
|
184
|
+
});
|
|
185
|
+
document.querySelector('[data-dashboard-ask]')?.addEventListener('click', () => {
|
|
186
|
+
window.dispatchEvent(new CustomEvent('eventcatalog:open-chat'));
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// "3 days ago", counted in the browser so a prerendered page stays current
|
|
190
|
+
const format = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });
|
|
191
|
+
const units: [Intl.RelativeTimeFormatUnit, number][] = [
|
|
192
|
+
['year', 365 * 24 * 3600],
|
|
193
|
+
['month', 30 * 24 * 3600],
|
|
194
|
+
['week', 7 * 24 * 3600],
|
|
195
|
+
['day', 24 * 3600],
|
|
196
|
+
['hour', 3600],
|
|
197
|
+
['minute', 60],
|
|
198
|
+
];
|
|
199
|
+
document.querySelectorAll<HTMLTimeElement>('time[data-relative-time]').forEach((time) => {
|
|
200
|
+
const seconds = (new Date(time.dateTime).getTime() - Date.now()) / 1000;
|
|
201
|
+
const [unit, size] = units.find(([, size]) => Math.abs(seconds) >= size) ?? ['minute', 60];
|
|
202
|
+
time.textContent = format.format(Math.round(seconds / size), unit);
|
|
203
|
+
time.title = new Date(time.dateTime).toLocaleString();
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
bind();
|
|
207
|
+
document.addEventListener('astro:page-load', bind);
|
|
208
|
+
</script>
|
|
209
|
+
|
|
210
|
+
<style is:global>
|
|
211
|
+
.ec-dashboard {
|
|
212
|
+
max-width: 96rem;
|
|
213
|
+
padding-bottom: 2.5rem;
|
|
214
|
+
}
|
|
215
|
+
.ec-dashboard-card {
|
|
216
|
+
border: 1px solid rgb(var(--ec-page-border));
|
|
217
|
+
border-radius: 0.875rem;
|
|
218
|
+
background: rgb(var(--ec-card-bg, var(--ec-page-bg)));
|
|
219
|
+
}
|
|
220
|
+
.ec-dashboard-card-header {
|
|
221
|
+
display: flex;
|
|
222
|
+
align-items: center;
|
|
223
|
+
justify-content: space-between;
|
|
224
|
+
gap: 0.75rem;
|
|
225
|
+
padding: 1rem 1.25rem 0.75rem;
|
|
226
|
+
}
|
|
227
|
+
.ec-dashboard-title {
|
|
228
|
+
display: inline-flex;
|
|
229
|
+
align-items: center;
|
|
230
|
+
gap: 0.5rem;
|
|
231
|
+
font-size: 13.5px;
|
|
232
|
+
font-weight: 600;
|
|
233
|
+
color: rgb(var(--ec-page-text));
|
|
234
|
+
}
|
|
235
|
+
.ec-dashboard-title svg {
|
|
236
|
+
color: rgb(var(--ec-page-text-muted));
|
|
237
|
+
}
|
|
238
|
+
.ec-dashboard-link {
|
|
239
|
+
display: inline-flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
gap: 0.25rem;
|
|
242
|
+
font-size: 12px;
|
|
243
|
+
font-weight: 500;
|
|
244
|
+
color: rgb(var(--ec-page-text-muted));
|
|
245
|
+
}
|
|
246
|
+
.ec-dashboard-link:hover {
|
|
247
|
+
color: rgb(var(--ec-page-text));
|
|
248
|
+
}
|
|
249
|
+
.ec-dashboard-search {
|
|
250
|
+
display: flex;
|
|
251
|
+
flex: 1;
|
|
252
|
+
align-items: center;
|
|
253
|
+
gap: 0.625rem;
|
|
254
|
+
min-width: 0;
|
|
255
|
+
height: 2.5rem;
|
|
256
|
+
padding: 0 0.75rem;
|
|
257
|
+
border: 1px solid rgb(var(--ec-page-border));
|
|
258
|
+
border-radius: 0.625rem;
|
|
259
|
+
background: rgb(var(--ec-card-bg, var(--ec-page-bg)));
|
|
260
|
+
font-size: 13px;
|
|
261
|
+
color: rgb(var(--ec-page-text-muted));
|
|
262
|
+
transition: border-color 150ms;
|
|
263
|
+
}
|
|
264
|
+
@media (min-width: 1024px) {
|
|
265
|
+
.ec-dashboard-search {
|
|
266
|
+
width: 22rem;
|
|
267
|
+
flex: none;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
.ec-dashboard-search:hover {
|
|
271
|
+
border-color: rgb(var(--ec-page-text) / 0.35);
|
|
272
|
+
}
|
|
273
|
+
.ec-dashboard-kbd {
|
|
274
|
+
border: 1px solid rgb(var(--ec-page-border));
|
|
275
|
+
border-radius: 0.375rem;
|
|
276
|
+
padding: 0.05rem 0.375rem;
|
|
277
|
+
font-family: inherit;
|
|
278
|
+
font-size: 11px;
|
|
279
|
+
}
|
|
280
|
+
.ec-dashboard-button {
|
|
281
|
+
display: inline-flex;
|
|
282
|
+
align-items: center;
|
|
283
|
+
gap: 0.375rem;
|
|
284
|
+
height: 2.5rem;
|
|
285
|
+
padding: 0 0.875rem;
|
|
286
|
+
border-radius: 0.625rem;
|
|
287
|
+
background: rgb(var(--ec-page-text));
|
|
288
|
+
font-size: 13px;
|
|
289
|
+
font-weight: 500;
|
|
290
|
+
color: rgb(var(--ec-page-bg));
|
|
291
|
+
transition: opacity 150ms;
|
|
292
|
+
}
|
|
293
|
+
.ec-dashboard-button:hover {
|
|
294
|
+
opacity: 0.85;
|
|
295
|
+
}
|
|
296
|
+
.ec-dashboard-stats {
|
|
297
|
+
display: grid;
|
|
298
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
299
|
+
gap: 0.75rem;
|
|
300
|
+
}
|
|
301
|
+
@media (min-width: 768px) {
|
|
302
|
+
.ec-dashboard-stats {
|
|
303
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
@media (min-width: 1280px) {
|
|
307
|
+
.ec-dashboard-stats {
|
|
308
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
.ec-dashboard-stat {
|
|
312
|
+
display: block;
|
|
313
|
+
padding: 1rem 1.1rem;
|
|
314
|
+
transition: border-color 150ms;
|
|
315
|
+
}
|
|
316
|
+
.ec-dashboard-stat:hover {
|
|
317
|
+
border-color: rgb(var(--ec-page-text) / 0.35);
|
|
318
|
+
}
|
|
319
|
+
.ec-dashboard-row {
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: 0.875rem;
|
|
323
|
+
padding: 0.7rem 1.25rem;
|
|
324
|
+
transition: background 150ms;
|
|
325
|
+
}
|
|
326
|
+
.ec-dashboard-row:hover {
|
|
327
|
+
background: rgb(var(--ec-page-text) / 0.03);
|
|
328
|
+
}
|
|
329
|
+
.ec-dashboard-type {
|
|
330
|
+
flex-shrink: 0;
|
|
331
|
+
width: 4.75rem;
|
|
332
|
+
border-radius: 0.375rem;
|
|
333
|
+
padding: 0.15rem 0;
|
|
334
|
+
text-align: center;
|
|
335
|
+
font-size: 11px;
|
|
336
|
+
font-weight: 600;
|
|
337
|
+
}
|
|
338
|
+
@media (min-width: 640px) {
|
|
339
|
+
}
|
|
340
|
+
@media (min-width: 1280px) {
|
|
341
|
+
}
|
|
342
|
+
</style>
|
|
@@ -12,15 +12,38 @@
|
|
|
12
12
|
* CSS ships in the page head and survives ClientRouter navigations (see NodeGraph.astro).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { useCallback, lazy, Suspense } from 'react';
|
|
15
|
+
import { useCallback, useEffect, useState, lazy, Suspense } from 'react';
|
|
16
|
+
import { createPortal } from 'react-dom';
|
|
16
17
|
import type { Node, Edge } from '@xyflow/react';
|
|
17
|
-
import type { FlowGroupBy } from '@eventcatalog/visualiser';
|
|
18
|
+
import type { FlowGroupBy, OpenInStudioRequest } from '@eventcatalog/visualiser';
|
|
18
19
|
import { buildUrl } from '@utils/url-builder';
|
|
20
|
+
import { createCanvasThroughApi } from '@features/studio/api/client';
|
|
21
|
+
import { getStoredName } from '@features/studio/identity';
|
|
22
|
+
|
|
23
|
+
// Studio's canvas code (what turns a diagram into a canvas, and the dialog asking for its name) is only loaded when a
|
|
24
|
+
// diagram is opened in Studio: every page with a diagram would load it otherwise, with Studio on or not
|
|
25
|
+
const OpenInStudioDialog = lazy(() => import('@features/studio/components/OpenInStudioDialog'));
|
|
19
26
|
|
|
20
27
|
const NodeGraph = lazy(() =>
|
|
21
28
|
import('@eventcatalog/visualiser').then((module) => ({ default: module.NodeGraph }))
|
|
22
29
|
) as React.LazyExoticComponent<React.ComponentType<AstroNodeGraphProps & Record<string, unknown>>>;
|
|
23
30
|
|
|
31
|
+
/**
|
|
32
|
+
* "Loading graph..." in the box the graph is drawn into, while the visualiser loads. Not where this island sits: the
|
|
33
|
+
* graph is portalled from there, and on the homepage that's beside the page's content (top right).
|
|
34
|
+
*/
|
|
35
|
+
const LoadingGraph = ({ portalId }: { portalId: string }) => {
|
|
36
|
+
const [container, setContainer] = useState<HTMLElement | null>(null);
|
|
37
|
+
useEffect(() => setContainer(document.getElementById(portalId)), [portalId]);
|
|
38
|
+
if (!container) return null;
|
|
39
|
+
return createPortal(
|
|
40
|
+
<div className="flex h-full min-h-[8rem] items-center justify-center text-sm text-[rgb(var(--ec-page-text-muted))]">
|
|
41
|
+
Loading graph...
|
|
42
|
+
</div>,
|
|
43
|
+
container
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
24
47
|
interface AstroNodeGraphProps {
|
|
25
48
|
id: string;
|
|
26
49
|
nodes: Node[];
|
|
@@ -57,9 +80,11 @@ interface AstroNodeGraphProps {
|
|
|
57
80
|
preferenceScope?: string;
|
|
58
81
|
// Group a flow's steps into swimlanes to start with
|
|
59
82
|
swimlanes?: FlowGroupBy;
|
|
83
|
+
// The Studio API's address, when Studio is on: the menu can then start a canvas from the diagram
|
|
84
|
+
studioApiUrl?: string;
|
|
60
85
|
}
|
|
61
86
|
|
|
62
|
-
const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: AstroNodeGraphProps) => {
|
|
87
|
+
const AstroNodeGraph = ({ isDevMode = false, resourceKey, studioApiUrl, ...otherProps }: AstroNodeGraphProps) => {
|
|
63
88
|
// Astro-specific navigation handler
|
|
64
89
|
const handleNavigate = useCallback((url: string) => {
|
|
65
90
|
// Use window.location for navigation since we can't import astro:transitions/client in a React component
|
|
@@ -108,8 +133,32 @@ const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: Astro
|
|
|
108
133
|
}
|
|
109
134
|
}, []);
|
|
110
135
|
|
|
136
|
+
// Opening the diagram in Studio: asks what to call the canvas, then makes it with what the diagram shows and opens
|
|
137
|
+
// it (in this tab) at the level shown. What it shows is only taken once it's named (laying a level out can take a
|
|
138
|
+
// moment), and anything that goes wrong is shown in the dialog.
|
|
139
|
+
const [toOpen, setToOpen] = useState<OpenInStudioRequest | null>(null);
|
|
140
|
+
const closeOpenInStudio = useCallback(() => setToOpen(null), []);
|
|
141
|
+
const openInStudio = useCallback(
|
|
142
|
+
async (title: string | undefined) => {
|
|
143
|
+
if (!studioApiUrl || !toOpen) return;
|
|
144
|
+
const snapshot = await toOpen.getSnapshot();
|
|
145
|
+
const { canvasFromVisualiser } = await import('@features/studio/from-visualiser');
|
|
146
|
+
const { nodes, edges, levels } = canvasFromVisualiser(snapshot);
|
|
147
|
+
if (nodes.length === 0) throw new Error('Nothing on this diagram can go on a canvas yet');
|
|
148
|
+
const canvas = await createCanvasThroughApi(studioApiUrl, {
|
|
149
|
+
title,
|
|
150
|
+
createdBy: getStoredName() ?? undefined,
|
|
151
|
+
nodes,
|
|
152
|
+
edges,
|
|
153
|
+
levels,
|
|
154
|
+
});
|
|
155
|
+
window.location.assign(snapshot.level === 3 ? canvas.url : `${canvas.url}?level=${snapshot.level}`);
|
|
156
|
+
},
|
|
157
|
+
[studioApiUrl, toOpen]
|
|
158
|
+
);
|
|
159
|
+
|
|
111
160
|
return (
|
|
112
|
-
<Suspense fallback={<
|
|
161
|
+
<Suspense fallback={<LoadingGraph portalId={otherProps.portalId || `${otherProps.id}-portal`} />}>
|
|
113
162
|
<NodeGraph
|
|
114
163
|
{...otherProps}
|
|
115
164
|
resourceKey={resourceKey}
|
|
@@ -118,7 +167,14 @@ const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: Astro
|
|
|
118
167
|
onBuildUrl={handleBuildUrl}
|
|
119
168
|
onSaveLayout={handleSaveLayout}
|
|
120
169
|
onResetLayout={handleResetLayout}
|
|
170
|
+
onOpenInStudio={studioApiUrl ? setToOpen : undefined}
|
|
121
171
|
/>
|
|
172
|
+
{toOpen && (
|
|
173
|
+
// Its own, so the diagram isn't swapped for "Loading graph..." while the dialog loads
|
|
174
|
+
<Suspense fallback={null}>
|
|
175
|
+
<OpenInStudioDialog title={toOpen.title} onOpen={openInStudio} onClose={closeOpenInStudio} />
|
|
176
|
+
</Suspense>
|
|
177
|
+
)}
|
|
122
178
|
</Suspense>
|
|
123
179
|
);
|
|
124
180
|
};
|
|
@@ -31,11 +31,14 @@ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
|
|
|
31
31
|
import { getNodesAndEdges as getNodesAndEdgesForContainer } from '@utils/node-graphs/container-node-graph';
|
|
32
32
|
import { getNodesAndEdges as getNodesAndEdgesForChannel } from '@utils/node-graphs/channel-node-graph';
|
|
33
33
|
import config from '@config';
|
|
34
|
-
import { isEventCatalogChatVisible, isDevMode } from '@utils/feature';
|
|
34
|
+
import { isEventCatalogChatVisible, isDevMode, isCanvasEnabled } from '@utils/feature';
|
|
35
|
+
import { CANVASES_API_PATH } from '@features/studio/api/canvases-api';
|
|
35
36
|
import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
|
|
36
37
|
import { compactVisualiserGraph } from '@utils/node-graphs/compact-visualiser-graph';
|
|
37
38
|
|
|
38
39
|
const isChatEnabled = isEventCatalogChatVisible();
|
|
40
|
+
// With Studio on, the menu can start a canvas from the diagram
|
|
41
|
+
const studioApiUrl = isCanvasEnabled() ? buildUrl(CANVASES_API_PATH, true) : undefined;
|
|
39
42
|
|
|
40
43
|
interface Props {
|
|
41
44
|
id: string;
|
|
@@ -257,6 +260,7 @@ if (overview && levelsOverview) {
|
|
|
257
260
|
hiddenMessagesGraph={hiddenMessagesGraph}
|
|
258
261
|
preferenceScope={collection}
|
|
259
262
|
swimlanes={lanes}
|
|
263
|
+
studioApiUrl={studioApiUrl}
|
|
260
264
|
/>
|
|
261
265
|
</div>
|
|
262
266
|
|
|
@@ -22,12 +22,19 @@
|
|
|
22
22
|
opacity: 1;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/* On every page, hidden until a navigation takes a while: paused until then (a running animation costs a style
|
|
26
|
+
recalc and paint on every frame, even when it can't be seen) */
|
|
25
27
|
.navigation-progress__bar {
|
|
26
28
|
width: 35%;
|
|
27
29
|
height: 100%;
|
|
28
30
|
background: rgb(var(--ec-accent));
|
|
29
31
|
box-shadow: 0 0 10px rgb(var(--ec-accent) / 0.55);
|
|
30
32
|
animation: navigation-progress 1.1s ease-in-out infinite;
|
|
33
|
+
animation-play-state: paused;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#navigation-progress[data-visible='true'] .navigation-progress__bar {
|
|
37
|
+
animation-play-state: running;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
:global([data-navigation-pending='true']) {
|
|
@@ -4,6 +4,7 @@ import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
|
4
4
|
import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
5
5
|
import { getLanguageForHighlight, getSchemaTypeLabel } from './utils';
|
|
6
6
|
import { useDarkMode } from './useDarkMode';
|
|
7
|
+
import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
|
|
7
8
|
import type { SchemaItem } from './types';
|
|
8
9
|
|
|
9
10
|
interface ApiContentViewerProps {
|
|
@@ -135,6 +136,7 @@ export default function ApiContentViewer({ message, onCopy, copiedId }: ApiConte
|
|
|
135
136
|
|
|
136
137
|
<div className="border-t" style={{ borderColor: dividerColor }}>
|
|
137
138
|
<SyntaxHighlighter
|
|
139
|
+
renderer={renderHighlightedRows}
|
|
138
140
|
language={getLanguageForHighlight(message.schemaExtension)}
|
|
139
141
|
style={isDarkMode ? oneDark : oneLight}
|
|
140
142
|
customStyle={{
|
|
@@ -13,6 +13,7 @@ import { MarkdownCodeGroup } from '../MDX/CodeGroup/MarkdownCodeGroup';
|
|
|
13
13
|
import { MarkdownColumns, MarkdownColumn } from '../MDX/Columns/MarkdownColumns';
|
|
14
14
|
import { remarkMarkdownColumns } from '../../remark-plugins/markdown-columns';
|
|
15
15
|
import { getLanguageForHighlight } from './utils';
|
|
16
|
+
import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
|
|
16
17
|
|
|
17
18
|
interface ExamplesViewerProps {
|
|
18
19
|
examples: MessageExample[];
|
|
@@ -40,6 +41,7 @@ function CodeBlock({ language, code }: { language?: string; code: string }) {
|
|
|
40
41
|
const content = code.replace(/\s+$/, '');
|
|
41
42
|
const highlighter = (
|
|
42
43
|
<SyntaxHighlighter
|
|
44
|
+
renderer={renderHighlightedRows}
|
|
43
45
|
language={language || 'text'}
|
|
44
46
|
style={isDarkMode ? oneDark : oneLight}
|
|
45
47
|
customStyle={{
|
|
@@ -6,6 +6,7 @@ import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
|
6
6
|
import { getLanguageForHighlight } from './utils';
|
|
7
7
|
import type { SchemaItem } from './types';
|
|
8
8
|
import { useDarkMode } from './useDarkMode';
|
|
9
|
+
import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
|
|
9
10
|
|
|
10
11
|
interface SchemaCodeModalProps {
|
|
11
12
|
isOpen: boolean;
|
|
@@ -60,6 +61,7 @@ export default function SchemaCodeModal({ isOpen, onOpenChange, message, onCopy,
|
|
|
60
61
|
{/* Content */}
|
|
61
62
|
<div className="flex-1 overflow-auto p-6">
|
|
62
63
|
<SyntaxHighlighter
|
|
64
|
+
renderer={renderHighlightedRows}
|
|
63
65
|
language={getLanguageForHighlight(message.schemaExtension)}
|
|
64
66
|
style={isDarkMode ? oneDark : oneLight}
|
|
65
67
|
customStyle={{
|
|
@@ -9,6 +9,7 @@ import ProtobufSchemaViewer from './ProtobufSchemaViewer';
|
|
|
9
9
|
import { getLanguageForHighlight, SCHEMA_CODE_STYLE } from './utils';
|
|
10
10
|
import type { SchemaItem } from './types';
|
|
11
11
|
import { useDarkMode } from './useDarkMode';
|
|
12
|
+
import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
|
|
12
13
|
|
|
13
14
|
interface SchemaContentViewerProps {
|
|
14
15
|
message: SchemaItem;
|
|
@@ -112,6 +113,7 @@ export default function SchemaContentViewer({
|
|
|
112
113
|
|
|
113
114
|
<div className="min-h-0 flex-1 overflow-auto">
|
|
114
115
|
<SyntaxHighlighter
|
|
116
|
+
renderer={renderHighlightedRows}
|
|
115
117
|
language={getLanguageForHighlight(message.schemaExtension)}
|
|
116
118
|
style={isDarkMode ? oneDark : oneLight}
|
|
117
119
|
customStyle={{ ...SCHEMA_CODE_STYLE, height: '100%' }}
|
|
@@ -16,34 +16,22 @@
|
|
|
16
16
|
import { setSidebarData, sidebarStore } from '@stores/sidebar-store';
|
|
17
17
|
import { buildUrl } from '@utils/url-builder';
|
|
18
18
|
|
|
19
|
-
// Only fetch if we haven't already loaded the data
|
|
19
|
+
// Only fetch if we haven't already loaded the data. Fetched straight away rather than when
|
|
20
|
+
// the browser is idle: the sidebar's first paint comes from the server (see SideNav.astro),
|
|
21
|
+
// but drilling down and search wait on this data
|
|
20
22
|
if (!sidebarStore.get()) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.then((data) => {
|
|
35
|
-
setSidebarData(data);
|
|
36
|
-
})
|
|
37
|
-
.catch((error) => {
|
|
38
|
-
console.error('Error loading sidebar data:', error);
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Defer non-critical sidebar payload fetch until browser is idle
|
|
43
|
-
if (typeof window.requestIdleCallback === 'function') {
|
|
44
|
-
window.requestIdleCallback(loadSidebarData, { timeout: 1200 });
|
|
45
|
-
} else {
|
|
46
|
-
setTimeout(loadSidebarData, 300);
|
|
47
|
-
}
|
|
23
|
+
fetch(buildUrl('/api/sidebar-data.json', true))
|
|
24
|
+
.then((response) => {
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
throw new Error(`Failed to fetch sidebar data: ${response.status}`);
|
|
27
|
+
}
|
|
28
|
+
return response.json();
|
|
29
|
+
})
|
|
30
|
+
.then((data) => {
|
|
31
|
+
setSidebarData(data);
|
|
32
|
+
})
|
|
33
|
+
.catch((error) => {
|
|
34
|
+
console.error('Error loading sidebar data:', error);
|
|
35
|
+
});
|
|
48
36
|
}
|
|
49
37
|
</script>
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
getUrlForSearchItem,
|
|
35
35
|
highlightQuery,
|
|
36
36
|
mapPagefindResultsToSearchItems,
|
|
37
|
+
rankResourceSearchItems,
|
|
37
38
|
type SearchItem,
|
|
38
39
|
type SearchNode,
|
|
39
40
|
} from './search-utils';
|
|
@@ -316,16 +317,7 @@ export default function SearchModal() {
|
|
|
316
317
|
return items;
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
|
|
320
|
-
return items.filter((item) => {
|
|
321
|
-
if (item.name.toLowerCase().includes(lowerQuery)) return true;
|
|
322
|
-
// Key format is "type:id:version" (e.g. "service:OrdersService:0.0.3").
|
|
323
|
-
// Match against the id so users can find resources by their raw id too.
|
|
324
|
-
const keyParts = item.key?.split(':') ?? [];
|
|
325
|
-
const id = keyParts[1];
|
|
326
|
-
if (id?.toLowerCase().includes(lowerQuery)) return true;
|
|
327
|
-
return !!item.rawNode.summary && item.rawNode.summary.toLowerCase().includes(lowerQuery);
|
|
328
|
-
});
|
|
320
|
+
return rankResourceSearchItems(items, query);
|
|
329
321
|
}, [indexedItems, isIndexedSearch, items, query]);
|
|
330
322
|
|
|
331
323
|
const filters = useMemo(() => {
|