@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @eventcatalog/core
|
|
2
2
|
|
|
3
|
+
## 2.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2bbccf8: feat(core): added new MDX component for Flows
|
|
8
|
+
|
|
9
|
+
## 2.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 067fd89: feat(core): added flows to eventcatalog
|
|
14
|
+
- c336807: feat(core): only latest versions are now shown in visualizer
|
|
15
|
+
- 20c2cba: fix(core): fixing search not working after builds
|
|
16
|
+
- 7476fa6: fix(core): nodegraphs for domains now work with semver versions
|
|
17
|
+
- 737380a: feat(core): added ability to see how many domains a team and users own
|
|
18
|
+
- a1490d3: chore(core): updated astro versions
|
|
19
|
+
feat(core): visuzlier arrows stroke width increased
|
|
20
|
+
- 58d6a2d: chore(core): fixing default for flows
|
|
21
|
+
|
|
3
22
|
## 2.4.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ You can see the markdown files that generated the website in the GitHub repo und
|
|
|
113
113
|
|
|
114
114
|
Interested in collaborating with us? Our offerings include dedicated support, priority assistance, feature development, custom integrations, and more.
|
|
115
115
|
|
|
116
|
-
Find more details on our [
|
|
116
|
+
Find more details on our [services page](https://eventcatalog.dev/services).
|
|
117
117
|
|
|
118
118
|
# Looking for v1?
|
|
119
119
|
|
|
@@ -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
|
-
|
|
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"));
|
package/bin/dist/eventcatalog.js
CHANGED
|
@@ -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
|
-
|
|
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
|
+
"version": "2.5.1",
|
|
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.
|
|
34
|
-
"@astrojs/markdown-remark": "^5.
|
|
35
|
-
"@astrojs/mdx": "^3.1.
|
|
36
|
-
"@astrojs/react": "^3.
|
|
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.
|
|
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,
|
package/scripts/watcher.js
CHANGED
|
@@ -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),
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getFlows } from '@utils/flows/flows';
|
|
3
|
+
import { getNodesAndEdges } from '@utils/flows/node-graph';
|
|
4
|
+
import Admonition from '@components/MDX/Admonition';
|
|
5
|
+
import NodeGraph from '../NodeGraph/NodeGraph';
|
|
6
|
+
import { getVersionFromCollection } from '@utils/versions/versions';
|
|
7
|
+
|
|
8
|
+
const { id, version = 'latest', maxHeight, includeKey = true } = Astro.props;
|
|
9
|
+
|
|
10
|
+
// Find the flow for the given id and version
|
|
11
|
+
const flows = await getFlows();
|
|
12
|
+
const flowCollection = getVersionFromCollection(flows, id, version) || [];
|
|
13
|
+
const flow = flowCollection[0];
|
|
14
|
+
|
|
15
|
+
// const flow = flows.find((flow) => flow.data.id === id && flow.data.version === version);
|
|
16
|
+
|
|
17
|
+
const { nodes, edges } = await getNodesAndEdges({
|
|
18
|
+
id: id,
|
|
19
|
+
version: flow.data.version,
|
|
20
|
+
});
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
!flow && (
|
|
25
|
+
<Admonition type="warning">
|
|
26
|
+
<>
|
|
27
|
+
<span class="block font-bold">{`<Flow/>`} failed to load</span>
|
|
28
|
+
<span class="block">
|
|
29
|
+
Tried to load flow id: {id} with version {version}. Make sure you have this flow defined in your project.
|
|
30
|
+
</span>
|
|
31
|
+
</>
|
|
32
|
+
</Admonition>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
class="h-[30em] my-6 mb-12 w-full relative border border-gray-200 rounded-md"
|
|
38
|
+
id={`${id}-portal`}
|
|
39
|
+
style={{
|
|
40
|
+
maxHeight: maxHeight ? `${maxHeight}em` : `30em`,
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div>
|
|
46
|
+
<NodeGraph
|
|
47
|
+
id={id}
|
|
48
|
+
nodes={nodes}
|
|
49
|
+
edges={edges}
|
|
50
|
+
hrefLabel={'View in visualizer'}
|
|
51
|
+
href={`/visualiser/flows/${id}/${version}`}
|
|
52
|
+
linkTo={'visualiser'}
|
|
53
|
+
includeKey={includeKey}
|
|
54
|
+
footerLabel=`Flow diagram - ${flow.data.name} - v(${flow.data.version})`
|
|
55
|
+
client:load
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<style is:global>
|
|
60
|
+
.react-flow__attribution {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -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';
|
|
@@ -28,6 +31,7 @@ interface Props {
|
|
|
28
31
|
includeBackground?: boolean;
|
|
29
32
|
includeControls?: boolean;
|
|
30
33
|
linkTo: 'docs' | 'visualiser';
|
|
34
|
+
includeKey?: boolean;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
const getDocUrlForCollection = (collectionItem: CollectionEntry<CollectionTypes>) => {
|
|
@@ -38,10 +42,27 @@ const getVisualiserUrlForCollection = (collectionItem: CollectionEntry<Collectio
|
|
|
38
42
|
};
|
|
39
43
|
|
|
40
44
|
// const NodeGraphBuilder = ({ title, subtitle, includeBackground = true, includeControls = true }: Props) => {
|
|
41
|
-
const NodeGraphBuilder = ({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
const NodeGraphBuilder = ({
|
|
46
|
+
nodes: initialNodes,
|
|
47
|
+
edges,
|
|
48
|
+
title,
|
|
49
|
+
includeBackground = true,
|
|
50
|
+
linkTo = 'docs',
|
|
51
|
+
includeKey = true,
|
|
52
|
+
}: Props) => {
|
|
53
|
+
const nodeTypes = useMemo(
|
|
54
|
+
() => ({
|
|
55
|
+
services: ServiceNode,
|
|
56
|
+
events: EventNode,
|
|
57
|
+
commands: CommandNode,
|
|
58
|
+
step: StepNode,
|
|
59
|
+
user: UserNode,
|
|
60
|
+
actor: UserNode,
|
|
61
|
+
externalSystem: ExternalSystemNode,
|
|
62
|
+
}),
|
|
63
|
+
[]
|
|
64
|
+
);
|
|
65
|
+
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
|
45
66
|
const nodeOrigin = [0.5, 0.5];
|
|
46
67
|
|
|
47
68
|
const handleNodeClick = (_: any, node: Node) => {
|
|
@@ -60,7 +81,6 @@ const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground
|
|
|
60
81
|
nodes={nodes}
|
|
61
82
|
edges={edges}
|
|
62
83
|
fitView
|
|
63
|
-
nodesDraggable
|
|
64
84
|
onNodesChange={onNodesChange}
|
|
65
85
|
connectionLineType={ConnectionLineType.SmoothStep}
|
|
66
86
|
// @ts-ignore
|
|
@@ -77,25 +97,27 @@ const NodeGraphBuilder = ({ nodes: initialNodes, edges, title, includeBackground
|
|
|
77
97
|
<DownloadButton filename={title} addPadding={!!title} />
|
|
78
98
|
{includeBackground && <Background color="#bbb" gap={16} />}
|
|
79
99
|
{includeBackground && <Controls />}
|
|
80
|
-
|
|
81
|
-
<
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
{includeKey && (
|
|
101
|
+
<Panel position="bottom-right">
|
|
102
|
+
<div className=" bg-white font-light px-4 text-[14px] shadow-md py-1 rounded-md">
|
|
103
|
+
<span className="font-bold">Key</span>
|
|
104
|
+
<ul>
|
|
105
|
+
<li className="flex space-x-2 items-center text-[12px]">
|
|
106
|
+
<span className="w-2 h-2 bg-orange-500 block" />
|
|
107
|
+
<span className="block">Event</span>
|
|
108
|
+
</li>
|
|
109
|
+
<li className="flex space-x-2 items-center text-[12px]">
|
|
110
|
+
<span className="w-2 h-2 bg-pink-500 block" />
|
|
111
|
+
<span className="block">Service</span>
|
|
112
|
+
</li>
|
|
113
|
+
<li className="flex space-x-2 items-center text-[12px]">
|
|
114
|
+
<span className="w-2 h-2 bg-blue-500 block" />
|
|
115
|
+
<span className="block">Command</span>
|
|
116
|
+
</li>
|
|
117
|
+
</ul>
|
|
118
|
+
</div>
|
|
119
|
+
</Panel>
|
|
120
|
+
)}
|
|
99
121
|
</ReactFlow>
|
|
100
122
|
);
|
|
101
123
|
};
|
|
@@ -108,9 +130,21 @@ interface NodeGraphProps {
|
|
|
108
130
|
nodes: Node[];
|
|
109
131
|
edges: Edge[];
|
|
110
132
|
linkTo: 'docs' | 'visualiser';
|
|
133
|
+
includeKey?: boolean;
|
|
134
|
+
footerLabel?: string;
|
|
111
135
|
}
|
|
112
136
|
|
|
113
|
-
const NodeGraph = ({
|
|
137
|
+
const NodeGraph = ({
|
|
138
|
+
id,
|
|
139
|
+
nodes,
|
|
140
|
+
edges,
|
|
141
|
+
title,
|
|
142
|
+
href,
|
|
143
|
+
linkTo = 'docs',
|
|
144
|
+
hrefLabel = 'Open in visualizer',
|
|
145
|
+
includeKey = true,
|
|
146
|
+
footerLabel,
|
|
147
|
+
}: NodeGraphProps) => {
|
|
114
148
|
const [elem, setElem] = useState(null);
|
|
115
149
|
|
|
116
150
|
useEffect(() => {
|
|
@@ -124,15 +158,23 @@ const NodeGraph = ({ id, nodes, edges, title, href, linkTo = 'docs', hrefLabel =
|
|
|
124
158
|
<div>
|
|
125
159
|
{createPortal(
|
|
126
160
|
<ReactFlowProvider>
|
|
127
|
-
<NodeGraphBuilder edges={edges} nodes={nodes} title={title} linkTo={linkTo} />
|
|
161
|
+
<NodeGraphBuilder edges={edges} nodes={nodes} title={title} linkTo={linkTo} includeKey={includeKey} />
|
|
162
|
+
|
|
163
|
+
<div className="flex justify-between">
|
|
164
|
+
{footerLabel && (
|
|
165
|
+
<div className="py-2 w-full text-left ">
|
|
166
|
+
<span className=" text-sm no-underline py-2 text-gray-300">{footerLabel}</span>
|
|
167
|
+
</div>
|
|
168
|
+
)}
|
|
128
169
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
170
|
+
{href && (
|
|
171
|
+
<div className="py-2 w-full text-right">
|
|
172
|
+
<a className=" text-sm no-underline py-2 text-gray-800 hover:text-purple-500" href={href}>
|
|
173
|
+
{hrefLabel} →
|
|
174
|
+
</a>
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
177
|
+
</div>
|
|
136
178
|
</ReactFlowProvider>,
|
|
137
179
|
elem
|
|
138
180
|
)}
|
|
@@ -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 ">
|