@eventcatalog/core 2.24.3 → 2.25.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 (30) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/catalog-to-astro-content-directory.cjs +0 -1
  6. package/dist/catalog-to-astro-content-directory.js +1 -1
  7. package/dist/{chunk-7K4ERS3X.js → chunk-7674GE3M.js} +1 -1
  8. package/dist/{chunk-3MDI2MXJ.js → chunk-H6PSWK2Z.js} +1 -1
  9. package/dist/{chunk-OZZMZUB3.js → chunk-JENKAK6L.js} +1 -1
  10. package/dist/{chunk-CXKIF3EI.js → chunk-VCR3LHZR.js} +0 -1
  11. package/dist/constants.cjs +1 -1
  12. package/dist/constants.js +1 -1
  13. package/dist/eventcatalog.cjs +1 -2
  14. package/dist/eventcatalog.js +4 -4
  15. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +3 -2
  16. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Channel.tsx +82 -54
  17. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Command.tsx +44 -41
  18. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Event.tsx +43 -41
  19. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/MessageContextMenu.tsx +54 -0
  20. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Query.tsx +45 -43
  21. package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Service.tsx +112 -42
  22. package/eventcatalog/src/components/SideNav/TreeView/getTreeView.ts +1 -1
  23. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/index.astro +0 -1
  24. package/eventcatalog/src/pages/docs/_default-docs.mdx +24 -0
  25. package/eventcatalog/src/pages/docs/index.astro +13 -18
  26. package/package.json +2 -1
  27. package/default-files-for-collections/pages.md +0 -7
  28. package/eventcatalog/src/components/DocsNavigation.astro +0 -145
  29. package/eventcatalog/src/layouts/CustomDocsPageLayout.astro +0 -131
  30. package/eventcatalog/src/layouts/PlainPage.astro +0 -29
@@ -1,7 +1,7 @@
1
1
  import { MagnifyingGlassIcon } from '@heroicons/react/16/solid';
2
2
  import type { CollectionEntry } from 'astro:content';
3
3
  import { Handle } from '@xyflow/react';
4
-
4
+ import MessageContextMenu from './MessageContextMenu';
5
5
  interface Data {
6
6
  title: string;
7
7
  label: string;
@@ -22,53 +22,55 @@ export default function QueryNode({ data, sourcePosition, targetPosition }: any)
22
22
 
23
23
  const { name, version, summary, owners = [], producers = [], consumers = [] } = message.data;
24
24
 
25
- const renderTarget = true; //showTarget || (targetPosition && producers.length > 0);
26
- const renderSource = true; // showSource || (sourcePosition && consumers.length > 0);
25
+ const renderTarget = true;
26
+ const renderSource = true;
27
27
 
28
28
  return (
29
- <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-green-400')}>
30
- <div
31
- className={classNames(
32
- 'bg-gradient-to-b from-green-500 to-green-700 relative flex items-center w-5 justify-center rounded-l-sm text-green-100-500',
33
- `border-r-[1px] border-green-500`
34
- )}
35
- >
36
- <MagnifyingGlassIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
37
- {mode === 'full' && (
38
- <span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
39
- Query
40
- </span>
41
- )}
42
- </div>
43
- <div className="p-1 min-w-60 max-w-[min-content]">
44
- {renderTarget && <Handle type="target" position={targetPosition} />}
45
- {renderSource && <Handle type="source" position={sourcePosition} />}
46
- <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
47
- <span className="text-xs font-bold block pb-0.5">{name}</span>
48
- <div className="flex justify-between">
49
- <span className="text-[10px] font-light block pt-0.5 pb-0.5 ">v{version}</span>
50
- {mode === 'simple' && <span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Query</span>}
51
- </div>
29
+ <MessageContextMenu message={message} messageType="queries">
30
+ <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-green-400')}>
31
+ <div
32
+ className={classNames(
33
+ 'bg-gradient-to-b from-green-500 to-green-700 relative flex items-center w-5 justify-center rounded-l-sm text-green-100-500',
34
+ `border-r-[1px] border-green-500`
35
+ )}
36
+ >
37
+ <MagnifyingGlassIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
38
+ {mode === 'full' && (
39
+ <span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
40
+ Query
41
+ </span>
42
+ )}
52
43
  </div>
53
- {mode === 'full' && (
54
- <div className="divide-y divide-gray-200 ">
55
- <div className="leading-3 py-1">
56
- <span className="text-[8px] font-light">{summary}</span>
57
- </div>
58
- <div className="grid grid-cols-2 gap-x-4 py-1">
59
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
60
- Producers: {producers.length}
61
- </span>
62
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
63
- Consumers: {consumers.length}
64
- </span>
65
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
66
- Owners: {owners.length}
67
- </span>
44
+ <div className="p-1 min-w-60 max-w-[min-content]">
45
+ {renderTarget && <Handle type="target" position={targetPosition} />}
46
+ {renderSource && <Handle type="source" position={sourcePosition} />}
47
+ <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
48
+ <span className="text-xs font-bold block pb-0.5">{name}</span>
49
+ <div className="flex justify-between">
50
+ <span className="text-[10px] font-light block pt-0.5 pb-0.5 ">v{version}</span>
51
+ {mode === 'simple' && <span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Query</span>}
68
52
  </div>
69
53
  </div>
70
- )}
54
+ {mode === 'full' && (
55
+ <div className="divide-y divide-gray-200 ">
56
+ <div className="leading-3 py-1">
57
+ <span className="text-[8px] font-light">{summary}</span>
58
+ </div>
59
+ <div className="grid grid-cols-2 gap-x-4 py-1">
60
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
61
+ Producers: {producers.length}
62
+ </span>
63
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
64
+ Consumers: {consumers.length}
65
+ </span>
66
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
67
+ Owners: {owners.length}
68
+ </span>
69
+ </div>
70
+ </div>
71
+ )}
72
+ </div>
71
73
  </div>
72
- </div>
74
+ </MessageContextMenu>
73
75
  );
74
76
  }
