@eventcatalog/core 2.10.1 → 2.11.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 (41) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +10 -2
  3. package/images/sponsors/gravitee-logo-black.svg +54 -0
  4. package/package.json +4 -1
  5. package/public/icons/discord.svg +1 -0
  6. package/public/icons/github-purple.svg +1 -0
  7. package/src/components/DocsNavigation.astro +12 -12
  8. package/src/components/Header.astro +18 -18
  9. package/src/components/Lists/OwnersList.tsx +21 -58
  10. package/src/components/Lists/PillList.tsx +20 -16
  11. package/src/components/Lists/PillListFlat.styles.css +8 -0
  12. package/src/components/Lists/PillListFlat.tsx +69 -0
  13. package/src/components/Lists/SpecificationsList.astro +4 -4
  14. package/src/components/Lists/VersionList.astro +33 -13
  15. package/src/components/Search.astro +5 -2
  16. package/src/components/SideBars/CatalogResourcesSideBar/index.tsx +120 -0
  17. package/src/components/SideBars/CatalogResourcesSideBar/styles.css +8 -0
  18. package/src/components/SideBars/DomainSideBar.astro +15 -8
  19. package/src/components/SideBars/MessageSideBar.astro +51 -43
  20. package/src/components/SideBars/ServiceSideBar.astro +23 -31
  21. package/src/components/Tables/Table.tsx +2 -2
  22. package/src/components/Tables/columns/MessageTableColumns.tsx +4 -4
  23. package/src/components/Tables/columns/ServiceTableColumns.tsx +4 -4
  24. package/src/layouts/DiscoverLayout.astro +7 -7
  25. package/src/layouts/Footer.astro +1 -1
  26. package/src/layouts/VerticalSideBarLayout.astro +312 -0
  27. package/src/layouts/VisualiserLayout.astro +6 -10
  28. package/src/pages/docs/[type]/[id]/[version]/asyncapi/index.astro +3 -2
  29. package/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +40 -5
  30. package/src/pages/docs/[type]/[id]/[version]/index.astro +149 -144
  31. package/src/pages/docs/[type]/[id]/[version]/spec/index.astro +13 -3
  32. package/src/pages/docs/[type]/[id]/[version]/spec/styles.css +3 -0
  33. package/src/pages/docs/index.astro +4 -4
  34. package/src/pages/docs/teams/[id]/index.astro +13 -10
  35. package/src/pages/docs/users/[id]/index.astro +115 -91
  36. package/src/pages/index.astro +83 -63
  37. package/src/pages/visualiser/[type]/[id]/[version]/index.astro +3 -1
  38. package/src/utils/collections/icons.ts +33 -0
  39. package/tailwind.config.mjs +2 -1
  40. package/src/components/Lists/BasicList.tsx +0 -59
  41. package/src/layouts/DocsLayout.astro +0 -62
