@eventcatalog/core 2.4.0 → 2.5.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +7 -0
  3. package/bin/dist/eventcatalog.cjs +5 -4
  4. package/bin/dist/eventcatalog.js +5 -4
  5. package/package.json +8 -6
  6. package/scripts/catalog-to-astro-content-directory.js +32 -1
  7. package/scripts/default-files-for-collections/flows.md +11 -0
  8. package/scripts/default-files-for-collections/pages.md +1 -0
  9. package/scripts/watcher.js +1 -2
  10. package/src/components/DocsNavigation.astro +5 -1
  11. package/src/components/MDX/NodeGraph/NodeGraph.astro +12 -0
  12. package/src/components/MDX/NodeGraph/NodeGraph.tsx +16 -4
  13. package/src/components/MDX/NodeGraph/Nodes/ExternalSystem.tsx +79 -0
  14. package/src/components/MDX/NodeGraph/Nodes/Service.tsx +0 -12
  15. package/src/components/MDX/NodeGraph/Nodes/Step.tsx +69 -0
  16. package/src/components/MDX/NodeGraph/Nodes/User.tsx +79 -0
  17. package/src/components/SideBars/DomainSideBar.astro +1 -1
  18. package/src/components/Tables/columns/FlowTableColumns.tsx +82 -0
  19. package/src/components/Tables/columns/index.tsx +3 -0
  20. package/src/content/config.ts +65 -5
  21. package/src/layouts/DiscoverLayout.astro +11 -1
  22. package/src/layouts/VisualiserLayout.astro +33 -22
  23. package/src/pages/discover/[type]/index.astro +3 -0
  24. package/src/pages/docs/[type]/[id]/[version]/index.astro +10 -2
  25. package/src/pages/docs/teams/[id]/index.astro +14 -0
  26. package/src/pages/docs/users/[id]/index.astro +23 -4
  27. package/src/pages/visualiser/[type]/[id]/[version]/index.astro +9 -2
  28. package/src/types/index.ts +1 -1
  29. package/src/utils/collections/util.ts +22 -0
  30. package/src/utils/commands/node-graph.ts +13 -2
  31. package/src/utils/config/catalog.ts +1 -0
  32. package/src/utils/domains/domains.ts +3 -5
  33. package/src/utils/domains/node-graph.ts +28 -9
  34. package/src/utils/events/node-graph.ts +13 -2
  35. package/src/utils/flows/flows.ts +59 -0
  36. package/src/utils/flows/node-graph.ts +153 -0
  37. package/src/utils/services/node-graph.ts +13 -2
  38. package/src/utils/teams.ts +7 -1
  39. package/src/utils/users.ts +8 -0
  40. package/tailwind.config.mjs +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @eventcatalog/core
2
2
 
3
+ ## 2.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 067fd89: feat(core): added flows to eventcatalog
8
+ - c336807: feat(core): only latest versions are now shown in visualizer
9
+ - 20c2cba: fix(core): fixing search not working after builds
10
+ - 7476fa6: fix(core): nodegraphs for domains now work with semver versions
11
+ - 737380a: feat(core): added ability to see how many domains a team and users own
12
+ - a1490d3: chore(core): updated astro versions
13
+ feat(core): visuzlier arrows stroke width increased
14
+ - 58d6a2d: chore(core): fixing default for flows
15
+
3
16
  ## 2.4.0
4
17
 
5
18
  ### Minor Changes
package/README.md CHANGED
@@ -129,6 +129,13 @@ If you have any questions, features or issues please raise any issue or pull req
129
129
 
