@eventcatalog/core 5.0.0-beta.3 → 5.0.0-beta.30
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-RFIXKATC.js → chunk-4G7FSRPN.js} +35 -42
- package/dist/{chunk-6OC46WQJ.js → chunk-55QETQZ3.js} +66 -35
- package/dist/{chunk-TQLRG35T.js → chunk-AD7CL772.js} +78 -45
- package/dist/chunk-CA6WCQ2T.js +54 -0
- package/dist/chunk-CPW6G62V.js +17 -0
- package/dist/{chunk-423S2KHN.js → chunk-FLAZ2JVN.js} +4 -2
- package/dist/{chunk-BH2F5WPN.js → chunk-GQI5UYXZ.js} +1 -1
- package/dist/{chunk-GYIVJXOJ.js → chunk-NA7OTBWW.js} +1 -1
- package/dist/{chunk-MDWB5HLO.js → chunk-NKNOXQ62.js} +1 -1
- 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-NDJOAITI.js → chunk-T3OROMAU.js} +9 -3
- 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
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { hideMessageNodes, layoutWithElk } from '@eventcatalog/visualiser/layout';
|
|
2
|
+
import { isSSR } from '@utils/feature';
|
|
2
3
|
|
|
3
4
|
type Graph = { nodes: any[]; edges: any[] };
|
|
4
5
|
|
|
6
|
+
// A build renders one route at a time (every message's docs page, then every schema page), so the
|
|
7
|
+
// cache has to outlast a whole route to be reused. A server keeps running as the catalog changes and
|
|
8
|
+
// renders pages as they're asked for, so it keeps the most recent layouts only.
|
|
9
|
+
const MAX_CACHED_LAYOUTS = isSSR() ? 200 : 5000;
|
|
10
|
+
const layouts = new Map<string, ReturnType<typeof layoutWithElk>>();
|
|
11
|
+
|
|
5
12
|
/**
|
|
6
13
|
* Lays a node graph out for the visualiser (with ELK, left to right). Builders
|
|
7
14
|
* create their nodes and edges without positions and lay the finished graph
|
|
@@ -9,7 +16,19 @@ type Graph = { nodes: any[]; edges: any[] };
|
|
|
9
16
|
* (nodes with children) are sized to fit them, and edges get the route they're
|
|
10
17
|
* drawn along (`data.route`), with room for their labels.
|
|
11
18
|
*/
|
|
12
|
-
export const layoutNodeGraph = async <G extends Graph>(graph: G): Promise<G> =>
|
|
19
|
+
export const layoutNodeGraph = async <G extends Graph>(graph: G): Promise<G> => {
|
|
20
|
+
// A build lays the same graph out on several pages (a message's docs, visualiser and schema pages):
|
|
21
|
+
// reuse the layout. Each caller gets its own copy, so it can't change the one kept.
|
|
22
|
+
const key = JSON.stringify(graph);
|
|
23
|
+
let layout = layouts.get(key);
|
|
24
|
+
if (!layout) {
|
|
25
|
+
layout = layoutWithElk(graph);
|
|
26
|
+
layouts.set(key, layout);
|
|
27
|
+
layout.catch(() => layouts.delete(key));
|
|
28
|
+
if (layouts.size > MAX_CACHED_LAYOUTS) layouts.delete(layouts.keys().next().value!);
|
|
29
|
+
}
|
|
30
|
+
return structuredClone(await layout) as unknown as G;
|
|
31
|
+
};
|
|
13
32
|
|
|
14
33
|
/**
|
|
15
34
|
* Lays out the graphs of a levels page: level 1 (`overview`: domains, systems
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The catalog resource a diagram node shows, for the node types the node graphs build. Has no imports so it can
|
|
3
|
+
* be shared by the server and the browser (the visualiser's "Open in Studio", the MCP App views).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// The collection each node type shows a resource of
|
|
7
|
+
const NODE_COLLECTIONS: Record<string, string> = {
|
|
8
|
+
service: 'services',
|
|
9
|
+
services: 'services',
|
|
10
|
+
agent: 'agents',
|
|
11
|
+
agents: 'agents',
|
|
12
|
+
event: 'events',
|
|
13
|
+
events: 'events',
|
|
14
|
+
command: 'commands',
|
|
15
|
+
commands: 'commands',
|
|
16
|
+
query: 'queries',
|
|
17
|
+
queries: 'queries',
|
|
18
|
+
channel: 'channels',
|
|
19
|
+
channels: 'channels',
|
|
20
|
+
flow: 'flows',
|
|
21
|
+
flows: 'flows',
|
|
22
|
+
data: 'containers',
|
|
23
|
+
containers: 'containers',
|
|
24
|
+
'data-products': 'data-products',
|
|
25
|
+
domain: 'domains',
|
|
26
|
+
domains: 'domains',
|
|
27
|
+
'context-domain': 'domains',
|
|
28
|
+
'domain-group': 'domains',
|
|
29
|
+
system: 'systems',
|
|
30
|
+
systems: 'systems',
|
|
31
|
+
'system-group': 'systems',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Where each node type keeps the resource it shows
|
|
35
|
+
const RESOURCE_DATA_KEYS = [
|
|
36
|
+
'service',
|
|
37
|
+
'agent',
|
|
38
|
+
'message',
|
|
39
|
+
'channel',
|
|
40
|
+
'data',
|
|
41
|
+
'dataProduct',
|
|
42
|
+
'flow',
|
|
43
|
+
'entity',
|
|
44
|
+
'domain',
|
|
45
|
+
'system',
|
|
46
|
+
'custom',
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
type DiagramNode = { type?: string; data?: Record<string, unknown> };
|
|
50
|
+
type ResourceDetails = { id?: unknown; version?: unknown; [key: string]: unknown };
|
|
51
|
+
|
|
52
|
+
/** The resource a node shows, as in its data: the fields shown, or the catalog entry's data (if it holds the entry) */
|
|
53
|
+
export const getNodeResourceDetails = (node: DiagramNode): ResourceDetails | undefined => {
|
|
54
|
+
const data = node.data ?? {};
|
|
55
|
+
const resource = RESOURCE_DATA_KEYS.map((key) => data[key]).find(Boolean) as
|
|
56
|
+
| (ResourceDetails & { data?: ResourceDetails })
|
|
57
|
+
| undefined;
|
|
58
|
+
return resource?.data ?? resource;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** The catalog resource a node shows (its collection, id and version), if it shows one */
|
|
62
|
+
export const getNodeCatalogResource = (node: DiagramNode): { collection: string; id: string; version?: string } | undefined => {
|
|
63
|
+
const collection = NODE_COLLECTIONS[node.type ?? ''];
|
|
64
|
+
const details = getNodeResourceDetails(node);
|
|
65
|
+
if (!collection || typeof details?.id !== 'string') return undefined;
|
|
66
|
+
return { collection, id: details.id, ...(typeof details.version === 'string' && { version: details.version }) };
|
|
67
|
+
};
|
|
@@ -142,7 +142,7 @@ const wrapNodesInSystemGroup = (systemNodes: any[], system: any) => {
|
|
|
142
142
|
draggable: false,
|
|
143
143
|
selectable: false,
|
|
144
144
|
data: {
|
|
145
|
-
system: { name: system.data.name, version: system.data.version },
|
|
145
|
+
system: { id: system.data.id, name: system.data.name, version: system.data.version },
|
|
146
146
|
// The system is the resource being viewed on its own diagram
|
|
147
147
|
isFocused: true,
|
|
148
148
|
},
|
|
@@ -24,7 +24,9 @@ export class HybridPage<T = any> {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* The page's data: its props in a static build, or looked up from its URL on a server. Undefined
|
|
28
|
+
* when nothing matches (an unknown resource or version): the page then returns
|
|
29
|
+
* `Astro.rewrite('/404')`. Throwing a Response instead made Astro answer with an empty 500.
|
|
28
30
|
*/
|
|
29
31
|
static async getData(astro: AstroGlobal): Promise<any> {
|
|
30
32
|
// Try props first (static mode)
|
|
@@ -32,13 +34,7 @@ export class HybridPage<T = any> {
|
|
|
32
34
|
return this.transformProps(astro.props);
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!data) {
|
|
38
|
-
throw this.createNotFoundResponse();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return data;
|
|
37
|
+
return (await this.fetchData(astro.params)) ?? undefined;
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
/**
|
|
@@ -58,11 +54,4 @@ export class HybridPage<T = any> {
|
|
|
58
54
|
protected static transformProps(props: any): any {
|
|
59
55
|
return props;
|
|
60
56
|
}
|
|
61
|
-
|
|
62
|
-
protected static createNotFoundResponse(): Response {
|
|
63
|
-
return new Response(null, {
|
|
64
|
-
status: 404,
|
|
65
|
-
statusText: 'Not found',
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
57
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import config from '@config';
|
|
2
|
+
|
|
3
|
+
/** The catalog's name: `title` in eventcatalog.config.js, or EventCatalog when it has none */
|
|
4
|
+
export const getCatalogTitle = (): string => config?.title?.trim() || 'EventCatalog';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A page's title, as browser tabs and link previews show it: the page's own title, then the
|
|
8
|
+
* catalog's (`Domains | Ordering | Acme Inc`), so tabs show the page first. A page without a title
|
|
9
|
+
* of its own (the homepage) is just the catalog's.
|
|
10
|
+
*/
|
|
11
|
+
export const formatPageTitle = (title?: string): string => {
|
|
12
|
+
const catalogTitle = getCatalogTitle();
|
|
13
|
+
const pageTitle = title?.trim();
|
|
14
|
+
return pageTitle && pageTitle !== catalogTitle ? `${pageTitle} | ${catalogTitle}` : catalogTitle;
|
|
15
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createElement, type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
import { createStyleObject } from 'react-syntax-highlighter/dist/cjs/create-element.js';
|
|
3
|
+
|
|
4
|
+
type Stylesheet = { [selector: string]: CSSProperties };
|
|
5
|
+
type HighlightedNode = {
|
|
6
|
+
type: 'element' | 'text';
|
|
7
|
+
value?: string | number;
|
|
8
|
+
tagName?: any;
|
|
9
|
+
properties?: { className?: string[]; style?: CSSProperties; [key: string]: unknown };
|
|
10
|
+
children?: HighlightedNode[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const selectorsByStylesheet = new WeakMap<Stylesheet, Set<string>>();
|
|
14
|
+
|
|
15
|
+
/** The class names a theme styles, worked out once per theme */
|
|
16
|
+
const stylesheetSelectors = (stylesheet: Stylesheet) => {
|
|
17
|
+
let selectors = selectorsByStylesheet.get(stylesheet);
|
|
18
|
+
if (!selectors) {
|
|
19
|
+
selectors = new Set(Object.keys(stylesheet).flatMap((selector) => selector.split('.')));
|
|
20
|
+
selectorsByStylesheet.set(stylesheet, selectors);
|
|
21
|
+
}
|
|
22
|
+
return selectors;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const renderNode = (node: HighlightedNode, stylesheet: Stylesheet, useInlineStyles: boolean, key: string): ReactNode => {
|
|
26
|
+
if (node.type === 'text') return node.value;
|
|
27
|
+
if (!node.tagName) return undefined;
|
|
28
|
+
|
|
29
|
+
const properties = node.properties ?? {};
|
|
30
|
+
const classNames = properties.className;
|
|
31
|
+
let props;
|
|
32
|
+
if (!useInlineStyles) {
|
|
33
|
+
props = { ...properties, className: classNames?.join(' ') };
|
|
34
|
+
} else {
|
|
35
|
+
// Theme classes become inline styles; any other class names stay
|
|
36
|
+
const selectors = stylesheetSelectors(stylesheet);
|
|
37
|
+
const className =
|
|
38
|
+
classNames && (classNames.includes('token') ? ['token'] : []).concat(classNames.filter((name) => !selectors.has(name)));
|
|
39
|
+
props = {
|
|
40
|
+
...properties,
|
|
41
|
+
className: className?.join(' ') || undefined,
|
|
42
|
+
style: createStyleObject(classNames ?? [], { ...properties.style }, stylesheet),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const children = (node.children ?? []).map((child, i) => renderNode(child, stylesheet, useInlineStyles, `code-segment-1-${i}`));
|
|
47
|
+
return createElement(node.tagName, { key, ...props }, children);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Renders react-syntax-highlighter's rows as its default renderer does (same elements, styles and keys), but
|
|
52
|
+
* works out the theme's class names once per theme rather than for every token: the default renderer did
|
|
53
|
+
* that for every token, which made highlighting a schema on the server take tens of milliseconds a page.
|
|
54
|
+
* Set `wrapLines`: with a custom renderer, react-syntax-highlighter turns it on when it isn't set.
|
|
55
|
+
*/
|
|
56
|
+
export const renderHighlightedRows = ({
|
|
57
|
+
rows,
|
|
58
|
+
stylesheet,
|
|
59
|
+
useInlineStyles,
|
|
60
|
+
}: {
|
|
61
|
+
rows: HighlightedNode[];
|
|
62
|
+
stylesheet: Stylesheet;
|
|
63
|
+
useInlineStyles: boolean;
|
|
64
|
+
}): ReactNode[] => rows.map((node, i) => renderNode(node, stylesheet, useInlineStyles, `code-segment-${i}`));
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
export const TRIAL_LENGTH_DAYS =
|
|
1
|
+
export const TRIAL_LENGTH_DAYS = 60;
|
|
2
2
|
|
|
3
3
|
export const LICENSE_FAQ_URL = 'https://www.eventcatalog.dev/license-faq';
|
|
4
4
|
|
|
5
5
|
// Where a commercial license is renewed
|
|
6
6
|
export const LICENSE_RENEW_URL = 'https://eventcatalog.cloud';
|
|
7
7
|
|
|
8
|
+
// Where the Business plan is bought: the order form on the website
|
|
9
|
+
export const BUY_BUSINESS_URL = 'https://www.eventcatalog.dev/buy?source=cli';
|
|
10
|
+
|
|
11
|
+
// Prices for a commercial license, linked while the trial is running
|
|
12
|
+
export const PRICING_URL = 'https://www.eventcatalog.dev/pricing';
|
|
13
|
+
|
|
14
|
+
// Questions about licensing or buying: talk to the EventCatalog team
|
|
15
|
+
export const TALK_TO_US_URL = 'https://www.eventcatalog.dev/book-demo';
|
|
16
|
+
|
|
17
|
+
// Shown with the trial, so organisations that qualify for Free Use don't read it as "EventCatalog is now paid"
|
|
18
|
+
export const FREE_USE_NOTE =
|
|
19
|
+
'Under $10M revenue and $10M raised, an individual or an open-source project? You qualify for Free Use; get a free key at eventcatalog.cloud.';
|
|
20
|
+
|
|
8
21
|
const DAY_IN_MS = 24 * 60 * 60 * 1000;
|
|
9
22
|
|
|
10
23
|
export type TrialStatus = {
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"license": "BUSL-1.1",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "5.0.0-beta.
|
|
10
|
+
"version": "5.0.0-beta.30",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@ai-sdk/react": "^4.0.109",
|
|
50
|
-
"@astrojs/markdown-remark": "^7.3.
|
|
51
|
-
"@astrojs/mdx": "^8.0.
|
|
52
|
-
"@astrojs/node": "^11.1.
|
|
53
|
-
"@astrojs/react": "^
|
|
50
|
+
"@astrojs/markdown-remark": "^7.3.2",
|
|
51
|
+
"@astrojs/mdx": "^8.0.3",
|
|
52
|
+
"@astrojs/node": "^11.1.7",
|
|
53
|
+
"@astrojs/react": "^7.0.1",
|
|
54
54
|
"@astrojs/rss": "^4.0.19",
|
|
55
55
|
"@asyncapi/avro-schema-parser": "3.0.24",
|
|
56
56
|
"@asyncapi/parser": "^3.6.0",
|
|
@@ -60,7 +60,11 @@
|
|
|
60
60
|
"@fontsource/inter": "^5.2.5",
|
|
61
61
|
"@headlessui/react": "^2.0.3",
|
|
62
62
|
"@heroicons/react": "^2.1.3",
|
|
63
|
+
"@hocuspocus/provider": "^4.7.0",
|
|
64
|
+
"@hocuspocus/server": "^4.7.0",
|
|
63
65
|
"@iconify-json/logos": "^1.2.4",
|
|
66
|
+
"@mcp-b/webmcp-local-relay": "5.1.0",
|
|
67
|
+
"@mcp-b/webmcp-polyfill": "5.1.0",
|
|
64
68
|
"@mermaid-js/layout-elk": "^0.2.0",
|
|
65
69
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
66
70
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
@@ -77,9 +81,9 @@
|
|
|
77
81
|
"@tanstack/react-table": "^8.17.3",
|
|
78
82
|
"@xyflow/react": "^12.12.0",
|
|
79
83
|
"ai": "^7.0.106",
|
|
80
|
-
"astro": "7.3.
|
|
84
|
+
"astro": "7.3.8",
|
|
81
85
|
"astro-expressive-code": "^0.44.0",
|
|
82
|
-
"astro-seo": "^
|
|
86
|
+
"astro-seo": "^1.2.0",
|
|
83
87
|
"boxen": "^8.0.1",
|
|
84
88
|
"commander": "^12.1.0",
|
|
85
89
|
"cross-env": "^7.0.3",
|
|
@@ -93,8 +97,9 @@
|
|
|
93
97
|
"elkjs": "^0.10.0",
|
|
94
98
|
"glob": "^13.0.6",
|
|
95
99
|
"gray-matter": "^4.0.3",
|
|
96
|
-
"hono": "4.13.
|
|
100
|
+
"hono": "^4.13.7",
|
|
97
101
|
"html-to-image": "^1.11.11",
|
|
102
|
+
"htmlparser2": "^12.0.0",
|
|
98
103
|
"js-yaml": "^4.3.2",
|
|
99
104
|
"jsonpath-plus": "^10.4.0",
|
|
100
105
|
"jsonwebtoken": "^9.0.2",
|
|
@@ -113,6 +118,7 @@
|
|
|
113
118
|
"picomatch": "^4.0.4",
|
|
114
119
|
"react": "^19.2.0",
|
|
115
120
|
"react-dom": "^19.2.0",
|
|
121
|
+
"react-hotkeys-hook": "^5.3.3",
|
|
116
122
|
"react-markdown": "^10.1.0",
|
|
117
123
|
"react-syntax-highlighter": "^16.1.1",
|
|
118
124
|
"recast": "^0.23.11",
|
|
@@ -125,7 +131,6 @@
|
|
|
125
131
|
"rimraf": "^6.1.3",
|
|
126
132
|
"semver": "7.6.3",
|
|
127
133
|
"set-cookie-parser": "^2.7.1",
|
|
128
|
-
"shelljs": "^0.9.0",
|
|
129
134
|
"sonner": "^2.0.7",
|
|
130
135
|
"sql.js": "^1.12.0",
|
|
131
136
|
"tailwindcss": "^4.3.1",
|
|
@@ -133,10 +138,12 @@
|
|
|
133
138
|
"unist-util-visit": "^5.0.0",
|
|
134
139
|
"update-notifier": "^7.3.1",
|
|
135
140
|
"uuid": "^11.1.1",
|
|
141
|
+
"y-protocols": "^1.0.7",
|
|
142
|
+
"yjs": "^13.6.33",
|
|
136
143
|
"zod": "^4.3.6",
|
|
137
|
-
"@eventcatalog/linter": "1.2.0-beta.
|
|
138
|
-
"@eventcatalog/sdk": "2.30.0-beta.
|
|
139
|
-
"@eventcatalog/visualiser": "^5.0.0-beta.
|
|
144
|
+
"@eventcatalog/linter": "1.2.0-beta.4",
|
|
145
|
+
"@eventcatalog/sdk": "2.30.0-beta.1",
|
|
146
|
+
"@eventcatalog/visualiser": "^5.0.0-beta.7"
|
|
140
147
|
},
|
|
141
148
|
"devDependencies": {
|
|
142
149
|
"@astrojs/check": "^0.9.10",
|
|
@@ -156,7 +163,6 @@
|
|
|
156
163
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
157
164
|
"@types/semver": "^7.5.8",
|
|
158
165
|
"@types/set-cookie-parser": "^2.4.10",
|
|
159
|
-
"@types/shelljs": "^0.8.15",
|
|
160
166
|
"@types/update-notifier": "^6.0.8",
|
|
161
167
|
"@types/uuid": "^10.0.0",
|
|
162
168
|
"jsdom": "27.0.0",
|
|
Binary file
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import * as Dialog from '@radix-ui/react-dialog';
|
|
3
|
-
import { ExternalLinkIcon, CheckIcon, ClipboardIcon, Loader2 } from 'lucide-react';
|
|
4
|
-
|
|
5
|
-
const StudioPageModal: React.FC = () => {
|
|
6
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
7
|
-
const [copySuccess, setCopySuccess] = useState(false);
|
|
8
|
-
const [hasCopied, setHasCopied] = useState(false);
|
|
9
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
10
|
-
const [error, setError] = useState<string | null>(null);
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const handleOpen = () => setIsOpen(true);
|
|
14
|
-
window.addEventListener('openStudioModal', handleOpen);
|
|
15
|
-
return () => window.removeEventListener('openStudioModal', handleOpen);
|
|
16
|
-
}, []);
|
|
17
|
-
|
|
18
|
-
const handleCopyResources = async () => {
|
|
19
|
-
setIsLoading(true);
|
|
20
|
-
setError(null);
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const response = await fetch('/api/catalog');
|
|
24
|
-
|
|
25
|
-
if (!response.ok) {
|
|
26
|
-
throw new Error('Failed to fetch catalog data');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const catalogData = await response.json();
|
|
30
|
-
|
|
31
|
-
await navigator.clipboard.writeText(JSON.stringify(catalogData, null, 2));
|
|
32
|
-
setCopySuccess(true);
|
|
33
|
-
setHasCopied(true);
|
|
34
|
-
setTimeout(() => setCopySuccess(false), 2000);
|
|
35
|
-
} catch (err) {
|
|
36
|
-
console.error('Failed to copy resources:', err);
|
|
37
|
-
setError('Failed to copy resources. Please try again.');
|
|
38
|
-
} finally {
|
|
39
|
-
setIsLoading(false);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const handleOpenStudio = () => {
|
|
44
|
-
window.open(
|
|
45
|
-
'https://app.eventcatalog.studio/playground?import-resources=true&utm_source=eventcatalog&utm_medium=referral&utm_campaign=studio-page',
|
|
46
|
-
'_blank'
|
|
47
|
-
);
|
|
48
|
-
setIsOpen(false);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
|
|
53
|
-
<Dialog.Portal>
|
|
54
|
-
<Dialog.Overlay className="fixed inset-0 bg-black/50 data-[state=open]:animate-overlayShow z-50" />
|
|
55
|
-
<Dialog.Content className="fixed top-1/2 left-1/2 w-[90vw] max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6 shadow-xl focus:outline-hidden data-[state=open]:animate-contentShow z-[100]">
|
|
56
|
-
<Dialog.Title className="text-lg font-semibold text-gray-900 mb-3">Open EventCatalog Studio</Dialog.Title>
|
|
57
|
-
|
|
58
|
-
<Dialog.Description className="text-sm text-gray-600 mb-6">
|
|
59
|
-
Import your catalog resources into{' '}
|
|
60
|
-
<a
|
|
61
|
-
href="https://eventcatalog.studio"
|
|
62
|
-
className="text-gray-900 hover:text-gray-700 underline font-semibold"
|
|
63
|
-
target="_blank"
|
|
64
|
-
rel="noopener noreferrer"
|
|
65
|
-
>
|
|
66
|
-
EventCatalog Studio
|
|
67
|
-
</a>{' '}
|
|
68
|
-
to create architecture diagrams.
|
|
69
|
-
</Dialog.Description>
|
|
70
|
-
|
|
71
|
-
<div className="space-y-4">
|
|
72
|
-
{/* Step 1: Copy Resources */}
|
|
73
|
-
<div className="bg-gray-50 rounded-lg p-4 border border-gray-200">
|
|
74
|
-
<h4 className="text-sm font-bold text-gray-900 mb-2">Step 1: Copy your resources</h4>
|
|
75
|
-
<p className="text-xs text-gray-600 mb-3">Copy your EventCatalog resources to your clipboard.</p>
|
|
76
|
-
|
|
77
|
-
<button
|
|
78
|
-
onClick={handleCopyResources}
|
|
79
|
-
disabled={isLoading}
|
|
80
|
-
className={`w-full flex items-center justify-center space-x-2 px-4 py-2 text-sm font-medium rounded-md border transition-colors ${
|
|
81
|
-
copySuccess
|
|
82
|
-
? 'bg-green-50 border-green-200 text-green-700'
|
|
83
|
-
: isLoading
|
|
84
|
-
? 'bg-gray-100 border-gray-300 text-gray-400 cursor-not-allowed'
|
|
85
|
-
: 'bg-white border-gray-300 text-gray-700 hover:bg-gray-50'
|
|
86
|
-
}`}
|
|
87
|
-
>
|
|
88
|
-
{isLoading ? (
|
|
89
|
-
<>
|
|
90
|
-
<Loader2 className="w-4 h-4 animate-spin" />
|
|
91
|
-
<span>Loading resources...</span>
|
|
92
|
-
</>
|
|
93
|
-
) : copySuccess ? (
|
|
94
|
-
<>
|
|
95
|
-
<CheckIcon className="w-4 h-4" />
|
|
96
|
-
<span>Copied!</span>
|
|
97
|
-
</>
|
|
98
|
-
) : (
|
|
99
|
-
<>
|
|
100
|
-
<ClipboardIcon className="w-4 h-4" />
|
|
101
|
-
<span>Copy resources to clipboard</span>
|
|
102
|
-
</>
|
|
103
|
-
)}
|
|
104
|
-
</button>
|
|
105
|
-
|
|
106
|
-
{error && <p className="text-xs text-red-600 mt-2">{error}</p>}
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
{/* Step 2: Open Studio */}
|
|
110
|
-
<div className="bg-gray-50 rounded-lg p-4 border border-gray-200">
|
|
111
|
-
<h4 className="text-sm font-bold text-gray-900 mb-2">Step 2: Open EventCatalog Studio</h4>
|
|
112
|
-
<p className="text-xs text-gray-600 mb-3">
|
|
113
|
-
Go to EventCatalog Studio and paste your resources into the modal dialog.
|
|
114
|
-
</p>
|
|
115
|
-
|
|
116
|
-
<button
|
|
117
|
-
onClick={handleOpenStudio}
|
|
118
|
-
disabled={!hasCopied}
|
|
119
|
-
className={`w-full flex items-center justify-center space-x-2 px-4 py-2 text-sm font-medium rounded-md transition-colors ${
|
|
120
|
-
hasCopied ? 'bg-gray-900 text-white hover:bg-gray-800' : 'bg-gray-300 text-gray-500 cursor-not-allowed'
|
|
121
|
-
}`}
|
|
122
|
-
>
|
|
123
|
-
<ExternalLinkIcon className="w-4 h-4" />
|
|
124
|
-
<span>Open EventCatalog Studio</span>
|
|
125
|
-
</button>
|
|
126
|
-
|
|
127
|
-
<p className="text-[12px] text-gray-500 italic mt-4 mb-0">
|
|
128
|
-
All data is stored locally in your browser. Nothing is sent to external servers.
|
|
129
|
-
</p>
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
<div className="mt-6 flex justify-end">
|
|
134
|
-
<Dialog.Close asChild>
|
|
135
|
-
<button
|
|
136
|
-
type="button"
|
|
137
|
-
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-hidden focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition-colors"
|
|
138
|
-
onClick={() => setIsOpen(false)}
|
|
139
|
-
>
|
|
140
|
-
Close
|
|
141
|
-
</button>
|
|
142
|
-
</Dialog.Close>
|
|
143
|
-
</div>
|
|
144
|
-
</Dialog.Content>
|
|
145
|
-
</Dialog.Portal>
|
|
146
|
-
</Dialog.Root>
|
|
147
|
-
);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export default StudioPageModal;
|