@@ -0,0 +1,312 @@
1
+ ---
2
+ interface Props {
3
+ title: string;
4
+ sidebar?: boolean;
5
+ description?: string;
6
+ }
7
+
8
+ import { BookOpenText, Workflow, TableProperties, House } from 'lucide-react';
9
+ import Header from '../components/Header.astro';
10
+ import SEO from '../components/Seo.astro';
11
+
12
+ import { getCommands } from '@utils/commands';
13
+ import { getDomains } from '@utils/domains/domains';
14
+ import { getEvents } from '@utils/events';
15
+ import { getServices } from '@utils/services/services';
16
+ import { getFlows } from '@utils/flows/flows';
17
+ import { getTeams } from '@utils/teams';
18
+ import { getUsers } from '@utils/users';
19
+ import config, { type CatalogConfig } from '@eventcatalog';
20
+ import { buildUrl } from '@utils/url-builder';
21
+ import { getQueries } from '@utils/queries';
22
+ import CatalogResourcesSideBar from '@components/SideBars/CatalogResourcesSideBar';
23
+
24
+ const events = await getEvents({ getAllVersions: false });
25
+ const commands = await getCommands({ getAllVersions: false });
26
+ const queries = await getQueries({ getAllVersions: false });
27
+ const services = await getServices({ getAllVersions: false });
28
+ const domains = await getDomains({ getAllVersions: false });
29
+ const flows = await getFlows({ getAllVersions: false });
30
+ const teams = await getTeams();
31
+ const users = await getUsers();
32
+
33
+ const messages = [...events, ...commands, ...queries];
34
+
35
+ // @ts-ignore for large catalogs https://github.com/event-catalog/eventcatalog/issues/552
36
+ const allData = [...domains, ...services, ...messages, ...flows, ...teams, ...users];
37
+
38
+ const currentPath = Astro.url.pathname;
39
+
40
+ const getDefaultUrl = (route: string, defaultValue: string) => {
41
+ if (domains.length > 0) return buildUrl(`/${route}/domains/${domains[0].data.id}/${domains[0].data.latestVersion}`);
42
+ if (services.length > 0) return buildUrl(`/${route}/services/${services[0].data.id}/${services[0].data.latestVersion}`);
43
+ if (messages.length > 0)
44
+ return buildUrl(`/${route}/${messages[0].collection}/${messages[0].data.id}/${messages[0].data.latestVersion}`);
45
+ if (flows.length > 0) return buildUrl(`/${route}/flows/${flows[0].data.id}/${flows[0].data.latestVersion}`);
46
+ return buildUrl(defaultValue);
47
+ };
48
+
49
+ const navigationItems = [
50
+ {
51
+ id: '/',
52
+ label: 'Home',
53
+ icon: House,
54
+ href: buildUrl('/'),
55
+ current: currentPath === '/',
56
+ sidebar: false,
57
+ },
58
+ {
59
+ id: '/docs',
60
+ label: 'Documentation',
61
+ icon: BookOpenText,
62
+ href: getDefaultUrl('docs', '/docs'),
63
+ current: currentPath.includes('/docs'),
64
+ sidebar: true,
65
+ },
66
+ {
67
+ id: '/visualiser',
68
+ label: 'Visualiser',
69
+ icon: Workflow,
70
+ href: getDefaultUrl('visualiser', '/visualiser'),
71
+ current: currentPath.includes('/visualiser'),
72
+ sidebar: true,
73
+ },
74
+ {
75
+ id: '/discover',
76
+ label: 'Explore',
77
+ icon: TableProperties,
78
+ href: buildUrl('/discover/events'),
79
+ current: currentPath.includes('/discover/'),
80
+ sidebar: false,
81
+ },
82
+ ];
83
+
84
+ const eventCatalogConfig = config as CatalogConfig;
85
+
86
+ const {
87
+ services: servicesConfig,
88
+ domains: domainsConfig,
89
+ messages: messagesConfig,
90
+ flows: flowsConfig,
91
+ teams: teamsConfig,
92
+ users: usersConfig,
93
+ } = eventCatalogConfig?.docs?.sidebar || {};
94
+
95
+ const getConfigValue = (obj: any, key: string, defaultValue: any) => {
96
+ return obj?.[key] ?? defaultValue;
97
+ };
98
+
99
+ const visibleCollections: { [key: string]: boolean } = {
100
+ events: getConfigValue(messagesConfig, 'visible', true),
101
+ commands: getConfigValue(messagesConfig, 'visible', true),
102
+ domains: getConfigValue(domainsConfig, 'visible', true),
103
+ flows: getConfigValue(flowsConfig, 'visible', true),
104
+ services: getConfigValue(servicesConfig, 'visible', true),
105
+ teams: getConfigValue(teamsConfig, 'visible', true),
106
+ users: getConfigValue(usersConfig, 'visible', true),
107
+ };
108
+
109
+ const sideNav = allData.reduce((acc, item) => {
110
+ const title = item.collection;
111
+ const group = acc[title] || [];
112
+ const currentPath = Astro.url.pathname;
113
+ const route = currentPath.includes('visualiser') ? 'visualiser' : 'docs';
114
+
115
+ if (currentPath.includes('visualiser') && (item.collection === 'teams' || item.collection === 'users')) {
116
+ return acc;
117
+ }
118
+
119
+ const navigationItem = {
120
+ label: item.data.name,
121
+ version: item.collection === 'teams' || item.collection === 'users' ? null : item.data.version,
122
+ // items: item.collection === 'users' ? [] : item.headings,
123
+ visible: visibleCollections[item.collection],
124
+ // @ts-ignore
125
+ href: item.data.version
126
+ ? // @ts-ignore
127
+ buildUrl(`/${route}/${item.collection}/${item.data.id}/${item.data.version}`)
128
+ : buildUrl(`/${route}/${item.collection}/${item.data.id}`),
129
+ collection: item.collection,
130
+ };
131
+
132
+ group.push(navigationItem);
133
+
134
+ return {
135
+ ...acc,
136
+ [title]: group,
137
+ };
138
+ }, {} as any);
139
+
140
+ const currentNavigationItem = navigationItems.find((item) => item.current);
141
+ const { title, description, sidebar: showSideBarOverride } = Astro.props;
142
+
143
+ const showSideBarOnLoad = currentNavigationItem?.sidebar;
144
+ ---
145
+
146
+ <!doctype html>
147
+ <html lang="en">
148
+ <head>
149
+ <SEO title={`EventCatalog | ${title}`} description={description} ogTitle={title} />
150
+ <style>
151
+ .sidebar-transition {
152
+ transition-property: width, transform;
153
+ transition-duration: 300ms;
154
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
155
+ }
156
+ .tooltip {
157
+ visibility: hidden;
158
+ position: absolute;
159
+ }
160
+ .has-tooltip:hover .tooltip {
161
+ visibility: visible;
162
+ z-index: 100;
163
+ }
164
+ </style>
165
+ </head>
166
+ <body>
167
+ <Header />
168
+ <div class="flex">
169
+ <aside class="flex" id="eventcatalog-vertical-nav">
170
+ <div
171
+ class="fixed flex flex-col items-center w-16 h-screen py-4 bg-white bg-gradient-to-b from-white to-gray-100 border-r border-gray-200 z-20 shadow-md justify-between"
172
+ >
173
+ <nav class="flex flex-col h-[84vh] justify-between">
174
+ <div class="flex flex-col items-center flex-1 space-y-8">
175
+ {
176
+ navigationItems.map((item) => {
177
+ return (
178
+ <a
179
+ id={item.id}
180
+ data-role="nav-item"
181
+ href={item.href}
182
+ class={`p-1.5 inline-block transition-colors duration-200 rounded-lg ${item.current ? 'text-white bg-gradient-to-b from-purple-500 to-purple-700' : 'hover:bg-gradient-to-r hover:from-purple-500 hover:to-purple-700 hover:text-white text-gray-700'}`}
183
+ >
184
+ <div class="has-tooltip">
185
+ <span class="tooltip rounded shadow-lg p-1 text-xs bg-gradient-to-l from-purple-500 to-purple-700 text-white ml-10">
186
+ {item.label}
187
+ </span>
188
+ <item.icon className="h-6 w-6 " />
189
+ </div>
190
+ </a>
191
+ );
192
+ })
193
+ }
194
+ </div>
195
+ <div class="flex flex-col items-center mt-4 space-y-4 -mb-10">
196
+ <a href="https://discord.com/invite/3rjaZMmrAm" class="text-gray-500 has-tooltip">
197
+ <span class="tooltip rounded shadow-lg p-1 text-xs bg-black text-white ml-10 w-[162px]"
198
+ >Join EventCatalog Discord</span
199
+ >
200
+ <img src="/icons/discord.svg" class="w-7 h-7" />
201
+ </a>
202
+ <a href="https://github.com/event-catalog/eventcatalog" class="text-gray-500 has-tooltip">
203
+ <span class="tooltip rounded shadow-lg p-1 text-xs bg-black text-white ml-10 w-[175px]"
204
+ >Found an issue? Let us know</span
205
+ >
206
+ <img src="/icons/github-purple.svg" class="w-7 h-7" />
207
+ </a>
208
+ </div>
209
+ </nav>
210
+ </div>
211
+
212
+ <div
213
+ id="sidebar"
214
+ class={`sidebar-transition h-[100vh] max-h-screen px-5 py-4 overflow-y-auto bg-white bg-gradient-to-b from-white to-gray-100 border-r border-gray-200 w-60 shadow-lg ml-16 ${showSideBarOnLoad ? 'block' : 'hidden'}`}
215
+ >
216
+ <CatalogResourcesSideBar resources={sideNav} currentPath={currentPath} client:load />
217
+ </div>
218
+ </aside>
219
+ <main class={`sidebar-transition w-full max-h-screen ${showSideBarOnLoad ? 'ml-0' : 'ml-16'}`} id="content">
220
+ <slot />
221
+ </main>
222
+ </div>
223
+ </body>
224
+ </html>
225
+ <script define:vars={{ navigationItems, currentNavigationItem, showSideBarOnLoad }}>
226
+ // Listen for Astro transititions
227
+ document.addEventListener('astro:page-load', () => {
228
+ document.dispatchEvent(new CustomEvent('contentLoaded'));
229
+ });
230
+
231
+ // Listen for DOM loaded
232
+ document.addEventListener('DOMContentLoaded', () => {
233
+ document.dispatchEvent(new CustomEvent('contentLoaded'));
234
+ });
235
+
236
+ document.addEventListener('contentLoaded', () => {
237
+ const sidebar = document.getElementById('sidebar');
238
+ const content = document.getElementById('content');
239
+ const currentPath = window.location.href;
240
+
241
+ // Hide the sidebar if the current navigation item is not a sidebar item
242
+ if (!currentNavigationItem.sidebar || currentPath.includes('asyncapi') || currentPath.includes('/spec')) {
243
+ sidebar.style.display = 'none';
244
+ content.style.width = '100%';
245
+ content.classList.add('ml-16');
246
+ } else {
247
+ sidebar.style.display = 'block';
248
+ }
249
+
250
+ const navItems = document.querySelectorAll('[data-role="nav-item"]');
251
+ let isOpen = showSideBarOnLoad;
252
+
253
+ navItems.forEach((item) => {
254
+ item.addEventListener('click', (e) => {
255
+ const currentPath = window.location.href;
256
+ const id = item.getAttribute('id');
257
+
258
+ const navItem = navigationItems.find((navItem) => navItem.id === id);
259
+
260
+ console.log(navItem);
261
+
262
+ if (!navItem.sidebar || !currentPath.includes(navItem.id)) {
263
+ window.location.href = navItem.href;
264
+ return;
265
+ }
266
+
267
+ // not on the target page then just go to it.
268
+ if (!currentPath.includes(navItem.id)) return;
269
+
270
+ if (currentPath.includes(navItem.id)) {
271
+ e.preventDefault();
272
+ if (isOpen) {
273
+ hideSidebar();
274
+ } else {
275
+ showSidebar();
276
+ }
277
+ }
278
+ });
279
+ });
280
+
281
+ function showSidebar() {
282
+ if (!sidebar || !content) return;
283
+ isOpen = true;
284
+ localStorage.setItem('sidebarState', 'open');
285
+ sidebar.style.display = 'block';
286
+ setTimeout(() => {
287
+ sidebar.style.transform = 'translateX(0)';
288
+ content.style.transform = 'translateX(0)';
289
+ content.classList.remove('ml-16');
290
+ content.style.width = 'calc(100% - 240px)';
291
+ }, 10);
292
+ }
293
+
294
+ function hideSidebar() {
295
+ if (!sidebar || !content) return;
296
+ isOpen = false;
297
+ sidebar.style.transform = 'translateX(-100%)';
298
+ content.style.transform = 'translateX(0px)';
299
+ content.style.width = '100%';
300
+ content.classList.add('ml-16');
301
+ }
302
+
303
+ if (sidebar) {
304
+ sidebar.addEventListener('transitionend', () => {
305
+ if (!isOpen && sidebar && content) {
306
+ sidebar.style.display = 'none';
307
+ content.style.transform = 'translateX(0px)';
308
+ }
309
+ });
310
+ }
311
+ });
312
+ </script>
@@ -1,14 +1,11 @@
1
1
  ---