130
130
  You can find the [contributing guidelines here](https://eventcatalog.dev/docs/contributing/overview).
131
131
 
132
+ ## Running the project locally
133
+
134
+ 1. Clone the repo
135
+ 1. Install required dependencies `npm run i`
136
+ 1. Run the command `npm run start:catalog`
137
+ - This will start the catalog found in `/examples` repo, locally on your machine
138
+
132
139
  [license-badge]: https://img.shields.io/github/license/event-catalog/eventcatalog.svg?color=yellow
133
140
  [license]: https://github.com/event-catalog/eventcatalog/blob/main/LICENSE
134
141
  [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
@@ -3095,9 +3095,6 @@ var ensureDir = (dir2) => {
3095
3095
  }
3096
3096
  };
3097
3097
  var copyCore = () => {
3098
- if (import_fs.default.existsSync(core)) {
3099
- import_fs.default.rmSync(core, { recursive: true });
3100
- }
3101
3098
  ensureDir(core);
3102
3099
  import_fs.default.cpSync(eventCatalogDir, core, {
3103
3100
  recursive: true,
@@ -3106,13 +3103,17 @@ var copyCore = () => {
3106
3103
  }
3107
3104
  });
3108
3105
  };
3109
- program2.command("dev").description("Run development server of EventCatalog").option("-d, --debug", "Output EventCatalog application information into your terminal").action((options) => {
3106
+ var clearCore = () => {
3107
+ if (import_fs.default.existsSync(core)) import_fs.default.rmSync(core, { recursive: true });
3108
+ };
3109
+ program2.command("dev").description("Run development server of EventCatalog").option("-d, --debug", "Output EventCatalog application information into your terminal").option("--force-recreate", "Recreate the eventcatalog-core directory", false).action((options) => {
3110
3110
  console.log("Setting up EventCatalog....");
3111
3111
  if (options.debug) {
3112
3112
  console.log("Debug mode enabled");
3113
3113
  console.log("PROJECT_DIR", dir);
3114
3114
  console.log("CATALOG_DIR", core);
3115
3115
  }
3116
+ if (options.forceRecreate) clearCore();
3116
3117
  copyCore();
3117
3118
  copyFolder((0, import_node_path.join)(dir, "public"), (0, import_node_path.join)(core, "public"));
3118
3119
  copyFile((0, import_node_path.join)(dir, "eventcatalog.config.js"), (0, import_node_path.join)(core, "eventcatalog.config.js"));
@@ -3062,9 +3062,6 @@ var ensureDir = (dir2) => {
3062
3062
  }
3063
3063
  };
3064
3064
  var copyCore = () => {
3065
- if (fs.existsSync(core)) {
3066
- fs.rmSync(core, { recursive: true });
3067
- }
3068
3065
  ensureDir(core);
3069
3066
  fs.cpSync(eventCatalogDir, core, {
3070
3067
  recursive: true,
@@ -3073,13 +3070,17 @@ var copyCore = () => {
3073
3070
  }
3074
3071
  });
3075
3072
  };
3076
- program2.command("dev").description("Run development server of EventCatalog").option("-d, --debug", "Output EventCatalog application information into your terminal").action((options) => {
3073
+ var clearCore = () => {
3074
+ if (fs.existsSync(core)) fs.rmSync(core, { recursive: true });
3075
+ };
3076
+ program2.command("dev").description("Run development server of EventCatalog").option("-d, --debug", "Output EventCatalog application information into your terminal").option("--force-recreate", "Recreate the eventcatalog-core directory", false).action((options) => {
3077
3077
  console.log("Setting up EventCatalog....");
3078
3078
  if (options.debug) {
3079
3079
  console.log("Debug mode enabled");
3080
3080
  console.log("PROJECT_DIR", dir);
3081
3081
  console.log("CATALOG_DIR", core);
3082
3082
  }
3083
+ if (options.forceRecreate) clearCore();
3083
3084
  copyCore();
3084
3085
  copyFolder(join(dir, "public"), join(core, "public"));
3085
3086
  copyFile(join(dir, "eventcatalog.config.js"), join(core, "eventcatalog.config.js"));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eventcatalog/core",
3
3
  "type": "module",
4
- "version": "2.4.0",
4
+ "version": "2.5.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,10 +30,10 @@
30
30
  "format:diff": "prettier --config .prettierrc --list-different \"**/*.{js,jsx,ts,tsx,json,astro}\""
31
31
  },
32
32
  "dependencies": {
33
- "@astrojs/check": "^0.7.0",
34
- "@astrojs/markdown-remark": "^5.1.0",
35
- "@astrojs/mdx": "^3.1.0",
36
- "@astrojs/react": "^3.5.0",
33
+ "@astrojs/check": "^0.9.2",
34
+ "@astrojs/markdown-remark": "^5.2.0",
35
+ "@astrojs/mdx": "^3.1.3",
36
+ "@astrojs/react": "^3.6.2",
37
37
  "@astrojs/tailwind": "^5.1.0",
38
38
  "@changesets/cli": "^2.27.5",
39
39
  "@headlessui/react": "^2.0.3",
@@ -44,13 +44,14 @@
44
44
  "@tanstack/react-table": "^8.17.3",
45
45
  "@types/dagre": "^0.7.52",
46
46
  "@types/node": "^20.14.2",
47
- "astro": "^4.10.1",
47
+ "astro": "^4.14.2",
48
48
  "astro-expressive-code": "^0.35.2",
49
49
  "astro-pagefind": "^1.5.0",
50
50
  "astro-seo": "^0.8.4",
51
51
  "dagre": "^0.8.5",
52
52
  "glob": "^10.4.1",
53
53
  "html-to-image": "^1.11.11",
54
+ "lodash.merge": "4.6.2",
54
55
  "mermaid": "^10.9.1",
55
56
  "rapidoc": "^9.3.4",
56
57
  "react": "^18.3.1",
@@ -65,6 +66,7 @@
65
66
  },
66
67
  "devDependencies": {
67
68
  "@parcel/watcher": "^2.4.1",
69
+ "@types/lodash.merge": "4.6.9",
68
70
  "@types/react": "^18.3.3",
69
71
  "@types/react-dom": "^18.3.0",
70
72
  "commander": "^12.1.0",
@@ -22,11 +22,12 @@ const ensureDirSync = async (filePath) => {
22
22
  }
23
23
  };
24
24
 
25
- const copyFiles = async ({ source, target, catalogFilesDir, pathToMarkdownFiles, pathToAllFiles, type }) => {
25
+ const copyFiles = async ({ source, target, catalogFilesDir, pathToMarkdownFiles, pathToAllFiles, type, ignore = null }) => {
26
26
  // Find all the event files
27
27
  const markdownFiles = await glob(pathToMarkdownFiles, {
28
28
  nodir: true,
29
29
  windowsPathsNoEscape: os.platform() == 'win32',
30
+ ignore: ignore,
30
31
  });
31
32
  const files = await glob(pathToAllFiles, {
32
33
  ignore: {
@@ -186,6 +187,11 @@ export const catalogToAstro = async (source, astroContentDir, catalogFilesDir) =
186
187
  path.join(source, 'services/**/**/changelog.md'),
187
188
  ],
188
189
  pathToAllFiles: [path.join(source, 'services/**'), path.join(source, 'domains/**/services/**')],
190
+ ignore: [
191
+ path.join(source, 'services/**/events/**'),
192
+ path.join(source, 'services/**/commands/**'),
193
+ path.join(source, 'services/**/flows/**'),
194
+ ],
189
195
  type: 'services',
190
196
  });
191
197
 
@@ -196,9 +202,34 @@ export const catalogToAstro = async (source, astroContentDir, catalogFilesDir) =
196
202
  catalogFilesDir,
197
203
  pathToMarkdownFiles: [path.join(source, 'domains/**/**/index.md'), path.join(source, 'domains/**/**/changelog.md')],
198
204
  pathToAllFiles: [path.join(source, 'domains/**')],
205
+ ignore: [
206
+ path.join(source, 'domains/**/services/**'),
207
+ path.join(source, 'domains/**/commands/**'),
208
+ path.join(source, 'domains/**/events/**'),
209
+ path.join(source, 'domains/**/flows/**'),
210
+ ],
199
211
  type: 'domains',
200
212
  });
201
213
 
214
+ // // Copy all the flow files over
215
+ await copyFiles({
216
+ source,
217
+ target: astroContentDir,
218
+ catalogFilesDir,
219
+ pathToMarkdownFiles: [
220
+ path.join(source, 'flows/**/**/index.md'),
221
+ path.join(source, 'flows/**/**/changelog.md'),
222
+ path.join(source, 'services/**/flows/**/index.md'),
223
+ path.join(source, 'domains/**/flows/**/index.md'),
224
+ ],
225
+ pathToAllFiles: [
226
+ path.join(source, 'flows/**'),
227
+ path.join(source, 'services/**/flows/**'),
228
+ path.join(source, 'domains/**/flows/**'),
229
+ ],
230
+ type: 'flows',
231
+ });
232
+
202
233
  // // Copy all the users
203
234
  await copyFiles({
204
235
  source,
@@ -0,0 +1,11 @@
1
+ ---
2
+ id: empty
3
+ steps:
4
+ - id: "empty"
5
+ title: "empty"
6
+ name: empty
7
+ version: 0.0.1
8
+ hidden: true
9
+ ---
10
+
11
+ <!-- Do not delete this file, required for EC, you an ignore this file -->
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  id: index
3
3
  slug: index
4
+ hidden: true
4
5
  ---
5
6
 
6
7
  <!-- Do not delete this file, required for EC, you an ignore this file -->
@@ -11,7 +11,7 @@ const catalogDirectory = process.env.CATALOG_DIR;
11
11
 
12
12
  const contentPath = path.join(catalogDirectory, 'src', 'content');
13
13
 
14
- const watchList = ['domains', 'commands', 'events', 'services', 'teams', 'users', 'pages', 'components'];
14
+ const watchList = ['domains', 'commands', 'events', 'services', 'teams', 'users', 'pages', 'components', 'flows'];
15
15
  // const absoluteWatchList = watchList.map((item) => path.join(projectDirectory, item));
16
16
 
17
17
  // confirm folders exist before watching them
@@ -62,7 +62,6 @@ for (let item of [...verifiedWatchList]) {
62
62
 
63
63
  // IF directory remove it
64
64
  if (type === 'delete') {
65
- console.log('eventPath', eventPath);
66
65
  fs.rmSync(newPath);
67
66
  }
68
67
  }
@@ -3,6 +3,7 @@ import { getCommands } from '@utils/commands';
3
3
  import { getDomains } from '@utils/domains/domains';
4
4
  import { getEvents } from '@utils/events';
5
5
  import { getServices } from '@utils/services/services';
6
+ import { getFlows } from '@utils/flows/flows';
6
7
  import { getTeams } from '@utils/teams';
7
8
  import { getUsers } from '@utils/users';
8
9
  import config, { type CatalogConfig } from '@eventcatalog';
@@ -12,19 +13,21 @@ const events = await getEvents({ getAllVersions: false });
12
13
  const commands = await getCommands({ getAllVersions: false });
13
14
  const services = await getServices({ getAllVersions: false });
14
15
  const domains = await getDomains({ getAllVersions: false });
16
+ const flows = await getFlows({ getAllVersions: false });
15
17
  const teams = await getTeams();
16
18
  const users = await getUsers();
17
19
 
18
20
  const messages = [...events, ...commands];
19
21
 
20
22
  // @ts-ignore for large catalogs https://github.com/event-catalog/eventcatalog/issues/552
21
- const allData = [...domains, ...services, ...messages, ...teams, ...users];
23
+ const allData = [...domains, ...services, ...messages, ...flows, ...teams, ...users];
22
24
 
23
25
  const eventCatalogConfig = config as CatalogConfig;
24
26
  const {
25
27
  services: servicesConfig,
26
28
  domains: domainsConfig,
27
29
  messages: messagesConfig,
30
+ flows: flowsConfig,
28
31
  teams: teamsConfig,
29
32
  users: usersConfig,
30
33
  showPageHeadings = true,
@@ -38,6 +41,7 @@ const visibleCollections: { [key: string]: boolean } = {
38
41
  events: getConfigValue(messagesConfig, 'visible', true),
39
42
  commands: getConfigValue(messagesConfig, 'visible', true),
40
43
  domains: getConfigValue(domainsConfig, 'visible', true),
44
+ flows: getConfigValue(flowsConfig, 'visible', true),
41
45
  services: getConfigValue(servicesConfig, 'visible', true),
42
46
  teams: getConfigValue(teamsConfig, 'visible', true),
43
47
  users: getConfigValue(usersConfig, 'visible', true),
@@ -4,6 +4,7 @@ import { getNodesAndEdges as getNodesAndEdgesForService } from '@utils/services/
4
4
  import { getNodesAndEdges as getNodesAndEdgesForEvent } from '@utils/events/node-graph';
5
5
  import { getNodesAndEdges as getNodesAndEdgesForCommand } from '@utils/commands/node-graph';
6
6
  import { getNodesAndEdges as getNodesAndEdgesForDomain } from '@utils/domains/node-graph';
7
+ import { getNodesAndEdges as getNodesAndEdgesForFlows } from '@utils/flows/node-graph';
7
8
 
8
9
  interface Props {
9
10
  id: string;
@@ -65,6 +66,17 @@ if (collection === 'domains') {
65
66
  nodes = eventNodes;
66
67
  edges = eventEdges;
67
68
  }
69
+
70
+ if (collection === 'flows') {
71
+ const { nodes: eventNodes, edges: eventEdges } = await getNodesAndEdgesForFlows({
72
+ id: id,
73
+ version,
74
+ mode,
75
+ });
76
+
77
+ nodes = eventNodes;
78
+ edges = eventEdges;
79
+ }
68
80
  ---
69
81
 
70
82
  <div>
@@ -13,7 +13,10 @@ import ReactFlow, {
13
13
  import 'reactflow/dist/style.css';
14
14
  import ServiceNode from './Nodes/Service';
15
15
  import EventNode from './Nodes/Event';
16
+ import UserNode from './Nodes/User';
17
+ import StepNode from './Nodes/Step';
16
18
  import CommandNode from './Nodes/Command';
19
+ import ExternalSystemNode from './Nodes/ExternalSystem';
17
20
  import type { CollectionEntry } from 'astro:content';
18
21
  import { navigate } from 'astro:transitions/client';
19
22
  import type { CollectionTypes } from '@types';
@@ -39,9 +42,19 @@ const getVisualiserUrlForCollection = (collectionItem: CollectionEntry<Collectio
39
42
 
40
43
  // const NodeGraphBuilder = ({ title, subtitle, includeBackground = true, includeControls = true }: Props) => {
41
44
  const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground = true, linkTo = 'docs' }: Props) => {
42
- const [nodes, _, onNodesChange] = useNodesState(initialNodes);
43
-
44
- const nodeTypes = useMemo(() => ({ services: ServiceNode, events: EventNode, commands: CommandNode }), []);
45
+ const nodeTypes = useMemo(
46
+ () => ({
47
+ services: ServiceNode,
48
+ events: EventNode,
49
+ commands: CommandNode,
50
+ step: StepNode,
51
+ user: UserNode,
52
+ actor: UserNode,
53
+ externalSystem: ExternalSystemNode,
54
+ }),
55
+ []
56
+ );
57
+ const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
45
58
  const nodeOrigin = [0.5, 0.5];
46
59
 
47
60
  const handleNodeClick = (_: any, node: Node) => {
@@ -60,7 +73,6 @@ const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground
60
73
  nodes={nodes}
61
74
  edges={edges}
62
75
  fitView
63
- nodesDraggable
64
76
  onNodesChange={onNodesChange}
65
77
  connectionLineType={ConnectionLineType.SmoothStep}
66
78
  // @ts-ignore
@@ -0,0 +1,79 @@
1
+ import { ServerIcon } from '@heroicons/react/16/solid';
2
+ import { GlobeAmericasIcon } from '@heroicons/react/20/solid';
3
+ import type { CollectionEntry } from 'astro:content';
4
+ import { Handle } from 'reactflow';
5
+
6
+ interface Data {
7
+ label: string;
8
+ bgColor: string;
9
+ color: string;
10
+ mode: 'simple' | 'full';
11
+ step: { id: string; title: string; summary: string; externalSystem: { name: string; summary?: string; url?: 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 ExternalSystemNode({ data, sourcePosition, targetPosition }: any) {
21
+ const { mode, step, showTarget = true, showSource = true } = data as Data;
22
+ const { externalSystem } = step;
23
+ const { name, summary, url } = externalSystem;
24
+
25
+ return (
26
+ <div
27
+ className={classNames(
28
+ `w-full rounded-md border flex justify-start bg-white text-black border-pink-500`,
29
+ mode === 'full' ? 'min-h-[7em]' : 'min-h-[2em]'
30
+ )}
31
+ >
32
+ <div
33
+ className={classNames(
34
+ 'bg-gradient-to-b from-pink-500 to-pink-700 relative flex items-center w-5 justify-center rounded-l-sm text-red-100-500',
35
+ `border-r-[1px] border-pink-500`
36
+ )}
37
+ >
38
+ <GlobeAmericasIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
39
+ {mode === 'full' && (
40
+ <span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
41
+ External
42
+ </span>
43
+ )}
44
+ </div>
45
+ <div className="p-1 min-w-60 max-w-[min-content]">
46
+ {showTarget && <Handle type="target" position={targetPosition} />}
47
+ {showSource && <Handle type="source" position={sourcePosition} />}
48
+ <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
49
+ <div className="h-full ">
50
+ <span className="text-sm font-bold pb-0.5 block w-full">{name}</span>
51
+ {mode === 'simple' && (
52
+ <div className="w-full text-right">
53
+ <span className=" w-full text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">External System</span>
54
+ </div>
55
+ )}
56
+ </div>
57
+ </div>
58
+ {mode === 'full' && (
59
+ <div className="divide-y divide-gray-200 ">
60
+ <div className="leading-3 py-1">
61
+ <span className="text-[8px] font-light">{summary}</span>
62
+ </div>
63
+
64
+ {url && (
65
+ <div className="grid grid-cols-2 gap-x-4 py-1">
66
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
67
+ URL:{' '}
68
+ <a href={url} target="_blank" className="text-purple-500 underline">
69
+ {url}
70
+ </a>
71
+ </span>
72
+ </div>
73
+ )}
74
+ </div>
75
+ )}
76
+ </div>
77
+ </div>
78
+ );
79
+ }
@@ -21,9 +21,6 @@ export default function ServiceNode({ data, sourcePosition, targetPosition }: an
21
21
 
22
22
  const { version, owners = [], sends = [], receives = [], name } = service.data;
23
23
 
24
- const renderTarget = showTarget;
25
- const renderSource = showSource;
26
-
27
24
  return (
28
25
  <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-pink-500')}>
29
26
  <div
@@ -42,21 +39,12 @@ export default function ServiceNode({ data, sourcePosition, targetPosition }: an
42
39
  <div className="p-1 min-w-60 max-w-[min-content]">
43
40
  {showTarget && <Handle type="target" position={targetPosition} />}
44
41
  {showSource && <Handle type="source" position={sourcePosition} />}
45
- {/* {mode === 'full' && (
46
- <div className="flex justify-end font-thin space-x-1 border-b border-orange-200 pb-0.5 " style={{ fontSize: '0.2em' }}>
47
- <span>Service</span>
48
- <ServerIcon className="w-2 h-2 opacity-90" />
49
- </div>
50
- )} */}
51
42
  <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
52
43
  <span className="text-xs font-bold block pt-0.5 pb-0.5">{name}</span>
53
44
  <div className="flex justify-between">
54
45
  <span className="text-[10px] font-light block pt-0.5 pb-0.5 ">v{version}</span>
55
46
  {mode === 'simple' && <span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Service</span>}
56
47
  </div>
57
- {/* <div className="flex justify-end">
58
- <span className="text-[8px] text-gray-500 font-light block pt-0.5 pb-0.5 ">View service</span>
59
- </div> */}
60
48
  </div>
61
49
  {mode === 'full' && (
62
50
  <div className="divide-y divide-gray-200 ">
@@ -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
+ }
@@ -42,7 +42,7 @@ const ownersList = owners.map((o) => ({
42
42
  client:load
43
43
  />
44
44
  <OwnersList
45
- title={`Service owners (${ownersList.length})`}
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