@eventcatalog/core 3.7.1 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/{chunk-44EDP7IH.js → chunk-4EJDLNIX.js} +1 -1
- package/dist/{chunk-MIHGWXCX.js → chunk-EG36OTR7.js} +1 -1
- package/dist/{chunk-BVJJ3COQ.js → chunk-GITARDPK.js} +1 -1
- package/dist/{chunk-PV5ER42D.js → chunk-IEEU454Z.js} +1 -1
- package/dist/{chunk-B6NBNZGS.js → chunk-ZIG6J4R2.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +5 -5
- 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/src/components/ChatPanel/ChatPanel.tsx +13 -1
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +109 -6
- package/eventcatalog/src/components/Grids/utils.tsx +10 -1
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +2 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +4 -0
- package/eventcatalog/src/components/MDX/NodeGraph/Nodes/DataProduct.tsx +132 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +29 -2
- package/eventcatalog/src/components/SchemaExplorer/types.ts +5 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +3 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +1 -0
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +23 -1
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +62 -0
- package/eventcatalog/src/content.config.ts +34 -0
- package/eventcatalog/src/enterprise/ai/chat-api.ts +26 -0
- package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +1 -1
- package/eventcatalog/src/enterprise/tools/catalog-tools.ts +169 -2
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -1
- package/eventcatalog/src/pages/discover/[type]/index.astro +57 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +5 -1
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +27 -3
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +74 -25
- package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +107 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +10 -1
- package/eventcatalog/src/stores/sidebar-store/builders/container.ts +23 -16
- package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +130 -0
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +51 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +68 -13
- package/eventcatalog/src/styles/theme.css +4 -0
- package/eventcatalog/src/styles/themes/forest.css +4 -0
- package/eventcatalog/src/styles/themes/ocean.css +4 -0
- package/eventcatalog/src/styles/themes/sapphire.css +4 -0
- package/eventcatalog/src/styles/themes/sunset.css +4 -0
- package/eventcatalog/src/types/index.ts +4 -2
- package/eventcatalog/src/utils/collections/commands.ts +11 -29
- package/eventcatalog/src/utils/collections/containers.ts +25 -1
- package/eventcatalog/src/utils/collections/data-products.ts +85 -0
- package/eventcatalog/src/utils/collections/domains.ts +33 -11
- package/eventcatalog/src/utils/collections/events.ts +11 -29
- package/eventcatalog/src/utils/collections/icons.ts +5 -0
- package/eventcatalog/src/utils/collections/messages.ts +68 -0
- package/eventcatalog/src/utils/collections/queries.ts +11 -29
- package/eventcatalog/src/utils/collections/services.ts +2 -26
- package/eventcatalog/src/utils/collections/util.ts +75 -2
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +91 -3
- package/eventcatalog/src/utils/node-graphs/data-products-node-graph.ts +225 -0
- package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +28 -2
- package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +74 -20
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-ZIG6J4R2.js";
|
|
4
|
+
import "../chunk-GITARDPK.js";
|
|
5
|
+
import "../chunk-EG36OTR7.js";
|
|
6
6
|
import "../chunk-UPONRQSN.js";
|
|
7
7
|
export {
|
|
8
8
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
|
@@ -109,7 +109,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
|
|
|
109
109
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
110
110
|
|
|
111
111
|
// package.json
|
|
112
|
-
var version = "3.
|
|
112
|
+
var version = "3.8.0";
|
|
113
113
|
|
|
114
114
|
// src/constants.ts
|
|
115
115
|
var VERSION = version;
|
package/dist/eventcatalog.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "./chunk-PLNJC7NZ.js";
|
|
7
7
|
import {
|
|
8
8
|
log_build_default
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-ZIG6J4R2.js";
|
|
10
|
+
import "./chunk-GITARDPK.js";
|
|
11
11
|
import {
|
|
12
12
|
runMigrations
|
|
13
13
|
} from "./chunk-BH3JMNAV.js";
|
|
@@ -21,13 +21,13 @@ import {
|
|
|
21
21
|
} from "./chunk-5VBIXL6C.js";
|
|
22
22
|
import {
|
|
23
23
|
generate
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-4EJDLNIX.js";
|
|
25
25
|
import {
|
|
26
26
|
logger
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-IEEU454Z.js";
|
|
28
28
|
import {
|
|
29
29
|
VERSION
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-EG36OTR7.js";
|
|
31
31
|
import "./chunk-UPONRQSN.js";
|
|
32
32
|
|
|
33
33
|
// src/eventcatalog.ts
|
package/dist/generate.cjs
CHANGED
package/dist/generate.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generate
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-4EJDLNIX.js";
|
|
4
|
+
import "./chunk-IEEU454Z.js";
|
|
5
|
+
import "./chunk-EG36OTR7.js";
|
|
6
6
|
import "./chunk-UPONRQSN.js";
|
|
7
7
|
export {
|
|
8
8
|
generate
|
package/dist/utils/cli-logger.js
CHANGED
|
@@ -171,6 +171,17 @@ const suggestedQuestionsConfig: QuestionConfig[] = [
|
|
|
171
171
|
{ label: 'Who owns this domain?', prompt: 'Who owns this domain and how do I contact them?' },
|
|
172
172
|
],
|
|
173
173
|
},
|
|
174
|
+
// Data Products page
|
|
175
|
+
{
|
|
176
|
+
pattern: /^\/(docs|visualiser)\/data-products\/.+/,
|
|
177
|
+
questions: [
|
|
178
|
+
{ label: 'What are the inputs and outputs?', prompt: 'What are the inputs and outputs of this data product?' },
|
|
179
|
+
{ label: 'Show me the data contracts', prompt: 'What are the data contracts for this data product?' },
|
|
180
|
+
{ label: 'Is this data product production ready?', prompt: 'Is this data product production ready?' },
|
|
181
|
+
{ label: 'What is the quality & SLA of this product?', prompt: 'What is the quality & SLA of this product?' },
|
|
182
|
+
{ label: 'Who owns this data product?', prompt: 'Who owns this data product and how do I contact them?' },
|
|
183
|
+
],
|
|
184
|
+
},
|
|
174
185
|
// Designs page
|
|
175
186
|
{
|
|
176
187
|
pattern: /^\/diagrams\/.+/,
|
|
@@ -490,7 +501,7 @@ const ChatPanel = ({ isOpen, onClose }: ChatPanelProps) => {
|
|
|
490
501
|
// Memoize page context to avoid recalculating on every render
|
|
491
502
|
const pageContext = useMemo(() => {
|
|
492
503
|
const match = pathname.match(
|
|
493
|
-
/^\/(docs|visualiser|architecture)\/(events|services|commands|queries|flows|domains|channels|entities|containers)\/([^/]+)(?:\/([^/]+))?/
|
|
504
|
+
/^\/(docs|visualiser|architecture)\/(events|services|commands|queries|flows|domains|channels|entities|containers|data-products)\/([^/]+)(?:\/([^/]+))?/
|
|
494
505
|
);
|
|
495
506
|
if (match) {
|
|
496
507
|
const [, , collection, id, version] = match;
|
|
@@ -504,6 +515,7 @@ const ChatPanel = ({ isOpen, onClose }: ChatPanelProps) => {
|
|
|
504
515
|
channels: 'Channel',
|
|
505
516
|
entities: 'Entity',
|
|
506
517
|
containers: 'Container',
|
|
518
|
+
'data-products': 'Data Product',
|
|
507
519
|
};
|
|
508
520
|
return {
|
|
509
521
|
type: collectionNames[collection] || collection,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ArrowTopRightOnSquareIcon,
|
|
12
12
|
ArrowLongRightIcon,
|
|
13
13
|
ArrowLongLeftIcon,
|
|
14
|
+
CubeIcon,
|
|
14
15
|
} from '@heroicons/react/24/outline';
|
|
15
16
|
import { buildUrl } from '@utils/url-builder';
|
|
16
17
|
import { BoxIcon } from 'lucide-react';
|
|
@@ -324,6 +325,43 @@ const ServiceCard = memo(({ service }: { service: any }) => {
|
|
|
324
325
|
);
|
|
325
326
|
});
|
|
326
327
|
|
|
328
|
+
const DataProductCard = memo(({ dataProduct }: { dataProduct: any }) => {
|
|
329
|
+
const data = dataProduct?.data || dataProduct;
|
|
330
|
+
|
|
331
|
+
if (!data?.id) return null;
|
|
332
|
+
|
|
333
|
+
const href = buildUrl(`/docs/data-products/${data.id}/${data.version}`);
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<a
|
|
337
|
+
href={href}
|
|
338
|
+
className="block bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] border border-[rgb(var(--ec-page-border))] rounded-xl shadow-sm hover:shadow-md hover:border-[rgb(var(--ec-accent)/0.5)] transition-all"
|
|
339
|
+
>
|
|
340
|
+
<div className="flex items-center justify-between px-4 py-3">
|
|
341
|
+
<div className="flex items-center gap-2.5">
|
|
342
|
+
<div className="flex items-center justify-center w-8 h-8 bg-purple-100 dark:bg-purple-500/20 rounded-lg">
|
|
343
|
+
<CubeIcon className="h-4 w-4 text-purple-600 dark:text-purple-400" />
|
|
344
|
+
</div>
|
|
345
|
+
<div>
|
|
346
|
+
<div className="flex items-center gap-2">
|
|
347
|
+
<span className="font-semibold text-[rgb(var(--ec-page-text))]">{data.name || data.id}</span>
|
|
348
|
+
<span className="text-[11px] text-[rgb(var(--ec-page-text-muted))] font-medium bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded">
|
|
349
|
+
v{data.version}
|
|
350
|
+
</span>
|
|
351
|
+
</div>
|
|
352
|
+
{data.summary && (
|
|
353
|
+
<p className="text-xs text-[rgb(var(--ec-page-text-muted))] line-clamp-1 mt-0.5 max-w-md">{data.summary}</p>
|
|
354
|
+
)}
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
<div className="p-1.5 text-[rgb(var(--ec-icon-color))]">
|
|
358
|
+
<ArrowTopRightOnSquareIcon className="h-4 w-4" />
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
</a>
|
|
362
|
+
);
|
|
363
|
+
});
|
|
364
|
+
|
|
327
365
|
const SubdomainSection = memo(({ subdomain }: { subdomain: any }) => {
|
|
328
366
|
const data = subdomain?.data || subdomain;
|
|
329
367
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
@@ -332,6 +370,7 @@ const SubdomainSection = memo(({ subdomain }: { subdomain: any }) => {
|
|
|
332
370
|
|
|
333
371
|
const services = data.services || [];
|
|
334
372
|
const entities = data.entities || [];
|
|
373
|
+
const dataProducts = data['data-products'] || [];
|
|
335
374
|
|
|
336
375
|
return (
|
|
337
376
|
<div className="bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] border border-[rgb(var(--ec-page-border))] rounded-xl overflow-hidden shadow-sm">
|
|
@@ -351,11 +390,13 @@ const SubdomainSection = memo(({ subdomain }: { subdomain: any }) => {
|
|
|
351
390
|
v{data.version}
|
|
352
391
|
</span>
|
|
353
392
|
{/* Show counts when collapsed */}
|
|
354
|
-
{isCollapsed && (services.length > 0 || entities.length > 0) && (
|
|
393
|
+
{isCollapsed && (services.length > 0 || entities.length > 0 || dataProducts.length > 0) && (
|
|
355
394
|
<span className="text-[11px] text-[rgb(var(--ec-icon-color))] ml-1">
|
|
356
395
|
{services.length > 0 && `${services.length} service${services.length > 1 ? 's' : ''}`}
|
|
357
|
-
{services.length > 0 && entities.length > 0 && ', '}
|
|
396
|
+
{services.length > 0 && (entities.length > 0 || dataProducts.length > 0) && ', '}
|
|
358
397
|
{entities.length > 0 && `${entities.length} entit${entities.length > 1 ? 'ies' : 'y'}`}
|
|
398
|
+
{entities.length > 0 && dataProducts.length > 0 && ', '}
|
|
399
|
+
{dataProducts.length > 0 && `${dataProducts.length} data product${dataProducts.length > 1 ? 's' : ''}`}
|
|
359
400
|
</span>
|
|
360
401
|
)}
|
|
361
402
|
</div>
|
|
@@ -417,9 +458,28 @@ const SubdomainSection = memo(({ subdomain }: { subdomain: any }) => {
|
|
|
417
458
|
</div>
|
|
418
459
|
)}
|
|
419
460
|
|
|
420
|
-
{
|
|
461
|
+
{/* Subdomain Data Products */}
|
|
462
|
+
{dataProducts.length > 0 && (
|
|
463
|
+
<div>
|
|
464
|
+
<div className="flex items-center gap-2 mb-3">
|
|
465
|
+
<CubeIcon className="h-4 w-4 text-purple-600 dark:text-purple-400" />
|
|
466
|
+
<h4 className="text-sm font-semibold text-[rgb(var(--ec-page-text))]">Data Products</h4>
|
|
467
|
+
<span className="text-xs text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-2 py-0.5 rounded-full font-medium">
|
|
468
|
+
{dataProducts.length}
|
|
469
|
+
</span>
|
|
470
|
+
</div>
|
|
471
|
+
<div className="space-y-3">
|
|
472
|
+
{dataProducts.map((dataProduct: any) => {
|
|
473
|
+
const dataProductId = dataProduct?.data?.id || dataProduct?.id;
|
|
474
|
+
return dataProductId ? <DataProductCard key={dataProductId} dataProduct={dataProduct} /> : null;
|
|
475
|
+
})}
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
)}
|
|
479
|
+
|
|
480
|
+
{entities.length === 0 && services.length === 0 && dataProducts.length === 0 && (
|
|
421
481
|
<p className="text-sm text-[rgb(var(--ec-icon-color))] italic text-center py-4">
|
|
422
|
-
No entities or
|
|
482
|
+
No entities, services, or data products in this subdomain
|
|
423
483
|
</p>
|
|
424
484
|
)}
|
|
425
485
|
</div>
|
|
@@ -439,6 +499,7 @@ export default function DomainGrid({ domain }: DomainGridProps) {
|
|
|
439
499
|
const subdomains = data.domains || [];
|
|
440
500
|
const entities = data.entities || [];
|
|
441
501
|
const services = data.services || [];
|
|
502
|
+
const dataProducts = data['data-products'] || [];
|
|
442
503
|
|
|
443
504
|
// Get services that are NOT in any subdomain
|
|
444
505
|
const subdomainServiceIds = useMemo(
|
|
@@ -452,6 +513,18 @@ export default function DomainGrid({ domain }: DomainGridProps) {
|
|
|
452
513
|
[subdomains]
|
|
453
514
|
);
|
|
454
515
|
|
|
516
|
+
// Get data products that are NOT in any subdomain
|
|
517
|
+
const subdomainDataProductIds = useMemo(
|
|
518
|
+
() =>
|
|
519
|
+
new Set(
|
|
520
|
+
subdomains.flatMap((sd: any) => {
|
|
521
|
+
const sdData = sd?.data || sd;
|
|
522
|
+
return (sdData?.['data-products'] || []).map((dp: any) => dp?.data?.id || dp?.id);
|
|
523
|
+
})
|
|
524
|
+
),
|
|
525
|
+
[subdomains]
|
|
526
|
+
);
|
|
527
|
+
|
|
455
528
|
const topLevelServices = useMemo(
|
|
456
529
|
() =>
|
|
457
530
|
services.filter((s: any) => {
|
|
@@ -461,6 +534,15 @@ export default function DomainGrid({ domain }: DomainGridProps) {
|
|
|
461
534
|
[services, subdomainServiceIds]
|
|
462
535
|
);
|
|
463
536
|
|
|
537
|
+
const topLevelDataProducts = useMemo(
|
|
538
|
+
() =>
|
|
539
|
+
dataProducts.filter((dp: any) => {
|
|
540
|
+
const dpId = dp?.data?.id || dp?.id;
|
|
541
|
+
return dpId && !subdomainDataProductIds.has(dpId);
|
|
542
|
+
}),
|
|
543
|
+
[dataProducts, subdomainDataProductIds]
|
|
544
|
+
);
|
|
545
|
+
|
|
464
546
|
return (
|
|
465
547
|
<div className="w-full">
|
|
466
548
|
{/* Domain Header - Doc style */}
|
|
@@ -548,13 +630,34 @@ export default function DomainGrid({ domain }: DomainGridProps) {
|
|
|
548
630
|
</div>
|
|
549
631
|
)}
|
|
550
632
|
|
|
633
|
+
{/* Top-level Data Products */}
|
|
634
|
+
{topLevelDataProducts.length > 0 && (
|
|
635
|
+
<div>
|
|
636
|
+
<div className="flex items-center gap-2 mb-4">
|
|
637
|
+
<CubeIcon className="h-5 w-5 text-purple-600 dark:text-purple-400" />
|
|
638
|
+
<h3 className="text-lg font-semibold text-[rgb(var(--ec-page-text))]">Data Products</h3>
|
|
639
|
+
<span className="text-sm text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-2.5 py-0.5 rounded-full font-medium">
|
|
640
|
+
{topLevelDataProducts.length}
|
|
641
|
+
</span>
|
|
642
|
+
</div>
|
|
643
|
+
<div className="space-y-3">
|
|
644
|
+
{topLevelDataProducts.map((dataProduct: any) => {
|
|
645
|
+
const dataProductId = dataProduct?.data?.id || dataProduct?.id;
|
|
646
|
+
return dataProductId ? <DataProductCard key={dataProductId} dataProduct={dataProduct} /> : null;
|
|
647
|
+
})}
|
|
648
|
+
</div>
|
|
649
|
+
</div>
|
|
650
|
+
)}
|
|
651
|
+
|
|
551
652
|
{/* Empty state */}
|
|
552
|
-
{entities.length === 0 && services.length === 0 && subdomains.length === 0 && (
|
|
653
|
+
{entities.length === 0 && services.length === 0 && dataProducts.length === 0 && subdomains.length === 0 && (
|
|
553
654
|
<div className="text-center py-12">
|
|
554
655
|
<div className="flex items-center justify-center w-16 h-16 mx-auto mb-4 bg-[rgb(var(--ec-content-hover))] rounded-2xl">
|
|
555
656
|
<RectangleGroupIcon className="h-8 w-8 text-[rgb(var(--ec-icon-color))]" />
|
|
556
657
|
</div>
|
|
557
|
-
<p className="text-[rgb(var(--ec-page-text-muted))]">
|
|
658
|
+
<p className="text-[rgb(var(--ec-page-text-muted))]">
|
|
659
|
+
This domain has no entities, services, data products, or subdomains defined.
|
|
660
|
+
</p>
|
|
558
661
|
</div>
|
|
559
662
|
)}
|
|
560
663
|
</div>
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BoltIcon,
|
|
3
|
+
ChatBubbleLeftIcon,
|
|
4
|
+
MagnifyingGlassIcon,
|
|
5
|
+
EnvelopeIcon,
|
|
6
|
+
ServerIcon,
|
|
7
|
+
DocumentCheckIcon,
|
|
8
|
+
} from '@heroicons/react/24/outline';
|
|
2
9
|
import type { CollectionMessageTypes, CollectionTypes } from '@types';
|
|
3
10
|
|
|
4
11
|
export const getCollectionStyles = (collection: CollectionMessageTypes | CollectionTypes) => {
|
|
@@ -11,6 +18,8 @@ export const getCollectionStyles = (collection: CollectionMessageTypes | Collect
|
|
|
11
18
|
return { color: 'green', Icon: MagnifyingGlassIcon };
|
|
12
19
|
case 'services':
|
|
13
20
|
return { color: 'pink', Icon: ServerIcon };
|
|
21
|
+
case 'data-products':
|
|
22
|
+
return { color: 'purple', Icon: DocumentCheckIcon };
|
|
14
23
|
default:
|
|
15
24
|
return { color: 'gray', Icon: EnvelopeIcon };
|
|
16
25
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { getNodesAndEdges as getNodesAndEdgesForDomainEntityMap } from '@utils/node-graphs/domain-entity-map';
|
|
14
14
|
import { getDomainsCanvasData } from '@utils/node-graphs/domains-canvas';
|
|
15
15
|
import { getNodesAndEdges as getNodesAndEdgesForFlows } from '@utils/node-graphs/flows-node-graph';
|
|
16
|
+
import { getNodesAndEdges as getNodesAndEdgesForDataProduct } from '@utils/node-graphs/data-products-node-graph';
|
|
16
17
|
import { buildUrl } from '@utils/url-builder';
|
|
17
18
|
import { getVersionFromCollection } from '@utils/collections/versions';
|
|
18
19
|
import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
|
|
@@ -61,6 +62,7 @@ const getNodesAndEdgesFunctions = {
|
|
|
61
62
|
domains: getNodesAndEdgesForDomain,
|
|
62
63
|
flows: getNodesAndEdgesForFlows,
|
|
63
64
|
containers: getNodesAndEdgesForContainer,
|
|
65
|
+
'data-products': getNodesAndEdgesForDataProduct,
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
let links: { label: string; url: string }[] = [];
|
|
@@ -39,6 +39,7 @@ import DataNode from './Nodes/Data';
|
|
|
39
39
|
import ViewNode from './Nodes/View';
|
|
40
40
|
import ActorNode from './Nodes/Actor';
|
|
41
41
|
import ExternalSystemNode2 from './Nodes/ExternalSystem2';
|
|
42
|
+
import DataProductNode from './Nodes/DataProduct';
|
|
42
43
|
import { Note as NoteNode } from '@eventcatalog/visualizer';
|
|
43
44
|
|
|
44
45
|
import type { CollectionEntry } from 'astro:content';
|
|
@@ -118,6 +119,8 @@ const NodeGraphBuilder = ({
|
|
|
118
119
|
data: DataNode,
|
|
119
120
|
view: ViewNode,
|
|
120
121
|
actor: ActorNode,
|
|
122
|
+
'data-product': DataProductNode,
|
|
123
|
+
'data-products': DataProductNode,
|
|
121
124
|
note: (props: any) => <NoteNode {...props} readOnly={true} />,
|
|
122
125
|
}) as unknown as NodeTypes,
|
|
123
126
|
[]
|
|
@@ -462,6 +465,7 @@ const NodeGraphBuilder = ({
|
|
|
462
465
|
actor: 'bg-yellow-500',
|
|
463
466
|
step: 'bg-gray-700',
|
|
464
467
|
data: 'bg-blue-600',
|
|
468
|
+
'data-products': 'bg-indigo-600',
|
|
465
469
|
};
|
|
466
470
|
|
|
467
471
|
let legendForDomains: { [key: string]: { count: number; colorClass: string; groupId: string } } = {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Handle } from '@xyflow/react';
|
|
2
|
+
import * as ContextMenu from '@radix-ui/react-context-menu';
|
|
3
|
+
import { buildUrl } from '@utils/url-builder';
|
|
4
|
+
import { Position } from '@xyflow/react';
|
|
5
|
+
import { Package } from 'lucide-react';
|
|
6
|
+
|
|
7
|
+
function classNames(...classes: any) {
|
|
8
|
+
return classes.filter(Boolean).join(' ');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface DataProductNodeProps {
|
|
12
|
+
data: {
|
|
13
|
+
mode: 'simple' | 'full';
|
|
14
|
+
dataProduct: {
|
|
15
|
+
id: string;
|
|
16
|
+
version: string;
|
|
17
|
+
name: string;
|
|
18
|
+
summary?: string;
|
|
19
|
+
inputs?: any[];
|
|
20
|
+
outputs?: any[];
|
|
21
|
+
owners?: any[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
selected?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function DataProductNode(props: DataProductNodeProps) {
|
|
28
|
+
const { id, version, name, summary, inputs = [], outputs = [], owners = [] } = props.data.dataProduct;
|
|
29
|
+
const mode = props.data.mode || 'simple';
|
|
30
|
+
const nodeLabel = 'Data Product';
|
|
31
|
+
const rotatedLabel = 'Product';
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ContextMenu.Root>
|
|
35
|
+
<ContextMenu.Trigger>
|
|
36
|
+
<div className="relative">
|
|
37
|
+
<Handle
|
|
38
|
+
type="target"
|
|
39
|
+
position={Position.Left}
|
|
40
|
+
style={{ width: 10, height: 10, background: '#6366f1', zIndex: 10 }}
|
|
41
|
+
className="bg-indigo-500"
|
|
42
|
+
/>
|
|
43
|
+
<Handle
|
|
44
|
+
type="source"
|
|
45
|
+
position={Position.Right}
|
|
46
|
+
style={{ width: 10, height: 10, background: '#6366f1', zIndex: 10 }}
|
|
47
|
+
className="bg-indigo-500"
|
|
48
|
+
/>
|
|
49
|
+
<div
|
|
50
|
+
className={classNames(
|
|
51
|
+
'w-full rounded-md border flex justify-start bg-white text-black',
|
|
52
|
+
props.selected ? 'border-indigo-600 ring-2 ring-indigo-500 shadow-lg' : 'border-indigo-400'
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
<div
|
|
56
|
+
className={`bg-gradient-to-b from-indigo-500 to-indigo-700 relative flex items-center w-5 justify-center rounded-l-sm text-indigo-100 border-r-[1px] border-indigo-500`}
|
|
57
|
+
>
|
|
58
|
+
<Package className="w-4 h-4 opacity-90 text-white absolute top-1" />
|
|
59
|
+
{mode === 'full' && (
|
|
60
|
+
<span
|
|
61
|
+
className={'w-1/2 text-center absolute bottom-1 text-[8px] text-white font-bold uppercase tracking-[3px]'}
|
|
62
|
+
style={{ transform: 'rotate(-90deg)' }}
|
|
63
|
+
>
|
|
64
|
+
{rotatedLabel}
|
|
65
|
+
</span>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
<div className="p-1 min-w-60 max-w-[min-content]">
|
|
69
|
+
<div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
|
|
70
|
+
<span className="text-xs font-bold block pt-0.5 pb-0.5">{name}</span>
|
|
71
|
+
<div className="flex justify-between">
|
|
72
|
+
<span className="text-[10px] font-light block pt-0.5 pb-0.5">v{version}</span>
|
|
73
|
+
{mode === 'simple' && (
|
|
74
|
+
<span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5">{nodeLabel}</span>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
{mode === 'full' && (
|
|
79
|
+
<div className="divide-y divide-gray-200">
|
|
80
|
+
<div className="leading-3 py-1">
|
|
81
|
+
<div
|
|
82
|
+
className="text-[8px] font-light overflow-hidden"
|
|
83
|
+
style={{
|
|
84
|
+
display: '-webkit-box',
|
|
85
|
+
WebkitLineClamp: 2,
|
|
86
|
+
WebkitBoxOrient: 'vertical',
|
|
87
|
+
}}
|
|
88
|
+
title={summary}
|
|
89
|
+
>
|
|
90
|
+
{summary}
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div className="grid grid-cols-2 gap-x-4 py-1">
|
|
95
|
+
<span className="text-xs" style={{ fontSize: '0.2em' }}>
|
|
96
|
+
Inputs: {inputs.length}
|
|
97
|
+
</span>
|
|
98
|
+
<span className="text-xs" style={{ fontSize: '0.2em' }}>
|
|
99
|
+
Outputs: {outputs.length}
|
|
100
|
+
</span>
|
|
101
|
+
<span className="text-xs" style={{ fontSize: '0.2em' }}>
|
|
102
|
+
Owners: {owners.length}
|
|
103
|
+
</span>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</ContextMenu.Trigger>
|
|
111
|
+
<ContextMenu.Portal>
|
|
112
|
+
<ContextMenu.Content className="min-w-[220px] bg-white rounded-md p-1 shadow-md border border-gray-200">
|
|
113
|
+
<ContextMenu.Item
|
|
114
|
+
asChild
|
|
115
|
+
className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-indigo-100 rounded-sm flex items-center"
|
|
116
|
+
>
|
|
117
|
+
<a href={buildUrl(`/docs/data-products/${id}/${version}`)}>Read documentation</a>
|
|
118
|
+
</ContextMenu.Item>
|
|
119
|
+
<ContextMenu.Separator className="h-[1px] bg-gray-200 m-1" />
|
|
120
|
+
<ContextMenu.Item asChild>
|
|
121
|
+
<a
|
|
122
|
+
href={buildUrl(`/visualiser/data-products/${id}/${version}`)}
|
|
123
|
+
className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-indigo-100 rounded-sm flex items-center"
|
|
124
|
+
>
|
|
125
|
+
View in Visualiser
|
|
126
|
+
</a>
|
|
127
|
+
</ContextMenu.Item>
|
|
128
|
+
</ContextMenu.Content>
|
|
129
|
+
</ContextMenu.Portal>
|
|
130
|
+
</ContextMenu.Root>
|
|
131
|
+
);
|
|
132
|
+
}
|