2
- import BasicList from '@components/Lists/BasicList';
3
- import PlainPage from '@layouts/PlainPage.astro';
4
2
  import { getCommands } from '@utils/commands';
5
3
  import { getDomains } from '@utils/domains/domains';
6
4
  import { getEvents } from '@utils/events';
7
5
  import { getFlows } from '@utils/flows/flows';
8
6
  import { getQueries } from '@utils/queries';
9
7
  import { getServices } from '@utils/services/services';
10
- import { buildUrl } from '@utils/url-builder';
11
- import { ViewTransitions } from 'astro:transitions';
8
+ import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
12
9
 
13
10
  const [services, events, commands, queries, domains, flows] = await Promise.all([
14
11
  getServices(),
@@ -55,10 +52,10 @@ const getColor = (collection: string) => {
55
52
  };
56
53
  ---
57
54
 
58
- <PlainPage title={title} description={description}>
55
+ <VerticalSideBarLayout title={title} description={description}>
59
56
  <div class="">
60
57
  <div class="">
61
- <div class="hidden md:block">
58
+ <!-- <div class="hidden md:block">
62
59
  <aside class="sm:fixed grow w-56 xl:w-[19em] overflow-y-auto h-full z-10 pb-20" id="visualiser-navigation">
63
60
  <div class="w-full">
64
61
  <div class="sticky top-0 z-10 h-8 pointer-events-none -mt-7">
@@ -93,9 +90,9 @@ const getColor = (collection: string) => {
93
90
  }
94
91
  </div>
95
92
  </aside>
96
- </div>
93
+ </div> -->
97
94
 
98
- <main class="flex-1 h-full w-full relative sm:pl-60 xl:pl-80">
95
+ <main class="flex-1 h-full w-full relative">
99
96
  <!-- <button
100
97
  id="fullscreen-toggle"
101
98
  class="absolute top-[1em] z-40 left-5 bg-white hover:bg-gray-100/50 border border-gray-200 hover:text-primary text-gray-800 font-semibold py-2 px-4 rounded-lg transition duration-300 ease-in-out flex items-center space-x-2 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75"
@@ -112,9 +109,8 @@ const getColor = (collection: string) => {
112
109
  <slot />
113
110
  </main>
114
111
  </div>
115
- <ViewTransitions />
116
112
  </div>
117
- </PlainPage>
113
+ </VerticalSideBarLayout>
118
114
 
119
115
  <script>
120
116
  function setupSidebarToggle() {
@@ -14,6 +14,7 @@ import js from '@asyncapi/react-component/browser/standalone/without-parser.js?u
14
14
  import { AsyncApiComponentWP, type ConfigInterface } from '@asyncapi/react-component';
15
15
  import { pageDataLoader } from '@utils/pages/pages';
16
16
  import type { CollectionEntry } from 'astro:content';
17
+ import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
17
18
 
18
19
  export async function getStaticPaths() {
19
20
  const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains'];
@@ -52,9 +53,9 @@ const component = createElement(AsyncApiComponentWP, { schema: { stringified },
52
53
  const renderedComponent = renderToString(component);
53
54
  ---
54
55
 
55
- <PlainPage title="AsyncApi Spec">
56
+ <VerticalSideBarLayout title="AsyncApi Spec">
56
57
  <div id="asyncapi" class="md:pr-14" set:html={renderedComponent} />
57
- </PlainPage>
58
+ </VerticalSideBarLayout>
58
59
 
59
60
  <script is:inline src={js}></script>
60
61
  <script define:vars={{ schema: stringified, config }}>
@@ -1,5 +1,4 @@
1
1
  ---
2
- import Layout from '@layouts/DocsLayout.astro';
3
2
  import Footer from '@layouts/Footer.astro';
4
3
 
5
4
  import type { PageTypes } from '@types';
@@ -11,6 +10,8 @@ import 'diff2html/bundles/css/diff2html.min.css';
11
10
  import { buildUrl } from '@utils/url-builder';
12
11
  import { getVersions, getPreviousVersion } from '@utils/collections/util';
13
12
  import { getDiffsForCurrentAndPreviousVersion } from '@utils/collections/file-diffs';
13
+ import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
14
+ import { ViewTransitions } from 'astro:transitions';
14
15
 
15
16
  export async function getStaticPaths() {
16
17
  const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains'];
@@ -100,10 +101,43 @@ const getBadge = () => {
100
101
  };
101
102
 
102
103
  const badges = [getBadge()];
104
+ import { HomeIcon } from '@heroicons/react/20/solid';
105
+
106
+ const pages = [
107
+ { name: 'Projects', href: '#', current: false },
108
+ { name: 'Project Nero', href: '#', current: true },
109
+ ];
103
110
  ---
104
111
 
105
- <Layout title="ChangeLog">
106
- <main class="flex-1 w-full lg:pr-10 md:pt-4">
112
+ <VerticalSideBarLayout title="ChangeLog">
113
+ <main class="w-full md:pt-4 px-8 overflow-y-auto h-full max-w-[95%]">
114
+ <nav aria-label="Breadcrumb" class="flex">
115
+ <ol role="list" class="flex items-center space-x-2">
116
+ <li>
117
+ <div>
118
+ <a
119
+ href={buildUrl(`/docs/${props.collection}/${props.data.id}/${props.data.version}`)}
120
+ class="text-sm font-medium text-gray-500 hover:text-gray-700"
121
+ >
122
+ {props.data.name}
123
+ </a>
124
+ </div>
125
+ </li>
126
+ <li>
127
+ <div class="flex items-center">
128
+ <svg fill="currentColor" viewBox="0 0 20 20" aria-hidden="true" class="h-5 w-5 flex-shrink-0 text-gray-300">
129
+ <path d="M5.555 17.776l8-16 .894.448-8 16-.894-.448z"></path>
130
+ </svg>
131
+ <a
132
+ href={buildUrl(`/docs/${props.collection}/${props.data.id}/${props.data.version}`)}
133
+ class="text-sm font-medium text-gray-500 hover:text-gray-700"
134
+ >
135
+ Changelog
136
+ </a>
137
+ </div>
138
+ </li>
139
+ </ol>
140
+ </nav>
107
141
  <div class="border-b border-gray-200 flex justify-between items-start py-4 w-full">
108
142
  <div>
109
143
  <h2 class="text-2xl md:text-4xl font-bold">{props.data.name} (Changelog)</h2>
@@ -131,7 +165,7 @@ const badges = [getBadge()];
131
165
  </div>
132
166
  )
133
167
  }
134
- <div class="flow-root py-8">
168
+ <div class="flow-root py-8 w-full">
135
169
  <ul role="list" class="-mb-8">
136
170
  {
137
171
  logList.map((log, index) => (
@@ -188,4 +222,5 @@ const badges = [getBadge()];
188
222
  </div>
189
223
  <Footer />
190
224
  </main>
191
- </Layout>
225
+ <ViewTransitions />
226
+ </VerticalSideBarLayout>