@eventcatalog/core 3.29.1 → 3.30.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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-H5UC2A5F.js → chunk-6UG4JMUV.js} +1 -1
- package/dist/{chunk-4MSAPCV3.js → chunk-ATRBVTJ6.js} +1 -1
- package/dist/{chunk-PLNJC7NZ.js → chunk-K3ZVEX2Y.js} +13 -2
- package/dist/{chunk-V4OTI3PF.js → chunk-MVZKHUX2.js} +1 -1
- package/dist/{chunk-FVKDNLZK.js → chunk-RRBDF4MM.js} +1 -1
- package/dist/{chunk-24NGK43A.js → chunk-Z26P4PCB.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +14 -3
- package/dist/eventcatalog.js +6 -6
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/dist/watcher.cjs +13 -2
- package/dist/watcher.js +1 -1
- package/eventcatalog/astro.config.mjs +1 -1
- package/eventcatalog/public/logo.png +0 -0
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +2 -2
- package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
- package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
- package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
- package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
- package/eventcatalog/src/components/Header.astro +9 -19
- package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
- package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
- package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
- package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
- package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
- package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
- package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
- package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
- package/eventcatalog/src/components/Search/Search.astro +1 -1
- package/eventcatalog/src/components/Seo.astro +1 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +229 -256
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +78 -59
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
- package/eventcatalog/src/components/Tables/Table.tsx +21 -18
- package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
- package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
- package/eventcatalog/src/enterprise/auth/error.astro +1 -1
- package/eventcatalog/src/enterprise/auth/login.astro +1 -1
- package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +95 -93
- package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +174 -136
- package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
- package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
- package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +528 -146
- package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
- package/eventcatalog/src/pages/_index.astro +5 -3
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
- package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +129 -29
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +129 -29
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +21 -18
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +33 -32
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +2 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +4 -6
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +11 -4
- package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
- package/eventcatalog/src/pages/studio.astro +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/styles/theme.css +68 -12
- package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
- package/package.json +1 -1
- package/eventcatalog/public/logo.svg +0 -14
- package/eventcatalog/src/enterprise/plans/index.astro +0 -319
|
@@ -43,6 +43,7 @@ export interface DiscoverTableData {
|
|
|
43
43
|
id: string;
|
|
44
44
|
name: string;
|
|
45
45
|
summary?: string;
|
|
46
|
+
icon?: string;
|
|
46
47
|
version: string;
|
|
47
48
|
latestVersion?: string;
|
|
48
49
|
draft?: boolean | { title?: string; message: string };
|
|
@@ -73,6 +74,7 @@ export interface DiscoverTableProps<T extends DiscoverTableData> {
|
|
|
73
74
|
data: T[];
|
|
74
75
|
collectionType: CollectionType;
|
|
75
76
|
collectionLabel: string;
|
|
77
|
+
collectionDescription?: string;
|
|
76
78
|
domains?: Array<{ id: string; name: string; version: string }>;
|
|
77
79
|
owners?: Array<{ id: string; name: string; type?: 'user' | 'team' }>;
|
|
78
80
|
producers?: Array<{ id: string; name: string }>;
|
|
@@ -89,6 +91,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
89
91
|
data: initialData,
|
|
90
92
|
collectionType,
|
|
91
93
|
collectionLabel,
|
|
94
|
+
collectionDescription,
|
|
92
95
|
domains = [],
|
|
93
96
|
owners = [],
|
|
94
97
|
producers = [],
|
|
@@ -427,9 +430,16 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
427
430
|
const selectedPropertyLabels = selectedProperties.map((id) => propertyOptions.find((p) => p.id === id)?.label || id);
|
|
428
431
|
|
|
429
432
|
return (
|
|
430
|
-
<div className="flex h-full">
|
|
433
|
+
<div className="flex h-full min-h-0" style={{ ['--ec-discover-sidebar-width' as any]: '320px' }}>
|
|
431
434
|
{/* Filter Sidebar */}
|
|
432
|
-
<div
|
|
435
|
+
<div
|
|
436
|
+
className="fixed left-[var(--ec-vertical-nav-width)] top-0 z-20 flex h-screen w-[320px] flex-shrink-0 flex-col border-r border-[rgb(var(--ec-content-border))] bg-[rgb(var(--ec-page-bg))]"
|
|
437
|
+
style={{ width: 'var(--ec-discover-sidebar-width, 320px)' }}
|
|
438
|
+
>
|
|
439
|
+
<div className="flex h-[60px] flex-shrink-0 items-center border-b border-[rgb(var(--ec-page-border))] px-4">
|
|
440
|
+
<h2 className="text-[13px] font-semibold text-[rgb(var(--ec-page-text))]">{collectionLabel} Filters</h2>
|
|
441
|
+
</div>
|
|
442
|
+
|
|
433
443
|
{/* Filter sections */}
|
|
434
444
|
<div className="flex-1 overflow-y-auto px-4 pt-4 pb-4 space-y-6">
|
|
435
445
|
{/* Message Filters Section */}
|
|
@@ -495,10 +505,6 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
495
505
|
|
|
496
506
|
{/* Catalog Filters Section */}
|
|
497
507
|
<div className="space-y-3">
|
|
498
|
-
<h3 className="text-[11px] font-bold uppercase tracking-widest text-[rgb(var(--ec-page-text))] pb-2">
|
|
499
|
-
Catalog Filters
|
|
500
|
-
</h3>
|
|
501
|
-
|
|
502
508
|
{/* Domains Filter */}
|
|
503
509
|
{showDomainsFilter && domains.length > 0 && (
|
|
504
510
|
<div>
|
|
@@ -666,13 +672,21 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
666
672
|
</div>
|
|
667
673
|
|
|
668
674
|
{/* Main Table */}
|
|
669
|
-
<div
|
|
675
|
+
<div
|
|
676
|
+
className="flex-1 min-w-0 flex flex-col overflow-hidden"
|
|
677
|
+
style={{ marginLeft: 'var(--ec-discover-sidebar-width, 320px)' }}
|
|
678
|
+
>
|
|
670
679
|
{/* Table Header */}
|
|
671
|
-
<div className="flex items-
|
|
672
|
-
<
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
680
|
+
<div className="flex items-end justify-between gap-6 px-6 py-5">
|
|
681
|
+
<div className="min-w-0">
|
|
682
|
+
<h2 className="text-2xl font-semibold text-[rgb(var(--ec-page-text))] md:text-4xl">
|
|
683
|
+
{collectionLabel}{' '}
|
|
684
|
+
<span className="ml-1 text-lg font-normal text-[rgb(var(--ec-page-text-muted))] md:text-3xl">({totalResults})</span>
|
|
685
|
+
</h2>
|
|
686
|
+
{collectionDescription && (
|
|
687
|
+
<p className="max-w-3xl pt-2 text-base font-light text-[rgb(var(--ec-page-text-muted))]">{collectionDescription}</p>
|
|
688
|
+
)}
|
|
689
|
+
</div>
|
|
676
690
|
<div className="relative">
|
|
677
691
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[rgb(var(--ec-icon-color))]" />
|
|
678
692
|
<input
|
|
@@ -680,7 +694,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
680
694
|
value={tableFilter}
|
|
681
695
|
onChange={(e) => setTableFilter(e.target.value)}
|
|
682
696
|
placeholder="Filter..."
|
|
683
|
-
className="
|
|
697
|
+
className="w-64 rounded-lg border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-dropdown-bg))] py-2 pl-9 pr-3 text-sm text-[rgb(var(--ec-input-text))] placeholder:text-[rgb(var(--ec-icon-color))] transition-colors focus:border-[rgb(var(--ec-accent))] focus:outline-hidden focus:ring-1 focus:ring-[rgb(var(--ec-accent)/0.3)]"
|
|
684
698
|
/>
|
|
685
699
|
{tableFilter && (
|
|
686
700
|
<button
|
|
@@ -694,55 +708,60 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
694
708
|
</div>
|
|
695
709
|
|
|
696
710
|
{/* Table */}
|
|
697
|
-
<div className="flex-1 overflow-auto px-6">
|
|
698
|
-
<
|
|
699
|
-
<
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
{headerGroup
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
|
708
|
-
</th>
|
|
709
|
-
))}
|
|
710
|
-
</tr>
|
|
711
|
-
))}
|
|
712
|
-
</thead>
|
|
713
|
-
|
|
714
|
-
<tbody className="divide-y divide-[rgb(var(--ec-page-border)/0.5)]">
|
|
715
|
-
{hasResults ? (
|
|
716
|
-
table.getRowModel().rows.map((row, index) => (
|
|
717
|
-
<tr key={`${row.id}-${index}`} className="group hover:bg-[rgb(var(--ec-content-hover))] transition-colors">
|
|
718
|
-
{row.getVisibleCells().map((cell) => (
|
|
719
|
-
<td
|
|
720
|
-
key={cell.id}
|
|
721
|
-
className={`px-4 py-3 text-sm text-[rgb(var(--ec-page-text))] ${cell.column.columnDef.meta?.className || ''}`}
|
|
711
|
+
<div className="min-h-0 flex-1 overflow-auto px-6 pb-5">
|
|
712
|
+
<div className="overflow-hidden rounded-xl border border-[rgb(var(--ec-page-border)/0.72)] dark:border-white/10 bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
|
|
713
|
+
<table className="min-w-full divide-y divide-[rgb(var(--ec-page-border)/0.62)] dark:divide-white/10">
|
|
714
|
+
<thead className="sticky top-0 z-10 bg-[rgb(var(--ec-content-hover)/0.45)]">
|
|
715
|
+
{table.getHeaderGroups().map((headerGroup, index) => (
|
|
716
|
+
<tr key={`${headerGroup}-${index}`}>
|
|
717
|
+
{headerGroup.headers.map((header) => (
|
|
718
|
+
<th
|
|
719
|
+
key={`${header.id}`}
|
|
720
|
+
className="px-4 py-2.5 text-left text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] uppercase tracking-wider"
|
|
722
721
|
>
|
|
723
|
-
{flexRender(
|
|
724
|
-
</
|
|
722
|
+
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
|
723
|
+
</th>
|
|
725
724
|
))}
|
|
726
725
|
</tr>
|
|
727
|
-
))
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
726
|
+
))}
|
|
727
|
+
</thead>
|
|
728
|
+
|
|
729
|
+
<tbody className="divide-y divide-[rgb(var(--ec-page-border)/0.5)] dark:divide-white/8">
|
|
730
|
+
{hasResults ? (
|
|
731
|
+
table.getRowModel().rows.map((row, index) => (
|
|
732
|
+
<tr
|
|
733
|
+
key={`${row.id}-${index}`}
|
|
734
|
+
className="group bg-transparent transition-colors hover:bg-[rgb(var(--ec-content-hover)/0.38)]"
|
|
735
|
+
>
|
|
736
|
+
{row.getVisibleCells().map((cell) => (
|
|
737
|
+
<td
|
|
738
|
+
key={cell.id}
|
|
739
|
+
className={`px-4 py-3 text-sm text-[rgb(var(--ec-page-text))] ${cell.column.columnDef.meta?.className || ''}`}
|
|
740
|
+
>
|
|
741
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
742
|
+
</td>
|
|
743
|
+
))}
|
|
744
|
+
</tr>
|
|
745
|
+
))
|
|
746
|
+
) : (
|
|
747
|
+
<tr>
|
|
748
|
+
<td colSpan={table.getAllColumns().length} className="px-4 py-12 text-center">
|
|
749
|
+
<div className="flex flex-col items-center justify-center text-[rgb(var(--ec-page-text-muted))]">
|
|
750
|
+
<SearchX className="w-10 h-10 text-[rgb(var(--ec-icon-color))] mb-3 opacity-50" />
|
|
751
|
+
<p className="text-sm font-medium text-[rgb(var(--ec-page-text-muted))]">No results found</p>
|
|
752
|
+
<p className="text-xs text-[rgb(var(--ec-icon-color))] mt-1">Try adjusting your search or filters</p>
|
|
753
|
+
{activeFilterCount > 0 && (
|
|
754
|
+
<button onClick={clearAllFilters} className="mt-3 text-sm text-[rgb(var(--ec-accent))] hover:underline">
|
|
755
|
+
Clear all filters
|
|
756
|
+
</button>
|
|
757
|
+
)}
|
|
758
|
+
</div>
|
|
759
|
+
</td>
|
|
760
|
+
</tr>
|
|
761
|
+
)}
|
|
762
|
+
</tbody>
|
|
763
|
+
</table>
|
|
764
|
+
</div>
|
|
746
765
|
</div>
|
|
747
766
|
|
|
748
767
|
{/* Pagination */}
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
import { createColumnHelper } from '@tanstack/react-table';
|
|
2
|
-
import { useMemo, useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
BoltIcon,
|
|
6
|
-
ChatBubbleLeftIcon,
|
|
7
|
-
MagnifyingGlassIcon,
|
|
8
|
-
RectangleGroupIcon,
|
|
9
|
-
QueueListIcon,
|
|
10
|
-
DocumentTextIcon,
|
|
11
|
-
MapIcon,
|
|
12
|
-
CubeIcon,
|
|
13
|
-
} from '@heroicons/react/24/solid';
|
|
14
|
-
import { ArrowDownIcon, ArrowUpIcon } from '@heroicons/react/24/outline';
|
|
15
|
-
import { DatabaseIcon } from 'lucide-react';
|
|
16
|
-
import * as Tooltip from '@radix-ui/react-tooltip';
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { DocumentTextIcon, MapIcon } from '@heroicons/react/24/solid';
|
|
4
|
+
import { ArrowDownIcon, ArrowUpIcon, EllipsisVerticalIcon, StarIcon } from '@heroicons/react/24/outline';
|
|
17
5
|
import { buildUrl } from '@utils/url-builder';
|
|
18
6
|
import { getColorAndIconForCollection } from '@utils/collections/icons';
|
|
19
|
-
import
|
|
7
|
+
import { isIconPath, resolveIconUrl } from '@utils/icon';
|
|
8
|
+
import { useStore } from '@nanostores/react';
|
|
9
|
+
import { favoritesStore, toggleFavorite, type FavoriteItem } from '../../../stores/favorites-store';
|
|
20
10
|
import type { DiscoverTableData, CollectionType } from './DiscoverTable';
|
|
21
11
|
import type { TableConfiguration } from '@types';
|
|
22
12
|
|
|
@@ -34,25 +24,6 @@ const colorClasses: Record<string, string> = {
|
|
|
34
24
|
cyan: 'text-cyan-500',
|
|
35
25
|
};
|
|
36
26
|
|
|
37
|
-
// Reusable tooltip wrapper component
|
|
38
|
-
const ActionTooltip = ({ children, label }: { children: React.ReactNode; label: string }) => (
|
|
39
|
-
<Tooltip.Provider delayDuration={200}>
|
|
40
|
-
<Tooltip.Root>
|
|
41
|
-
<Tooltip.Trigger asChild>{children}</Tooltip.Trigger>
|
|
42
|
-
<Tooltip.Portal>
|
|
43
|
-
<Tooltip.Content
|
|
44
|
-
className="bg-[rgb(var(--ec-page-text))] text-[rgb(var(--ec-page-bg))] rounded px-2 py-1 text-xs shadow-md z-50"
|
|
45
|
-
side="top"
|
|
46
|
-
sideOffset={5}
|
|
47
|
-
>
|
|
48
|
-
{label}
|
|
49
|
-
<Tooltip.Arrow className="fill-[rgb(var(--ec-page-text))]" />
|
|
50
|
-
</Tooltip.Content>
|
|
51
|
-
</Tooltip.Portal>
|
|
52
|
-
</Tooltip.Root>
|
|
53
|
-
</Tooltip.Provider>
|
|
54
|
-
);
|
|
55
|
-
|
|
56
27
|
const columnHelper = createColumnHelper<DiscoverTableData>();
|
|
57
28
|
|
|
58
29
|
// Badge cell component (proper React component to use hooks)
|
|
@@ -95,6 +66,119 @@ const createBadgesColumn = (tableConfiguration: TableConfiguration) =>
|
|
|
95
66
|
},
|
|
96
67
|
});
|
|
97
68
|
|
|
69
|
+
const ResourceNameCell = ({ item }: { item: DiscoverTableData }) => {
|
|
70
|
+
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
71
|
+
const { color, Icon } = getColorAndIconForCollection(item.collection);
|
|
72
|
+
const resourceIcon = item.data.icon;
|
|
73
|
+
const resourceIconUrl = isIconPath(resourceIcon) ? resolveIconUrl(resourceIcon) : null;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<a
|
|
77
|
+
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
78
|
+
className="group inline-flex items-center gap-2.5 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
79
|
+
>
|
|
80
|
+
{resourceIconUrl ? (
|
|
81
|
+
<img src={resourceIconUrl} alt="" className="h-5 w-5 flex-shrink-0 rounded-sm object-contain" />
|
|
82
|
+
) : (
|
|
83
|
+
<Icon className={`h-4 w-4 flex-shrink-0 ${colorClasses[color] || 'text-[rgb(var(--ec-icon-color))]'}`} />
|
|
84
|
+
)}
|
|
85
|
+
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
86
|
+
{item.data.name}
|
|
87
|
+
</span>
|
|
88
|
+
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
89
|
+
</a>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const RowActionsMenu = ({ item, collectionType }: { item: DiscoverTableData; collectionType: CollectionType }) => {
|
|
94
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
95
|
+
const menuRef = useRef<HTMLDivElement>(null);
|
|
96
|
+
const favorites = useStore(favoritesStore);
|
|
97
|
+
const href = buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`);
|
|
98
|
+
const visualiserHref = buildUrl(`/visualiser/${item.collection}/${item.data.id}/${item.data.version}`);
|
|
99
|
+
const nodeKey = `${item.collection}-${item.data.id}-${item.data.version}`;
|
|
100
|
+
const badgeLabel =
|
|
101
|
+
collectionType === 'external-systems'
|
|
102
|
+
? 'External System'
|
|
103
|
+
: collectionType.charAt(0).toUpperCase() + collectionType.slice(1, -1);
|
|
104
|
+
const isFavorite = favorites.some((fav) => fav.nodeKey === nodeKey);
|
|
105
|
+
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const handlePointerDown = (event: MouseEvent) => {
|
|
108
|
+
if (!menuRef.current?.contains(event.target as Node)) {
|
|
109
|
+
setIsOpen(false);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const handleEscape = (event: KeyboardEvent) => {
|
|
114
|
+
if (event.key === 'Escape') {
|
|
115
|
+
setIsOpen(false);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
document.addEventListener('mousedown', handlePointerDown);
|
|
120
|
+
document.addEventListener('keydown', handleEscape);
|
|
121
|
+
|
|
122
|
+
return () => {
|
|
123
|
+
document.removeEventListener('mousedown', handlePointerDown);
|
|
124
|
+
document.removeEventListener('keydown', handleEscape);
|
|
125
|
+
};
|
|
126
|
+
}, []);
|
|
127
|
+
|
|
128
|
+
const handleToggleFavorite = () => {
|
|
129
|
+
const favoriteItem: FavoriteItem = {
|
|
130
|
+
nodeKey,
|
|
131
|
+
path: [],
|
|
132
|
+
title: item.data.name,
|
|
133
|
+
badge: badgeLabel,
|
|
134
|
+
href,
|
|
135
|
+
};
|
|
136
|
+
toggleFavorite(favoriteItem);
|
|
137
|
+
setIsOpen(false);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<div className="relative flex justify-end" ref={menuRef}>
|
|
142
|
+
<button
|
|
143
|
+
type="button"
|
|
144
|
+
aria-haspopup="menu"
|
|
145
|
+
aria-expanded={isOpen}
|
|
146
|
+
onClick={() => setIsOpen((prev) => !prev)}
|
|
147
|
+
className="rounded-md p-1.5 text-[rgb(var(--ec-icon-color))] transition-colors hover:bg-[rgb(var(--ec-content-hover)/0.5)] hover:text-[rgb(var(--ec-page-text))]"
|
|
148
|
+
>
|
|
149
|
+
<EllipsisVerticalIcon className="h-4 w-4" />
|
|
150
|
+
</button>
|
|
151
|
+
|
|
152
|
+
{isOpen && (
|
|
153
|
+
<div className="absolute right-0 top-[calc(100%+0.35rem)] z-30 min-w-[280px] overflow-hidden rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] shadow-xl">
|
|
154
|
+
<a
|
|
155
|
+
href={href}
|
|
156
|
+
className="flex items-center gap-2.5 px-3 py-2.5 text-xs font-medium text-[rgb(var(--ec-page-text))] transition-colors hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-accent))]"
|
|
157
|
+
>
|
|
158
|
+
<DocumentTextIcon className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))]" />
|
|
159
|
+
View documentation
|
|
160
|
+
</a>
|
|
161
|
+
<a
|
|
162
|
+
href={visualiserHref}
|
|
163
|
+
className="flex items-center gap-2.5 px-3 py-2.5 text-xs font-medium text-[rgb(var(--ec-page-text))] transition-colors hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-accent))]"
|
|
164
|
+
>
|
|
165
|
+
<MapIcon className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))]" />
|
|
166
|
+
View in visualiser
|
|
167
|
+
</a>
|
|
168
|
+
<button
|
|
169
|
+
type="button"
|
|
170
|
+
onClick={handleToggleFavorite}
|
|
171
|
+
className="flex w-full items-center gap-2.5 px-3 py-2.5 text-left text-xs font-medium text-[rgb(var(--ec-page-text))] transition-colors hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-accent))]"
|
|
172
|
+
>
|
|
173
|
+
<StarIcon className="h-3.5 w-3.5 text-[rgb(var(--ec-page-text-muted))]" />
|
|
174
|
+
{isFavorite ? 'Remove from favorites' : 'Add to favorites'}
|
|
175
|
+
</button>
|
|
176
|
+
</div>
|
|
177
|
+
)}
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
|
|
98
182
|
// Shared actions column
|
|
99
183
|
const createActionsColumn = (collectionType: CollectionType, tableConfiguration: TableConfiguration) =>
|
|
100
184
|
columnHelper.accessor('data.name', {
|
|
@@ -102,38 +186,7 @@ const createActionsColumn = (collectionType: CollectionType, tableConfiguration:
|
|
|
102
186
|
header: () => <span></span>,
|
|
103
187
|
cell: (info) => {
|
|
104
188
|
const item = info.row.original;
|
|
105
|
-
|
|
106
|
-
const nodeKey = `${item.collection}-${item.data.id}-${item.data.version}`;
|
|
107
|
-
const badgeLabel =
|
|
108
|
-
collectionType === 'external-systems'
|
|
109
|
-
? 'External System'
|
|
110
|
-
: collectionType.charAt(0).toUpperCase() + collectionType.slice(1, -1);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<div className="flex items-center gap-0.5">
|
|
114
|
-
<ActionTooltip label="View documentation">
|
|
115
|
-
<a
|
|
116
|
-
className="p-1.5 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-accent))] hover:bg-[rgb(var(--ec-accent)/0.1)] rounded-md transition-colors"
|
|
117
|
-
href={href}
|
|
118
|
-
>
|
|
119
|
-
<DocumentTextIcon className="w-4 h-4" />
|
|
120
|
-
</a>
|
|
121
|
-
</ActionTooltip>
|
|
122
|
-
<ActionTooltip label="View in visualiser">
|
|
123
|
-
<a
|
|
124
|
-
className="p-1.5 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-accent))] hover:bg-[rgb(var(--ec-accent)/0.1)] rounded-md transition-colors"
|
|
125
|
-
href={buildUrl(`/visualiser/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
126
|
-
>
|
|
127
|
-
<MapIcon className="w-4 h-4" />
|
|
128
|
-
</a>
|
|
129
|
-
</ActionTooltip>
|
|
130
|
-
<ActionTooltip label="Add to favorites">
|
|
131
|
-
<span>
|
|
132
|
-
<FavoriteButton nodeKey={nodeKey} title={item.data.name} badge={badgeLabel} href={href} size="sm" />
|
|
133
|
-
</span>
|
|
134
|
-
</ActionTooltip>
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
189
|
+
return <RowActionsMenu item={item} collectionType={collectionType} />;
|
|
137
190
|
},
|
|
138
191
|
meta: {
|
|
139
192
|
showFilter: false,
|
|
@@ -150,7 +203,7 @@ const createSummaryColumn = (tableConfiguration: TableConfiguration) =>
|
|
|
150
203
|
const isDraft = info.row.original.data.draft;
|
|
151
204
|
const displayText = `${summary || ''}${isDraft ? ' (Draft)' : ''}`;
|
|
152
205
|
return (
|
|
153
|
-
<span className="text-
|
|
206
|
+
<span className="text-[0.8rem] text-[rgb(var(--ec-icon-color))] line-clamp-2" title={displayText}>
|
|
154
207
|
{displayText}
|
|
155
208
|
</span>
|
|
156
209
|
);
|
|
@@ -193,7 +246,7 @@ const CollectionListCell = ({
|
|
|
193
246
|
<a
|
|
194
247
|
key={`${item.data.id}-${index}`}
|
|
195
248
|
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
196
|
-
className="group inline-flex items-center gap-1.5 text-
|
|
249
|
+
className="group inline-flex items-center gap-1.5 text-[0.8rem] text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
197
250
|
>
|
|
198
251
|
<item.Icon className={`h-3.5 w-3.5 ${colorClasses[item.color] || 'text-gray-500'} flex-shrink-0`} />
|
|
199
252
|
<span className="truncate max-w-[120px]" title={item.data.name}>
|
|
@@ -220,22 +273,7 @@ export const getEventColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
220
273
|
columnHelper.accessor('data.name', {
|
|
221
274
|
id: 'name',
|
|
222
275
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Event'}</span>,
|
|
223
|
-
cell: (info) => {
|
|
224
|
-
const item = info.row.original;
|
|
225
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
226
|
-
return (
|
|
227
|
-
<a
|
|
228
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
229
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
230
|
-
>
|
|
231
|
-
<BoltIcon className="h-4 w-4 text-orange-500 flex-shrink-0" />
|
|
232
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
233
|
-
{item.data.name}
|
|
234
|
-
</span>
|
|
235
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
236
|
-
</a>
|
|
237
|
-
);
|
|
238
|
-
},
|
|
276
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
239
277
|
meta: {
|
|
240
278
|
filterVariant: 'name',
|
|
241
279
|
},
|
|
@@ -268,22 +306,7 @@ export const getCommandColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
268
306
|
columnHelper.accessor('data.name', {
|
|
269
307
|
id: 'name',
|
|
270
308
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Command'}</span>,
|
|
271
|
-
cell: (info) => {
|
|
272
|
-
const item = info.row.original;
|
|
273
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
274
|
-
return (
|
|
275
|
-
<a
|
|
276
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
277
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
278
|
-
>
|
|
279
|
-
<ChatBubbleLeftIcon className="h-4 w-4 text-blue-500 flex-shrink-0" />
|
|
280
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
281
|
-
{item.data.name}
|
|
282
|
-
</span>
|
|
283
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
284
|
-
</a>
|
|
285
|
-
);
|
|
286
|
-
},
|
|
309
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
287
310
|
meta: {
|
|
288
311
|
filterVariant: 'name',
|
|
289
312
|
},
|
|
@@ -316,22 +339,7 @@ export const getQueryColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
316
339
|
columnHelper.accessor('data.name', {
|
|
317
340
|
id: 'name',
|
|
318
341
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Query'}</span>,
|
|
319
|
-
cell: (info) => {
|
|
320
|
-
const item = info.row.original;
|
|
321
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
322
|
-
return (
|
|
323
|
-
<a
|
|
324
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
325
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
326
|
-
>
|
|
327
|
-
<MagnifyingGlassIcon className="h-4 w-4 text-green-500 flex-shrink-0" />
|
|
328
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
329
|
-
{item.data.name}
|
|
330
|
-
</span>
|
|
331
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
332
|
-
</a>
|
|
333
|
-
);
|
|
334
|
-
},
|
|
342
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
335
343
|
meta: {
|
|
336
344
|
filterVariant: 'name',
|
|
337
345
|
},
|
|
@@ -364,22 +372,7 @@ export const getServiceColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
364
372
|
columnHelper.accessor('data.name', {
|
|
365
373
|
id: 'name',
|
|
366
374
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Service'}</span>,
|
|
367
|
-
cell: (info) => {
|
|
368
|
-
const item = info.row.original;
|
|
369
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
370
|
-
return (
|
|
371
|
-
<a
|
|
372
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
373
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
374
|
-
>
|
|
375
|
-
<ServerIcon className="h-4 w-4 text-pink-500 flex-shrink-0" />
|
|
376
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
377
|
-
{item.data.name}
|
|
378
|
-
</span>
|
|
379
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
380
|
-
</a>
|
|
381
|
-
);
|
|
382
|
-
},
|
|
375
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
383
376
|
meta: {
|
|
384
377
|
filterVariant: 'name',
|
|
385
378
|
},
|
|
@@ -422,22 +415,7 @@ export const getDomainColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
422
415
|
columnHelper.accessor('data.name', {
|
|
423
416
|
id: 'name',
|
|
424
417
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Domain'}</span>,
|
|
425
|
-
cell: (info) => {
|
|
426
|
-
const item = info.row.original;
|
|
427
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
428
|
-
return (
|
|
429
|
-
<a
|
|
430
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
431
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
432
|
-
>
|
|
433
|
-
<RectangleGroupIcon className="h-4 w-4 text-yellow-500 flex-shrink-0" />
|
|
434
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
435
|
-
{item.data.name}
|
|
436
|
-
</span>
|
|
437
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
438
|
-
</a>
|
|
439
|
-
);
|
|
440
|
-
},
|
|
418
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
441
419
|
meta: {
|
|
442
420
|
filterVariant: 'name',
|
|
443
421
|
},
|
|
@@ -462,22 +440,7 @@ export const getFlowColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
462
440
|
columnHelper.accessor('data.name', {
|
|
463
441
|
id: 'name',
|
|
464
442
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Flow'}</span>,
|
|
465
|
-
cell: (info) => {
|
|
466
|
-
const item = info.row.original;
|
|
467
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
468
|
-
return (
|
|
469
|
-
<a
|
|
470
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
471
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
472
|
-
>
|
|
473
|
-
<QueueListIcon className="h-4 w-4 text-teal-500 flex-shrink-0" />
|
|
474
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
475
|
-
{item.data.name}
|
|
476
|
-
</span>
|
|
477
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
478
|
-
</a>
|
|
479
|
-
);
|
|
480
|
-
},
|
|
443
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
481
444
|
meta: {
|
|
482
445
|
filterVariant: 'name',
|
|
483
446
|
},
|
|
@@ -494,22 +457,7 @@ export const getContainerColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
494
457
|
columnHelper.accessor('data.name', {
|
|
495
458
|
id: 'name',
|
|
496
459
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Data'}</span>,
|
|
497
|
-
cell: (info) => {
|
|
498
|
-
const item = info.row.original;
|
|
499
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
500
|
-
return (
|
|
501
|
-
<a
|
|
502
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
503
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
504
|
-
>
|
|
505
|
-
<DatabaseIcon className="h-4 w-4 text-blue-500 flex-shrink-0" />
|
|
506
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
507
|
-
{item.data.name}
|
|
508
|
-
</span>
|
|
509
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
510
|
-
</a>
|
|
511
|
-
);
|
|
512
|
-
},
|
|
460
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
513
461
|
meta: {
|
|
514
462
|
filterVariant: 'name',
|
|
515
463
|
},
|
|
@@ -552,22 +500,7 @@ export const getDataProductColumns = (tableConfiguration: TableConfiguration) =>
|
|
|
552
500
|
columnHelper.accessor('data.name', {
|
|
553
501
|
id: 'name',
|
|
554
502
|
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Data Product'}</span>,
|
|
555
|
-
cell: (info) => {
|
|
556
|
-
const item = info.row.original;
|
|
557
|
-
const isLatestVersion = item.data.version === item.data.latestVersion;
|
|
558
|
-
return (
|
|
559
|
-
<a
|
|
560
|
-
href={buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`)}
|
|
561
|
-
className="group inline-flex items-center gap-2 hover:text-[rgb(var(--ec-accent))] transition-colors"
|
|
562
|
-
>
|
|
563
|
-
<CubeIcon className="h-4 w-4 text-cyan-500 flex-shrink-0" />
|
|
564
|
-
<span className="text-sm font-semibold text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))]">
|
|
565
|
-
{item.data.name}
|
|
566
|
-
</span>
|
|
567
|
-
{!isLatestVersion && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
|
|
568
|
-
</a>
|
|
569
|
-
);
|
|
570
|
-
},
|
|
503
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
571
504
|
meta: {
|
|
572
505
|
filterVariant: 'name',
|
|
573
506
|
},
|