@@ -1,6 +1,8 @@
1
1
  import { ServerIcon } from '@heroicons/react/16/solid';
2
2
  import type { CollectionEntry } from 'astro:content';
3
3
  import { Handle } from '@xyflow/react';
4
+ import * as ContextMenu from '@radix-ui/react-context-menu';
5
+ import { buildUrl } from '@utils/url-builder';
4
6
 
5
7
  interface Data {
6
8
  label: string;
@@ -19,53 +21,121 @@ function classNames(...classes: any) {
19
21
  export default function ServiceNode({ data, sourcePosition, targetPosition }: any) {
20
22
  const { label, bgColor = 'bg-blue-500', mode, service } = data as Data;
21
23
 
22
- const { version, owners = [], sends = [], receives = [], name } = service.data;
24
+ const { id, version, owners = [], sends = [], receives = [], name, specifications, repository } = service.data;
25
+ const asyncApiPath = specifications?.asyncapiPath;
26
+ const openApiPath = specifications?.openapiPath;
27
+ const repositoryUrl = repository?.url;
23
28
 
24
29
  return (
25
- <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-pink-500')}>
26
- <div
27
- className={classNames(
28
- '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',
29
- `border-r-[1px] border-pink-500`
30
- )}
31
- >
32
- <ServerIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
33
- {mode === 'full' && (
34
- <span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
35
- Service
36
- </span>
37
- )}
38
- </div>
39
- <div className="p-1 min-w-60 max-w-[min-content]">
40
- {targetPosition && <Handle type="target" position={targetPosition} />}
41
- {sourcePosition && <Handle type="source" position={sourcePosition} />}
42
- <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
43
- <span className="text-xs font-bold block pt-0.5 pb-0.5">{name}</span>
44
- <div className="flex justify-between">
45
- <span className="text-[10px] font-light block pt-0.5 pb-0.5 ">v{version}</span>
46
- {mode === 'simple' && <span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Service</span>}
30
+ <ContextMenu.Root>
31
+ <ContextMenu.Trigger>
32
+ <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-pink-500')}>
33
+ <div
34
+ className={classNames(
35
+ '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',
36
+ `border-r-[1px] border-pink-500`
37
+ )}
38
+ >
39
+ <ServerIcon className="w-4 h-4 opacity-90 text-white absolute top-1 " />
40
+ {mode === 'full' && (
41
+ <span className="rotate -rotate-90 w-1/2 text-center absolute bottom-1 text-[9px] text-white font-bold uppercase tracking-[3px] ">
42
+ Service
43
+ </span>
44
+ )}
47
45
  </div>
48
- </div>
49
- {mode === 'full' && (
50
- <div className="divide-y divide-gray-200 ">
51
- <div className="leading-3 py-1">
52
- <span className="text-[8px] font-light">{service.data.summary}</span>
46
+ <div className="p-1 min-w-60 max-w-[min-content]">
47
+ {targetPosition && <Handle type="target" position={targetPosition} />}
48
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
49
+ <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
50
+ <span className="text-xs font-bold block pt-0.5 pb-0.5">{name}</span>
51
+ <div className="flex justify-between">
52
+ <span className="text-[10px] font-light block pt-0.5 pb-0.5 ">v{version}</span>
53
+ {mode === 'simple' && <span className="text-[10px] text-gray-500 font-light block pt-0.5 pb-0.5 ">Service</span>}
54
+ </div>
53
55
  </div>
56
+ {mode === 'full' && (
57
+ <div className="divide-y divide-gray-200 ">
58
+ <div className="leading-3 py-1">
59
+ <span className="text-[8px] font-light">{service.data.summary}</span>
60
+ </div>
54
61
 
55
- <div className="grid grid-cols-2 gap-x-4 py-1">
56
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
57
- Receives messages: {receives.length}
58
- </span>
59
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
60
- Publishes messages: {sends.length}
61
- </span>
62
- <span className="text-xs" style={{ fontSize: '0.2em' }}>
63
- Owners: {owners.length}
64
- </span>
65
- </div>
62
+ <div className="grid grid-cols-2 gap-x-4 py-1">
63
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
64
+ Receives messages: {receives.length}
65
+ </span>
66
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
67
+ Publishes messages: {sends.length}
68
+ </span>
69
+ <span className="text-xs" style={{ fontSize: '0.2em' }}>
70
+ Owners: {owners.length}
71
+ </span>
72
+ </div>
73
+ </div>
74
+ )}
66
75
  </div>
67
- )}
68
- </div>
69
- </div>
76
+ </div>
77
+ </ContextMenu.Trigger>
78
+ <ContextMenu.Portal>
79
+ <ContextMenu.Content className="min-w-[220px] bg-white rounded-md p-1 shadow-md border border-gray-200">
80
+ <ContextMenu.Item
81
+ asChild
82
+ className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-orange-100 rounded-sm flex items-center"
83
+ >
84
+ <a href={buildUrl(`/docs/services/${id}/${version}`)}>Read documentation</a>
85
+ </ContextMenu.Item>
86
+ <ContextMenu.Separator className="h-[1px] bg-gray-200 m-1" />
87
+ {asyncApiPath && (
88
+ <ContextMenu.Item asChild>
89
+ <a
90
+ href={buildUrl(`/docs/services/${id}/${version}/asyncapi`)}
91
+ className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-orange-100 rounded-sm flex items-center"
92
+ target="_blank"
93
+ rel="noopener noreferrer"
94
+ >
95
+ View AsyncAPI specification
96
+ </a>
97
+ </ContextMenu.Item>
98
+ )}
99
+ {openApiPath && (
100
+ <ContextMenu.Item asChild>
101
+ <a
102
+ href={buildUrl(`/docs/services/${id}/${version}/spec`)}
103
+ className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-orange-100 rounded-sm flex items-center"
104
+ target="_blank"
105
+ rel="noopener noreferrer"
106
+ >
107
+ View OpenAPI specification
108
+ </a>
109
+ </ContextMenu.Item>
110
+ )}
111
+ {asyncApiPath && openApiPath && <ContextMenu.Separator className="h-[1px] bg-gray-200 m-1" />}
112
+ {repositoryUrl && (
113
+ <>
114
+ <ContextMenu.Item asChild>
115
+ <a
116
+ href={repositoryUrl}
117
+ className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-orange-100 rounded-sm flex items-center"
118
+ target="_blank"
119
+ rel="noopener noreferrer"
120
+ >
121
+ View code repository
122
+ </a>
123
+ </ContextMenu.Item>
124
+ <ContextMenu.Separator className="h-[1px] bg-gray-200 m-1" />
125
+ </>
126
+ )}
127
+ <ContextMenu.Item asChild>
128
+ <a
129
+ href={buildUrl(`/docs/services/${id}/${version}/changelog`)}
130
+ className="text-sm px-2 py-1.5 outline-none cursor-pointer hover:bg-orange-100 rounded-sm flex items-center"
131
+ target="_blank"
132
+ rel="noopener noreferrer"
133
+ >
134
+ Read changelog
135
+ </a>
136
+ </ContextMenu.Item>
137
+ </ContextMenu.Content>
138
+ </ContextMenu.Portal>
139
+ </ContextMenu.Root>
70
140
  );
71
141
  }
@@ -138,7 +138,7 @@ function groupChildrenByType(parentNode: TreeNode) {
138
138
  const treeViewCache = new Map<string, TreeNode>();
139
139
 
140
140
  export function getTreeView({ projectDir, currentPath }: { projectDir: string; currentPath: string }): TreeNode {
141
- const basePathname = currentPath.split('/')[1] as 'docs' | 'visualiser';
141
+ const basePathname = currentPath.split('/').find((p) => p === 'docs' || p === 'visualiser') || 'docs';
142
142
 
143
143
  const cacheKey = `${projectDir}:${basePathname}`;
144
144
  if (treeViewCache.has(cacheKey)) return treeViewCache.get(cacheKey)!;
@@ -4,7 +4,6 @@ import * as path from 'path';
4
4
  import fs from 'node:fs';
5
5
 
6
6
  import type { CollectionTypes, PageTypes } from '@types';
7
- import PlainPage from '@layouts/PlainPage.astro';
8
7
  import { DocumentMinusIcon } from '@heroicons/react/24/outline';
9
8
  import { buildUrl } from '@utils/url-builder';
10
9
  import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
@@ -0,0 +1,24 @@
1
+ # **EventCatalog**
2
+
3
+ Welcome to [EventCatalog](https://www.eventcatalog.dev/).
4
+
5
+ This open-source project is designed to help you and your teams bring discoverability and clarity to your event-driven architectures (EDA).
6
+
7
+ To get started you can read the following guides:
8
+
9
+ - [Getting started with EventCatalog](https://eventcatalog.dev/docs/development/getting-started/introduction)
10
+ - [Creating domains](https://eventcatalog.dev/docs/development/guides/domains/adding-domains)
11
+ - [Creating services](https://eventcatalog.dev/docs/development/guides/services/adding-services)
12
+ - [Creating commands](https://eventcatalog.dev/docs/development/guides/messages/commands/introduction)
13
+ - [Creating events](https://eventcatalog.dev/docs/development/guides/messages/events/introduction)
14
+ - [Assigning owners to resources](https://eventcatalog.dev/docs/owners)
15
+ - [Using components in your pages (Schemas, OpenAPI, etc)](https://eventcatalog.dev/docs/development/components/using-components)
16
+ - [Deploying and hosting your EventCatalog](https://eventcatalog.dev/docs/development/deployment)
17
+
18
+ ### **Join the community**
19
+
20
+ Got questions about EventCatalog? Feature requests or need support? [Join our community on Discord.](https://discord.gg/3rjaZMmrAm)
21
+
22
+ ### **Enterprise support**
23
+
24
+ Using EventCatalog and needs enterprise support? Work with us, find out what we offer on our [enterprise page](https://eventcatalog.dev/enterprise).
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  import Footer from '@layouts/Footer.astro';
3
- import DefaultDocsLandingPage from '@layouts/CustomDocsPageLayout.astro';
4
3
  import components from '@components/MDX/page-components';
5
4
  import { getIndexPage } from '@utils/pages';
6
5
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
@@ -11,24 +10,20 @@ let CustomContent = null;
11
10
  if (page) {
12
11
  const { Content } = await page.render();
13
12
  CustomContent = Content;
13
+ } else {
14
+ CustomContent = await import('./_default-docs.mdx').then((mod) => mod.default);
14
15
  }
15
16
  ---
16
17
 
17
- {
18
- CustomContent && (
19
- <VerticalSideBarLayout title="EventCatalog">
20
- <main class="flex sm:px-8 docs-layout h-full">
21
- <div class="flex docs-layout w-full">
22
- <div class="w-full lg:mr-2 pr-8 overflow-y-auto py-8">
23
- <div class="prose prose-md w-full !max-w-none">
24
- <CustomContent components={components} />
25
- </div>
26
- <Footer />
27
- </div>
18
+ <VerticalSideBarLayout title="EventCatalog">
19
+ <main class="flex sm:px-8 docs-layout h-full">
20
+ <div class="flex docs-layout w-full">
21
+ <div class="w-full lg:mr-2 pr-8 overflow-y-auto py-8">
22
+ <div class="prose prose-md w-full !max-w-none">
23
+ <CustomContent components={components} />
28
24
  </div>
29
- </main>
30
- </VerticalSideBarLayout>
31
- )
32
- }
33
-
34
- {!CustomContent && <DefaultDocsLandingPage title="EventCatalog" />}
25
+ <Footer />
26
+ </div>
27
+ </div>
28
+ </main>
29
+ </VerticalSideBarLayout>
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/event-catalog/eventcatalog.git"
7
7
  },
8
8
  "type": "module",
9
- "version": "2.24.3",
9
+ "version": "2.25.0",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
@@ -37,6 +37,7 @@
37
37
  "@langchain/community": "^0.3.32",
38
38
  "@mlc-ai/web-llm": "^0.2.78",
39
39
  "@parcel/watcher": "^2.4.1",
40
+ "@radix-ui/react-context-menu": "^2.2.6",
40
41
  "@radix-ui/react-dialog": "^1.1.6",
41
42
  "@stoplight/json-schema-viewer": "^4.16.4",
42
43
  "@tailwindcss/typography": "^0.5.13",
@@ -1,7 +0,0 @@
1
- ---
2
- id: index
3
- slug: index
4
- hidden: true
5
- ---
6
-
7
- <!-- Do not delete this file, required for EC, you an ignore this file -->
@@ -1,145 +0,0 @@
1
- ---
2
- import { getCommands } from '@utils/commands';
3
- import { getDomains } from '@utils/collections/domains';
4
- import { getEvents } from '@utils/events';
5
- import { getServices } from '@utils/collections/services';
6
- import { getFlows } from '@utils/collections/flows';
7
- import { getTeams } from '@utils/teams';
8
- import { getUsers } from '@utils/users';
9
- import config, { type CatalogConfig } from '@utils/eventcatalog-config/catalog';
10
- import { buildUrl } from '@utils/url-builder';
11
- import { getQueries } from '@utils/queries';
12
-
13
- const events = await getEvents({ getAllVersions: false });
14
- const commands = await getCommands({ getAllVersions: false });
15
- const queries = await getQueries({ getAllVersions: false });
16
- const services = await getServices({ getAllVersions: false });
17
- const domains = await getDomains({ getAllVersions: false });
18
- const flows = await getFlows({ getAllVersions: false });
19
- const teams = await getTeams();
20
- const users = await getUsers();
21
-
22
- const messages = [...events, ...commands, ...queries];
23
-
24
- // @ts-ignore for large catalogs https://github.com/event-catalog/eventcatalog/issues/552
25
- const allData = [...domains, ...services, ...messages, ...flows, ...teams, ...users];
26
-
27
- const eventCatalogConfig = config as CatalogConfig;
28
- const {
29
- services: servicesConfig,
30
- domains: domainsConfig,
31
- messages: messagesConfig,
32
- flows: flowsConfig,
33
- teams: teamsConfig,
34
- users: usersConfig,
35
- showPageHeadings = true,
36
- } = eventCatalogConfig?.docs?.sidebar || {};
37
-
38
- const getConfigValue = (obj: any, key: string, defaultValue: any) => {
39
- return obj?.[key] ?? defaultValue;
40
- };
41
-
42
- const visibleCollections: { [key: string]: boolean } = {
43
- events: getConfigValue(messagesConfig, 'visible', true),
44
- commands: getConfigValue(messagesConfig, 'visible', true),
45
- domains: getConfigValue(domainsConfig, 'visible', true),
46
- flows: getConfigValue(flowsConfig, 'visible', true),
47
- services: getConfigValue(servicesConfig, 'visible', true),
48
- teams: getConfigValue(teamsConfig, 'visible', true),
49
- users: getConfigValue(usersConfig, 'visible', true),
50
- };
51
-
52
- const fetchHeadings = allData.map(async (item) => {
53
- const renderHeadings = showPageHeadings;
54
- const headings = renderHeadings ? await item.render() : { headings: [] };
55
- return {
56
- ...item,
57
- headings: headings.headings,
58
- };
59
- });
60
-
61
- const withHeadings = await Promise.all(fetchHeadings);
62
-
63
- const sideNav = withHeadings.reduce((acc, item) => {
64
- const title = item.collection === 'events' || item.collection === 'commands' ? 'Messages' : item.collection;
65
-
66
- const group = acc[title] || [];
67
-
68
- const navigationItem = {
69
- label: item.data.name,
70
- version: item.collection === 'teams' || item.collection === 'users' ? null : item.data.version,
71
- items: item.collection === 'users' ? [] : item.headings,
72
- visible: visibleCollections[item.collection],
73
- // @ts-ignore
74
- href: item.data.version
75
- ? // @ts-ignore
76
- buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)
77
- : buildUrl(`/docs/${item.collection}/${item.data.id}`),
78
- };
79
-
80
- group.push(navigationItem);
81
-
82
- return {
83
- ...acc,
84
- [title]: group,
85
- };
86
- }, {} as any);
87
-
88
- const currentPath = Astro.url.pathname;
89
- ---
90
-
91
- <div class="font-light w-full xl:pr-10 pb-20">
92
- {
93
- Object.keys(sideNav).map((key) => {
94
- const collection = sideNav[key];
95
- if (collection[0] && collection[0].visible === false) return null;
96
- return (
97
- <ul class=" w-full space-y-2 pb-8">
98
- <li class="font-semibold capitalize ">{key}</li>
99
- {collection.map((item: any) => {
100
- return (
101
- <li class="px-2 w-full text-md xl:text-lg border-l border-gray-200 space-y-2 scroll-m-20" id={item.href}>
102
- <a
103
- class={`flex justify-between items-center w-full px-2 rounded-md font-normal ${currentPath.includes(item.href) ? 'bg-primary/5 text-primary ' : 'font-thin'}`}
104
- href={`${item.href}`}
105
- >
106
- <span class="block truncate !whitespace-normal">{item.label}</span>
107
- {item.version && (
108
- <span class="block text-sm bg-primary/10 p-0.5 px-1 text-gray-600 rounded-md font-light">
109
- v{item.version}
110
- </span>
111
- )}
112
- </a>
113
- <ul class="hidden xl:block px-4 text-gray-500 text-md space-y-2 ">
114
- {item.items.map((heading: any) => {
115
- return (
116
- <li class="text-xs">
117
- <a href={`${item.href}#${heading.slug}`}>{heading.text}</a>
118
- </li>
119
- );
120
- })}
121
- </ul>
122
- </li>
123
- );
124
- })}
125
- </ul>
126
- );
127
- })
128
- }
129
- </div>
130
-
131
- <script>
132
- // Scroll to the current page element
133
- // document.addEventListener('DOMContentLoaded', () => {
134
- // const currentPath = document.location.pathname;
135
- // const currentElement = document.getElementById(currentPath);
136
- // if (currentElement) {
137
- // // scroll to the current element with padding
138
- // currentElement.scrollIntoView({
139
- // behavior: 'auto',
140
- // block: 'start',
141
- // inline: 'start',
142
- // });
143
- // }
144
- // });
145
- </script>