@eventcatalog/core 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +8 -1
- package/bin/dist/eventcatalog.cjs +5 -4
- package/bin/dist/eventcatalog.js +5 -4
- package/package.json +8 -6
- package/scripts/catalog-to-astro-content-directory.js +32 -1
- package/scripts/default-files-for-collections/flows.md +11 -0
- package/scripts/default-files-for-collections/pages.md +1 -0
- package/scripts/watcher.js +1 -2
- package/src/components/DocsNavigation.astro +5 -1
- package/src/components/MDX/Flow/Flow.astro +63 -0
- package/src/components/MDX/NodeGraph/NodeGraph.astro +12 -0
- package/src/components/MDX/NodeGraph/NodeGraph.tsx +75 -33
- package/src/components/MDX/NodeGraph/Nodes/ExternalSystem.tsx +79 -0
- package/src/components/MDX/NodeGraph/Nodes/Service.tsx +0 -12
- package/src/components/MDX/NodeGraph/Nodes/Step.tsx +69 -0
- package/src/components/MDX/NodeGraph/Nodes/User.tsx +79 -0
- package/src/components/MDX/components.tsx +2 -0
- package/src/components/SideBars/DomainSideBar.astro +1 -1
- package/src/components/Tables/columns/FlowTableColumns.tsx +82 -0
- package/src/components/Tables/columns/index.tsx +3 -0
- package/src/content/config.ts +65 -5
- package/src/layouts/DiscoverLayout.astro +11 -1
- package/src/layouts/VisualiserLayout.astro +33 -22
- package/src/pages/discover/[type]/index.astro +3 -0
- package/src/pages/docs/[type]/[id]/[version]/index.astro +12 -3
- package/src/pages/docs/teams/[id]/index.astro +14 -0
- package/src/pages/docs/users/[id]/index.astro +23 -4
- package/src/pages/visualiser/[type]/[id]/[version]/index.astro +9 -2
- package/src/types/index.ts +1 -1
- package/src/utils/collections/util.ts +22 -0
- package/src/utils/commands/node-graph.ts +13 -2
- package/src/utils/config/catalog.ts +1 -0
- package/src/utils/domains/domains.ts +3 -5
- package/src/utils/domains/node-graph.ts +28 -9
- package/src/utils/events/node-graph.ts +13 -2
- package/src/utils/flows/flows.ts +59 -0
- package/src/utils/flows/node-graph.ts +153 -0
- package/src/utils/services/node-graph.ts +16 -5
- package/src/utils/services/services.ts +3 -26
- package/src/utils/teams.ts +7 -1
- package/src/utils/users.ts +8 -0
- package/src/utils/versions/versions.ts +26 -0
- package/tailwind.config.mjs +1 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { EnvelopeIcon } from '@heroicons/react/16/solid';
|
|
2
|
+
import type { CollectionEntry } from 'astro:content';
|
|
3
|
+
import { Handle } from 'reactflow';
|
|
4
|
+
|
|
5
|
+
interface Data {
|
|
6
|
+
title: string;
|
|
7
|
+
label: string;
|
|
8
|
+
bgColor: string;
|
|
9
|
+
color: string;
|
|
10
|
+
mode: 'simple' | 'full';
|
|
11
|
+
step: { id: string; title: string; summary: string };
|
|
12
|
+
showTarget?: boolean;
|
|
13
|
+
showSource?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function classNames(...classes: any) {
|
|
17
|
+
return classes.filter(Boolean).join(' ');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function StepNode({ data, sourcePosition, targetPosition }: any) {
|
|
21
|
+
const { mode, step, showTarget = true, showSource = true } = data as Data;
|
|
22
|
+
|
|
23
|
+
const { title, summary } = step;
|
|
24
|
+
|
|
25
|
+
const renderTarget = showTarget || true;
|
|
26
|
+
const renderSource = showSource || true;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-blue-400 min-h-[3em]')}>
|
|
30
|
+
<div
|
|
31
|
+
className={classNames(
|
|
32
|
+
'bg-gradient-to-b from-gray-700 to-gray-700 relative flex items-center w-5 justify-center rounded-l-sm text-orange-100-500',
|
|
33
|
+
`border-r-[1px] border-gray-500`
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{mode === 'full' && (
|
|
37
|
+
<span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
|
|
38
|
+
Step
|
|
39
|
+
</span>
|
|
40
|
+
)}
|
|
41
|
+
</div>
|
|
42
|
+
<div className="p-1 min-w-60 max-w-[min-content]">
|
|
43
|
+
{renderTarget && <Handle type="target" position={targetPosition} />}
|
|
44
|
+
{renderSource && <Handle type="source" position={sourcePosition} />}
|
|
45
|
+
|
|
46
|
+
{!summary && (
|
|
47
|
+
<div className="h-full flex items-center">
|
|
48
|
+
<span className="text-sm font-bold block pb-0.5">{title}</span>
|
|
49
|
+
</div>
|
|
50
|
+
)}
|
|
51
|
+
|
|
52
|
+
{summary && (
|
|
53
|
+
<>
|
|
54
|
+
<div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
|
|
55
|
+
<span className="text-xs font-bold block pb-0.5">{title}</span>
|
|
56
|
+
</div>
|
|
57
|
+
{mode === 'full' && (
|
|
58
|
+
<div className="divide-y divide-gray-200 ">
|
|
59
|
+
<div className="leading-3 py-1">
|
|
60
|
+
<span className="text-[8px] font-light">{summary}</span>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
</>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { UserIcon } from '@heroicons/react/20/solid';
|
|
2
|
+
import { Handle } from 'reactflow';
|
|
3
|
+
|
|
4
|
+
interface Data {
|
|
5
|
+
title: string;
|
|
6
|
+
label: string;
|
|
7
|
+
bgColor: string;
|
|
8
|
+
color: string;
|
|
9
|
+
mode: 'simple' | 'full';
|
|
10
|
+
step: { id: string; title: string; summary: string; name: string; actor: { name: string } };
|
|
11
|
+
showTarget?: boolean;
|
|
12
|
+
showSource?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function classNames(...classes: any) {
|
|
16
|
+
return classes.filter(Boolean).join(' ');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default function UserNode({ data, sourcePosition, targetPosition }: any) {
|
|
20
|
+
const { mode, step, showTarget = true, showSource = true } = data as Data;
|
|
21
|
+
|
|
22
|
+
const { summary, actor: { name } = {} } = step;
|
|
23
|
+
|
|
24
|
+
const renderTarget = showTarget || true;
|
|
25
|
+
const renderSource = showSource || true;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
className={classNames(
|
|
30
|
+
`w-full rounded-md border flex justify-start bg-white text-black border-yellow-400`,
|
|
31
|
+
mode === 'full' ? 'min-h-[5em]' : 'min-h-[2em]'
|
|
32
|
+
)}
|
|
33
|
+
>
|
|
34
|
+
<div
|
|
35
|
+
className={classNames(
|
|
36
|
+
'bg-gradient-to-b from-yellow-400 to-yellow-600 relative flex items-center w-5 justify-center rounded-l-sm text-orange-100-500',
|
|
37
|
+
`border-r-[1px] border-yellow-500`
|
|
38
|
+
)}
|
|
39
|
+
>
|
|
40
|
+
<UserIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
|
|
41
|
+
{mode === 'full' && (
|
|
42
|
+
<span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
|
|
43
|
+
ACTOR
|
|
44
|
+
</span>
|
|
45
|
+
)}
|
|
46
|
+
</div>
|
|
47
|
+
<div className="p-1 min-w-60 max-w-[min-content]">
|
|
48
|
+
{renderTarget && <Handle type="target" position={targetPosition} />}
|
|
49
|
+
{renderSource && <Handle type="source" position={sourcePosition} />}
|
|
50
|
+
|
|
51
|
+
{(!summary || mode !== 'full') && (
|
|
52
|
+
<div className="h-full ">
|
|
53
|
+
<span className="text-sm font-bold block pb-0.5 block w-full">{name}</span>
|
|
54
|
+
{mode === 'simple' && (
|
|
55
|
+
<div className="w-full text-right">
|
|
56
|
+
<span className=" w-full text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Event</span>
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
)}
|
|
61
|
+
|
|
62
|
+
{summary && mode === 'full' && (
|
|
63
|
+
<>
|
|
64
|
+
<div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
|
|
65
|
+
<span className="text-xs font-bold block pb-0.5">{name}</span>
|
|
66
|
+
</div>
|
|
67
|
+
{mode === 'full' && (
|
|
68
|
+
<div className="divide-y divide-gray-200 ">
|
|
69
|
+
<div className="leading-3 py-1">
|
|
70
|
+
<span className="text-[8px] font-light">{summary}</span>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
</>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -3,6 +3,7 @@ import Schema from '@components/MDX/Schema';
|
|
|
3
3
|
import File from '@components/MDX/File';
|
|
4
4
|
import Accordion from '@components/MDX/Accordion/Accordion.astro';
|
|
5
5
|
import AccordionGroup from '@components/MDX/Accordion/AccordionGroup.astro';
|
|
6
|
+
import Flow from '@components/MDX/Flow/Flow.astro';
|
|
6
7
|
import Admonition from '@components/MDX/Admonition';
|
|
7
8
|
import OpenAPI from '@components/MDX/OpenAPI/OpenAPI';
|
|
8
9
|
|
|
@@ -14,6 +15,7 @@ const components = (props: any) => {
|
|
|
14
15
|
return {
|
|
15
16
|
Accordion,
|
|
16
17
|
AccordionGroup,
|
|
18
|
+
Flow,
|
|
17
19
|
Admonition: (mdxProp: any) => <Admonition {...mdxProp} {...props} />,
|
|
18
20
|
File: (mdxProp: any) => File({ ...props, ...mdxProp }),
|
|
19
21
|
NodeGraph: (mdxProp: any) => NodeGraphPortal({ ...props.data, ...mdxProp }),
|
|
@@ -42,7 +42,7 @@ const ownersList = owners.map((o) => ({
|
|
|
42
42
|
client:load
|
|
43
43
|
/>
|
|
44
44
|
<OwnersList
|
|
45
|
-
title={`
|
|
45
|
+
title={`Domain owners (${ownersList.length})`}
|
|
46
46
|
owners={ownersList}
|
|
47
47
|
emptyMessage={`This domain does not have any documented owners.`}
|
|
48
48
|
client:load
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ServerIcon } from '@heroicons/react/20/solid';
|
|
2
|
+
import { RectangleGroupIcon } from '@heroicons/react/20/solid';
|
|
3
|
+
import { createColumnHelper } from '@tanstack/react-table';
|
|
4
|
+
import type { CollectionEntry } from 'astro:content';
|
|
5
|
+
import { filterByName, filterCollectionByName } from '../filters/custom-filters';
|
|
6
|
+
import { buildUrl } from '@utils/url-builder';
|
|
7
|
+
import { QueueListIcon } from '@heroicons/react/24/solid';
|
|
8
|
+
|
|
9
|
+
const columnHelper = createColumnHelper<CollectionEntry<'flows'>>();
|
|
10
|
+
|
|
11
|
+
export const columns = () => [
|
|
12
|
+
columnHelper.accessor('data.name', {
|
|
13
|
+
id: 'name',
|
|
14
|
+
header: () => <span>Flow</span>,
|
|
15
|
+
cell: (info) => {
|
|
16
|
+
const flowRaw = info.row.original;
|
|
17
|
+
const color = 'teal';
|
|
18
|
+
return (
|
|
19
|
+
<div className=" group ">
|
|
20
|
+
<a
|
|
21
|
+
href={buildUrl(`/docs/${flowRaw.collection}/${flowRaw.data.id}/${flowRaw.data.version}`)}
|
|
22
|
+
className={`group-hover:text-${color}-500 flex space-x-1 items-center`}
|
|
23
|
+
>
|
|
24
|
+
<div className={`flex items-center border border-gray-300 shadow-sm rounded-md group-hover:border-${color}-400`}>
|
|
25
|
+
<span className="flex items-center">
|
|
26
|
+
<span className={`bg-${color}-500 group-hover:bg-${color}-600 h-full rounded-tl rounded-bl p-1`}>
|
|
27
|
+
<QueueListIcon className="h-4 w-4 text-white" />
|
|
28
|
+
</span>
|
|
29
|
+
<span className="leading-none px-2 group-hover:underline group-hover:text-purple-500 font-light">
|
|
30
|
+
{flowRaw.data.name} (v{flowRaw.data.version})
|
|
31
|
+
</span>
|
|
32
|
+
</span>
|
|
33
|
+
</div>
|
|
34
|
+
</a>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
footer: (info) => info.column.id,
|
|
39
|
+
meta: {
|
|
40
|
+
filterVariant: 'name',
|
|
41
|
+
},
|
|
42
|
+
filterFn: filterByName,
|
|
43
|
+
}),
|
|
44
|
+
columnHelper.accessor('data.version', {
|
|
45
|
+
header: () => <span>Version</span>,
|
|
46
|
+
cell: (info) => {
|
|
47
|
+
const service = info.row.original;
|
|
48
|
+
return (
|
|
49
|
+
<div className="text-left font-light">{`v${info.getValue()} ${service.data.latestVersion === service.data.version ? '(latest)' : ''}`}</div>
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
footer: (info) => info.column.id,
|
|
53
|
+
}),
|
|
54
|
+
columnHelper.accessor('data.summary', {
|
|
55
|
+
id: 'summary',
|
|
56
|
+
header: () => 'Summary',
|
|
57
|
+
cell: (info) => <span className="font-light ">{info.renderValue()}</span>,
|
|
58
|
+
footer: (info) => info.column.id,
|
|
59
|
+
meta: {
|
|
60
|
+
showFilter: false,
|
|
61
|
+
className: 'max-w-md',
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
columnHelper.accessor('data.name', {
|
|
65
|
+
header: () => <span />,
|
|
66
|
+
cell: (info) => {
|
|
67
|
+
const domain = info.row.original;
|
|
68
|
+
return (
|
|
69
|
+
<a
|
|
70
|
+
className="hover:text-purple-500 hover:underline px-4 font-light"
|
|
71
|
+
href={buildUrl(`/visualiser/${domain.collection}/${domain.data.id}/${domain.data.version}`)}
|
|
72
|
+
>
|
|
73
|
+
Visualiser →
|
|
74
|
+
</a>
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
id: 'actions',
|
|
78
|
+
meta: {
|
|
79
|
+
showFilter: false,
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { columns as MessageTableColumns } from './MessageTableColumns';
|
|
2
2
|
import { columns as ServiceTableColumns } from './ServiceTableColumns';
|
|
3
3
|
import { columns as DomainTableColumns } from './DomainTableColumns';
|
|
4
|
+
import { columns as FlowTableColumns } from './FlowTableColumns';
|
|
4
5
|
|
|
5
6
|
export const getColumnsByCollection = (collection: string): any => {
|
|
6
7
|
switch (collection) {
|
|
@@ -11,6 +12,8 @@ export const getColumnsByCollection = (collection: string): any => {
|
|
|
11
12
|
return ServiceTableColumns();
|
|
12
13
|
case 'domains':
|
|
13
14
|
return DomainTableColumns();
|
|
15
|
+
case 'flows':
|
|
16
|
+
return FlowTableColumns();
|
|
14
17
|
default:
|
|
15
18
|
return [];
|
|
16
19
|
}
|
package/src/content/config.ts
CHANGED
|
@@ -13,6 +13,11 @@ const pages = defineCollection({
|
|
|
13
13
|
}),
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
const pointer = z.object({
|
|
17
|
+
id: z.string(),
|
|
18
|
+
version: z.string().optional().default('latest'),
|
|
19
|
+
});
|
|
20
|
+
|
|
16
21
|
const changelogs = defineCollection({
|
|
17
22
|
type: 'content',
|
|
18
23
|
schema: z.object({
|
|
@@ -58,6 +63,63 @@ const baseSchema = z.object({
|
|
|
58
63
|
.optional(),
|
|
59
64
|
});
|
|
60
65
|
|
|
66
|
+
const flowStep = z
|
|
67
|
+
.union([
|
|
68
|
+
// Can be a string or a number just to reference a step
|
|
69
|
+
z.union([z.string(), z.number()]),
|
|
70
|
+
z
|
|
71
|
+
.object({
|
|
72
|
+
id: z.union([z.string(), z.number()]),
|
|
73
|
+
label: z.string().optional(),
|
|
74
|
+
})
|
|
75
|
+
.optional(),
|
|
76
|
+
])
|
|
77
|
+
.optional();
|
|
78
|
+
|
|
79
|
+
const flows = defineCollection({
|
|
80
|
+
type: 'content',
|
|
81
|
+
schema: z
|
|
82
|
+
.object({
|
|
83
|
+
steps: z.array(
|
|
84
|
+
z
|
|
85
|
+
.object({
|
|
86
|
+
id: z.union([z.string(), z.number()]),
|
|
87
|
+
type: z.enum(['node', 'message', 'user', 'actor']).optional(),
|
|
88
|
+
title: z.string(),
|
|
89
|
+
summary: z.string().optional(),
|
|
90
|
+
message: pointer.optional(),
|
|
91
|
+
service: pointer.optional(),
|
|
92
|
+
actor: z
|
|
93
|
+
.object({
|
|
94
|
+
name: z.string(),
|
|
95
|
+
})
|
|
96
|
+
.optional(),
|
|
97
|
+
externalSystem: z
|
|
98
|
+
.object({
|
|
99
|
+
name: z.string(),
|
|
100
|
+
summary: z.string().optional(),
|
|
101
|
+
url: z.string().url().optional(),
|
|
102
|
+
})
|
|
103
|
+
.optional(),
|
|
104
|
+
next_step: flowStep,
|
|
105
|
+
next_steps: z.array(flowStep).optional(),
|
|
106
|
+
})
|
|
107
|
+
.refine((data) => {
|
|
108
|
+
if (!data.message && !data.service && !data.actor) return true;
|
|
109
|
+
// Cant have both next_steps and next_steps
|
|
110
|
+
if (data.next_step && data.next_steps) return false;
|
|
111
|
+
// Either message or service or actor must be present, but not all
|
|
112
|
+
return (
|
|
113
|
+
(data.message && !data.service && !data.actor) ||
|
|
114
|
+
(!data.message && data.service) ||
|
|
115
|
+
(data.actor && !data.message && !data.service)
|
|
116
|
+
);
|
|
117
|
+
})
|
|
118
|
+
),
|
|
119
|
+
})
|
|
120
|
+
.merge(baseSchema),
|
|
121
|
+
});
|
|
122
|
+
|
|
61
123
|
const events = defineCollection({
|
|
62
124
|
type: 'content',
|
|
63
125
|
schema: z
|
|
@@ -78,11 +140,6 @@ const commands = defineCollection({
|
|
|
78
140
|
.merge(baseSchema),
|
|
79
141
|
});
|
|
80
142
|
|
|
81
|
-
const pointer = z.object({
|
|
82
|
-
id: z.string(),
|
|
83
|
-
version: z.string().optional().default('latest'),
|
|
84
|
-
});
|
|
85
|
-
|
|
86
143
|
const services = defineCollection({
|
|
87
144
|
type: 'content',
|
|
88
145
|
schema: z
|
|
@@ -112,6 +169,7 @@ const users = defineCollection({
|
|
|
112
169
|
hidden: z.boolean().optional(),
|
|
113
170
|
email: z.string().optional(),
|
|
114
171
|
slackDirectMessageUrl: z.string().optional(),
|
|
172
|
+
ownedDomains: z.array(reference('domains')).optional(),
|
|
115
173
|
ownedServices: z.array(reference('services')).optional(),
|
|
116
174
|
ownedEvents: z.array(reference('events')).optional(),
|
|
117
175
|
ownedCommands: z.array(reference('commands')).optional(),
|
|
@@ -130,6 +188,7 @@ const teams = defineCollection({
|
|
|
130
188
|
slackDirectMessageUrl: z.string().optional(),
|
|
131
189
|
members: z.array(reference('users')).optional(),
|
|
132
190
|
ownedCommands: z.array(reference('commands')).optional(),
|
|
191
|
+
ownedDomains: z.array(reference('domains')).optional(),
|
|
133
192
|
ownedServices: z.array(reference('services')).optional(),
|
|
134
193
|
ownedEvents: z.array(reference('events')).optional(),
|
|
135
194
|
}),
|
|
@@ -142,6 +201,7 @@ export const collections = {
|
|
|
142
201
|
users,
|
|
143
202
|
teams,
|
|
144
203
|
domains,
|
|
204
|
+
flows,
|
|
145
205
|
pages,
|
|
146
206
|
changelogs,
|
|
147
207
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Table } from '@components/Tables/Table';
|
|
3
|
-
import { RectangleGroupIcon } from '@heroicons/react/24/outline';
|
|
3
|
+
import { QueueListIcon, RectangleGroupIcon } from '@heroicons/react/24/outline';
|
|
4
4
|
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
|
|
5
5
|
import ServerIcon from '@heroicons/react/24/outline/ServerIcon';
|
|
6
6
|
import PlainPage from '@layouts/PlainPage.astro';
|
|
7
7
|
import { getCommands } from '@utils/commands';
|
|
8
8
|
import { getDomains } from '@utils/domains/domains';
|
|
9
|
+
import { getFlows } from '@utils/flows/flows';
|
|
9
10
|
import { getEvents } from '@utils/events';
|
|
10
11
|
import { getServices } from '@utils/services/services';
|
|
11
12
|
import { buildUrl } from '@utils/url-builder';
|
|
@@ -14,6 +15,7 @@ const events = await getEvents();
|
|
|
14
15
|
const commands = await getCommands();
|
|
15
16
|
const services = await getServices();
|
|
16
17
|
const domains = await getDomains();
|
|
18
|
+
const flows = await getFlows();
|
|
17
19
|
|
|
18
20
|
const { title, subtitle, data, type } = Astro.props;
|
|
19
21
|
const currentPath = Astro.url.pathname;
|
|
@@ -51,6 +53,14 @@ const tabs = [
|
|
|
51
53
|
activeColor: 'yellow',
|
|
52
54
|
enabled: domains.length > 0,
|
|
53
55
|
},
|
|
56
|
+
{
|
|
57
|
+
label: `Flows (${flows.length})`,
|
|
58
|
+
href: buildUrl('/discover/flows'),
|
|
59
|
+
isActive: currentPath === '/discover/flows',
|
|
60
|
+
icon: QueueListIcon,
|
|
61
|
+
activeColor: 'teal',
|
|
62
|
+
enabled: flows.length > 0,
|
|
63
|
+
},
|
|
54
64
|
];
|
|
55
65
|
---
|
|
56
66
|
|
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
import BasicList from '@components/Lists/BasicList';
|
|
3
3
|
import PlainPage from '@layouts/PlainPage.astro';
|
|
4
|
-
import type { CollectionTypes } from '@types';
|
|
5
4
|
import { getCommands } from '@utils/commands';
|
|
6
5
|
import { getDomains } from '@utils/domains/domains';
|
|
7
6
|
import { getEvents } from '@utils/events';
|
|
7
|
+
import { getFlows } from '@utils/flows/flows';
|
|
8
8
|
import { getServices } from '@utils/services/services';
|
|
9
9
|
import { buildUrl } from '@utils/url-builder';
|
|
10
|
-
import type { CollectionEntry } from 'astro:content';
|
|
11
10
|
import { ViewTransitions } from 'astro:transitions';
|
|
12
11
|
|
|
13
|
-
const [services, events, commands, domains] = await Promise.all([
|
|
12
|
+
const [services, events, commands, domains, flows] = await Promise.all([
|
|
13
|
+
getServices(),
|
|
14
|
+
getEvents(),
|
|
15
|
+
getCommands(),
|
|
16
|
+
getDomains(),
|
|
17
|
+
getFlows(),
|
|
18
|
+
]);
|
|
14
19
|
|
|
15
20
|
// @ts-ignore for large catalogs https://github.com/event-catalog/eventcatalog/issues/552
|
|
16
|
-
const navItems = [...domains, ...services, ...events, ...commands];
|
|
21
|
+
const navItems = [...domains, ...services, ...events, ...commands, ...flows];
|
|
17
22
|
|
|
18
|
-
const navigation = navItems
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
const navigation = navItems
|
|
24
|
+
.filter((item) => item.data.version === item.data.latestVersion)
|
|
25
|
+
.reduce((acc, item) => {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
const group = acc[item.collection] || [];
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}, {}) as any;
|
|
29
|
+
return {
|
|
30
|
+
...acc,
|
|
31
|
+
[item.collection]: [...group, item],
|
|
32
|
+
};
|
|
33
|
+
}, {}) as any;
|
|
27
34
|
|
|
28
35
|
const currentPath = Astro.url.pathname;
|
|
29
36
|
const { title, description } = Astro.props;
|
|
@@ -53,16 +60,20 @@ const getColor = (collection: string) => {
|
|
|
53
60
|
>
|
|
54
61
|
{
|
|
55
62
|
Object.keys(navigation).map((key: any) => {
|
|
56
|
-
const items = navigation[key]
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
const items = navigation[key]
|
|
64
|
+
.map((item: any) => {
|
|
65
|
+
const isCurrent = currentPath.includes(`${item.collection}/${item.data.id}/${item.data.version}`);
|
|
66
|
+
const isLatest = item.data.version === item.data.latestVersion;
|
|
67
|
+
if (!isLatest) return null;
|
|
68
|
+
return {
|
|
69
|
+
label: item.data.name,
|
|
70
|
+
version: item.data.version,
|
|
71
|
+
color: getColor(item.collection),
|
|
72
|
+
href: buildUrl(`/visualiser/${item.collection}/${item.data.id}/${item.data.version}`),
|
|
73
|
+
active: isCurrent,
|
|
74
|
+
};
|
|
75
|
+
})
|
|
76
|
+
.filter((n: any) => n !== null);
|
|
66
77
|
return (
|
|
67
78
|
<BasicList
|
|
68
79
|
title={`${key} (${navigation[key].length})`}
|
|
@@ -6,12 +6,14 @@ import type { CollectionTypes } from '@types';
|
|
|
6
6
|
import { getCommands } from '@utils/commands';
|
|
7
7
|
import { getServices } from '@utils/services/services';
|
|
8
8
|
import { getDomains } from '@utils/domains/domains';
|
|
9
|
+
import { getFlows } from '@utils/flows/flows';
|
|
9
10
|
|
|
10
11
|
export async function getStaticPaths() {
|
|
11
12
|
const events = await getEvents();
|
|
12
13
|
const commands = await getCommands();
|
|
13
14
|
const services = await getServices();
|
|
14
15
|
const domains = await getDomains();
|
|
16
|
+
const flows = await getFlows();
|
|
15
17
|
|
|
16
18
|
const buildPage = (type: string, collection: CollectionEntry<CollectionTypes>[]) => {
|
|
17
19
|
return {
|
|
@@ -30,6 +32,7 @@ export async function getStaticPaths() {
|
|
|
30
32
|
buildPage('commands', commands),
|
|
31
33
|
buildPage('services', services),
|
|
32
34
|
buildPage('domains', domains),
|
|
35
|
+
buildPage('flows', flows),
|
|
33
36
|
];
|
|
34
37
|
}
|
|
35
38
|
|
|
@@ -5,6 +5,7 @@ import Footer from '@layouts/Footer.astro';
|
|
|
5
5
|
|
|
6
6
|
import components from '@components/MDX/components';
|
|
7
7
|
import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
|
|
8
|
+
import SchemaViewer from '@components/MDX/SchemaViewer/SchemaViewer.astro';
|
|
8
9
|
|
|
9
10
|
// SideBars
|
|
10
11
|
import ServiceSideBar from '@components/SideBars/ServiceSideBar.astro';
|
|
@@ -13,18 +14,20 @@ import MessageSideBar from '@components/SideBars/MessageSideBar.astro';
|
|
|
13
14
|
import { getEvents } from '@utils/events';
|
|
14
15
|
import { getServices } from '@utils/services/services';
|
|
15
16
|
import { getCommands } from '@utils/commands';
|
|
16
|
-
import { EnvelopeIcon, PencilIcon, RectangleGroupIcon, ServerIcon } from '@heroicons/react/24/outline';
|
|
17
|
+
import { EnvelopeIcon, PencilIcon, QueueListIcon, RectangleGroupIcon, ServerIcon } from '@heroicons/react/24/outline';
|
|
17
18
|
import { getDomains } from '@utils/domains/domains';
|
|
18
19
|
import DomainSideBar from '@components/SideBars/DomainSideBar.astro';
|
|
19
20
|
import type { CollectionTypes } from '@types';
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
import { buildUrl } from '@utils/url-builder';
|
|
23
|
+
import { getFlows } from '@utils/flows/flows';
|
|
22
24
|
|
|
23
25
|
export async function getStaticPaths() {
|
|
24
26
|
const events = await getEvents();
|
|
25
27
|
const commands = await getCommands();
|
|
26
28
|
const services = await getServices();
|
|
27
29
|
const domains = await getDomains();
|
|
30
|
+
const flows = await getFlows();
|
|
28
31
|
|
|
29
32
|
const buildPages = (collection: CollectionEntry<CollectionTypes>[]) => {
|
|
30
33
|
return collection.map((item) => ({
|
|
@@ -40,7 +43,7 @@ export async function getStaticPaths() {
|
|
|
40
43
|
}));
|
|
41
44
|
};
|
|
42
45
|
|
|
43
|
-
return [...buildPages(domains), ...buildPages(events), ...buildPages(services), ...buildPages(commands)];
|
|
46
|
+
return [...buildPages(domains), ...buildPages(events), ...buildPages(services), ...buildPages(commands), ...buildPages(flows)];
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
const props = Astro.props;
|
|
@@ -70,6 +73,12 @@ const getBadge = () => {
|
|
|
70
73
|
class: 'text-yellow-400',
|
|
71
74
|
};
|
|
72
75
|
}
|
|
76
|
+
|
|
77
|
+
if (props.collection === 'flows') {
|
|
78
|
+
return { backgroundColor: 'teal', textColor: 'teal', content: 'Flow', icon: QueueListIcon, class: 'text-gray' };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { backgroundColor: 'teal', textColor: 'teal', content: '', icon: QueueListIcon, class: 'text-gray' };
|
|
73
82
|
};
|
|
74
83
|
|
|
75
84
|
const badges = [getBadge(), ...contentBadges];
|
|
@@ -34,6 +34,7 @@ const { Content } = await render();
|
|
|
34
34
|
const membersRaw = props.data.members || [];
|
|
35
35
|
const members = await Promise.all(membersRaw.map((m) => getEntry(m)));
|
|
36
36
|
|
|
37
|
+
const domains = props.data.ownedDomains as CollectionEntry<'domains'>[];
|
|
37
38
|
const services = props.data.ownedServices as CollectionEntry<'services'>[];
|
|
38
39
|
const events = props.data.ownedEvents as CollectionEntry<'events'>[];
|
|
39
40
|
const commands = props.data.ownedCommands as CollectionEntry<'commands'>[];
|
|
@@ -46,6 +47,12 @@ const membersList = members.map((o) => ({
|
|
|
46
47
|
href: buildUrl(`/docs/${o.collection}/${o.data.id}`),
|
|
47
48
|
}));
|
|
48
49
|
|
|
50
|
+
const ownedDomainsList = domains.map((p) => ({
|
|
51
|
+
label: `${p.data.name}`,
|
|
52
|
+
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
53
|
+
tag: `v${p.data.version}`,
|
|
54
|
+
}));
|
|
55
|
+
|
|
49
56
|
const ownedServicesList = services.map((p) => ({
|
|
50
57
|
label: `${p.data.name} (service)`,
|
|
51
58
|
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
@@ -112,6 +119,13 @@ const ownedEventsList = [...events, ...commands].map((p) => ({
|
|
|
112
119
|
</main>
|
|
113
120
|
<aside class="sticky top-20 h-[calc(100vh-theme(spacing.16))] w-56 overflow-y-auto">
|
|
114
121
|
<div class="divide-y-2 divide-gray-100">
|
|
122
|
+
<PillList
|
|
123
|
+
color="pink"
|
|
124
|
+
title={`Owned domains (${ownedDomainsList.length})`}
|
|
125
|
+
pills={ownedDomainsList}
|
|
126
|
+
emptyMessage={`${props.data.name} does not own any domains.`}
|
|
127
|
+
client:load
|
|
128
|
+
/>
|
|
115
129
|
<PillList
|
|
116
130
|
color="blue"
|
|
117
131
|
title={`Owned services (${ownedServicesList.length})`}
|