@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
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import { useState, useMemo, useEffect, useRef } from 'react';
|
|
2
|
-
import { DocumentTextIcon, MagnifyingGlassIcon
|
|
3
|
-
import {
|
|
4
|
-
BoltIcon,
|
|
5
|
-
ChatBubbleLeftIcon,
|
|
6
|
-
MagnifyingGlassIcon as MagnifyingGlassSolidIcon,
|
|
7
|
-
CodeBracketIcon,
|
|
8
|
-
DocumentCheckIcon,
|
|
9
|
-
} from '@heroicons/react/24/solid';
|
|
2
|
+
import { AdjustmentsHorizontalIcon, DocumentTextIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
|
10
3
|
import type { CollectionMessageTypes } from '@types';
|
|
11
|
-
|
|
12
|
-
// Specification file types (OpenAPI, AsyncAPI, GraphQL)
|
|
13
|
-
const SPEC_TYPES = ['openapi', 'asyncapi', 'graphql'];
|
|
14
|
-
const HIDDEN_FORMAT_FILTERS = new Set(['graphql', 'gql', 'yaml', 'yml']);
|
|
15
4
|
import semver from 'semver';
|
|
16
5
|
import SchemaListItem from './SchemaListItem';
|
|
17
6
|
import SchemaDetailsPanel from './SchemaDetailsPanel';
|
|
18
7
|
import Pagination from './Pagination';
|
|
19
8
|
import type { SchemaItem } from './types';
|
|
20
9
|
|
|
10
|
+
// Specification file types (OpenAPI, AsyncAPI, GraphQL)
|
|
11
|
+
const SPEC_TYPES = ['openapi', 'asyncapi', 'graphql'];
|
|
12
|
+
const HIDDEN_FORMAT_FILTERS = new Set(['graphql', 'gql', 'yaml', 'yml']);
|
|
13
|
+
const SCHEMA_TYPE_LABELS: Record<string, string> = {
|
|
14
|
+
json: 'JSON Schema',
|
|
15
|
+
asyncapi: 'AsyncAPI',
|
|
16
|
+
openapi: 'OpenAPI',
|
|
17
|
+
graphql: 'GraphQL',
|
|
18
|
+
avro: 'Avro',
|
|
19
|
+
avsc: 'Avro',
|
|
20
|
+
proto: 'Protobuf',
|
|
21
|
+
yaml: 'YAML',
|
|
22
|
+
yml: 'YAML',
|
|
23
|
+
xml: 'XML',
|
|
24
|
+
xsd: 'XML Schema',
|
|
25
|
+
};
|
|
26
|
+
|
|
21
27
|
/** Resolve the spec filename for a schema item, with consistent fallback. */
|
|
22
28
|
function getSpecFile(item: SchemaItem): string {
|
|
23
29
|
return item.specFilenameWithoutExtension || item.specName || '';
|
|
@@ -42,15 +48,14 @@ interface SchemaExplorerProps {
|
|
|
42
48
|
|
|
43
49
|
export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: SchemaExplorerProps) {
|
|
44
50
|
const [searchQuery, setSearchQuery] = useState(() => {
|
|
45
|
-
// Load from localStorage
|
|
46
51
|
if (typeof window !== 'undefined') {
|
|
47
52
|
const stored = localStorage.getItem('schemaRegistrySearchQuery');
|
|
48
53
|
return stored !== null ? stored : '';
|
|
49
54
|
}
|
|
50
55
|
return '';
|
|
51
56
|
});
|
|
57
|
+
|
|
52
58
|
const [selectedTypes, setSelectedTypes] = useState<Set<CollectionMessageTypes | 'specifications' | 'data-contracts'>>(() => {
|
|
53
|
-
// Load from localStorage
|
|
54
59
|
if (typeof window !== 'undefined') {
|
|
55
60
|
const stored = localStorage.getItem('schemaRegistrySelectedTypes');
|
|
56
61
|
if (stored) {
|
|
@@ -64,22 +69,30 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
64
69
|
}
|
|
65
70
|
return new Set();
|
|
66
71
|
});
|
|
72
|
+
|
|
67
73
|
const [selectedSchemaType, setSelectedSchemaType] = useState<'all' | string>(() => {
|
|
68
|
-
// Load from localStorage
|
|
69
74
|
if (typeof window !== 'undefined') {
|
|
70
75
|
const stored = localStorage.getItem('schemaRegistrySelectedSchemaType');
|
|
71
76
|
return stored !== null ? stored : 'all';
|
|
72
77
|
}
|
|
73
78
|
return 'all';
|
|
74
79
|
});
|
|
80
|
+
|
|
81
|
+
const [showFormatFilters, setShowFormatFilters] = useState(() => {
|
|
82
|
+
if (typeof window !== 'undefined') {
|
|
83
|
+
const stored = localStorage.getItem('schemaRegistrySelectedSchemaType');
|
|
84
|
+
return stored !== null && stored !== 'all';
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
});
|
|
88
|
+
|
|
75
89
|
const [selectedMessage, setSelectedMessage] = useState<SchemaItem | null>(null);
|
|
76
90
|
const [selectedVersion, setSelectedVersion] = useState<string | null>(null);
|
|
77
91
|
const [currentPage, setCurrentPage] = useState(1);
|
|
78
|
-
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
79
92
|
const selectedItemRef = useRef<HTMLButtonElement>(null);
|
|
93
|
+
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
80
94
|
const ITEMS_PER_PAGE = 50;
|
|
81
95
|
|
|
82
|
-
// Function to update URL with query params
|
|
83
96
|
const updateUrlParams = (message: SchemaItem) => {
|
|
84
97
|
if (typeof window === 'undefined') return;
|
|
85
98
|
|
|
@@ -88,7 +101,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
88
101
|
params.set('version', message.data.version);
|
|
89
102
|
params.set('collection', message.collection);
|
|
90
103
|
|
|
91
|
-
// For services, add spec type and filename to disambiguate multiple specs
|
|
92
104
|
if (message.collection === 'services') {
|
|
93
105
|
params.set('specType', message.specType || 'unknown');
|
|
94
106
|
const specFile = getSpecFile(message);
|
|
@@ -101,12 +113,11 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
101
113
|
window.history.pushState({}, '', newUrl);
|
|
102
114
|
};
|
|
103
115
|
|
|
104
|
-
// Group messages by ID (and spec type for services) and get all versions
|
|
105
116
|
const messagesByIdAndVersions = useMemo(() => {
|
|
106
117
|
const grouped = new Map<string, SchemaItem[]>();
|
|
118
|
+
|
|
107
119
|
schemas.forEach((message) => {
|
|
108
120
|
const groupKey = getGroupKey(message);
|
|
109
|
-
|
|
110
121
|
const existing = grouped.get(groupKey);
|
|
111
122
|
if (existing) {
|
|
112
123
|
existing.push(message);
|
|
@@ -115,42 +126,36 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
115
126
|
}
|
|
116
127
|
});
|
|
117
128
|
|
|
118
|
-
// Sort versions for each ID (descending - latest first)
|
|
119
129
|
grouped.forEach((versions, id) => {
|
|
120
130
|
versions.sort((a, b) => {
|
|
121
131
|
const aVersion = a.data.version;
|
|
122
132
|
const bVersion = b.data.version;
|
|
123
|
-
|
|
124
|
-
// Try to use semver for comparison
|
|
125
133
|
const aValid = semver.valid(semver.coerce(aVersion));
|
|
126
134
|
const bValid = semver.valid(semver.coerce(bVersion));
|
|
127
135
|
|
|
128
136
|
if (aValid && bValid) {
|
|
129
|
-
return semver.rcompare(aValid, bValid);
|
|
137
|
+
return semver.rcompare(aValid, bValid);
|
|
130
138
|
}
|
|
131
139
|
|
|
132
|
-
// Fall back to numeric comparison
|
|
133
140
|
const aNum = parseFloat(aVersion);
|
|
134
141
|
const bNum = parseFloat(bVersion);
|
|
135
142
|
if (!isNaN(aNum) && !isNaN(bNum)) {
|
|
136
143
|
return bNum - aNum;
|
|
137
144
|
}
|
|
138
145
|
|
|
139
|
-
// Final fallback to string comparison
|
|
140
146
|
return bVersion.localeCompare(aVersion);
|
|
141
147
|
});
|
|
148
|
+
|
|
142
149
|
grouped.set(id, versions);
|
|
143
150
|
});
|
|
144
151
|
|
|
145
152
|
return grouped;
|
|
146
153
|
}, [schemas]);
|
|
147
154
|
|
|
148
|
-
// Get latest version for each message (for sidebar display)
|
|
149
155
|
const latestMessages = useMemo(() => {
|
|
150
156
|
return Array.from(messagesByIdAndVersions.values()).map((versions) => versions[0]);
|
|
151
157
|
}, [messagesByIdAndVersions]);
|
|
152
158
|
|
|
153
|
-
// Get unique schema types (exclude types that aren't useful as standalone filters)
|
|
154
159
|
const schemaTypes = useMemo(() => {
|
|
155
160
|
const types = new Set<string>();
|
|
156
161
|
latestMessages.forEach((msg) => {
|
|
@@ -161,22 +166,17 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
161
166
|
return Array.from(types).sort();
|
|
162
167
|
}, [latestMessages]);
|
|
163
168
|
|
|
164
|
-
// Filter messages (using latest versions only)
|
|
165
169
|
const filteredMessages = useMemo(() => {
|
|
166
170
|
let result = [...latestMessages];
|
|
167
171
|
|
|
168
|
-
// Filter by message types (multi-select)
|
|
169
172
|
if (selectedTypes.size > 0) {
|
|
170
173
|
result = result.filter((msg) => {
|
|
171
|
-
// Check if message matches any selected collection type
|
|
172
174
|
if (selectedTypes.has(msg.collection as CollectionMessageTypes)) {
|
|
173
175
|
return true;
|
|
174
176
|
}
|
|
175
|
-
// Check if 'specifications' is selected and this is a spec file
|
|
176
177
|
if (selectedTypes.has('specifications') && SPEC_TYPES.includes(msg.schemaExtension?.toLowerCase() || '')) {
|
|
177
178
|
return true;
|
|
178
179
|
}
|
|
179
|
-
// Check if 'data-contracts' is selected and this is a data product contract
|
|
180
180
|
if (selectedTypes.has('data-contracts') && msg.collection === 'data-products') {
|
|
181
181
|
return true;
|
|
182
182
|
}
|
|
@@ -184,12 +184,10 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Filter by schema type
|
|
188
187
|
if (selectedSchemaType !== 'all') {
|
|
189
188
|
result = result.filter((msg) => msg.schemaExtension?.toLowerCase() === selectedSchemaType);
|
|
190
189
|
}
|
|
191
190
|
|
|
192
|
-
// Filter by search query
|
|
193
191
|
if (searchQuery) {
|
|
194
192
|
const query = searchQuery.toLowerCase();
|
|
195
193
|
result = result.filter(
|
|
@@ -200,7 +198,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
200
198
|
);
|
|
201
199
|
}
|
|
202
200
|
|
|
203
|
-
// Sort by name alphabetically
|
|
204
201
|
result.sort((a, b) => {
|
|
205
202
|
const nameA = a.data.name?.toLowerCase() || '';
|
|
206
203
|
const nameB = b.data.name?.toLowerCase() || '';
|
|
@@ -210,7 +207,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
210
207
|
return result;
|
|
211
208
|
}, [latestMessages, searchQuery, selectedTypes, selectedSchemaType]);
|
|
212
209
|
|
|
213
|
-
// Pagination
|
|
214
210
|
const totalPages = Math.ceil(filteredMessages.length / ITEMS_PER_PAGE);
|
|
215
211
|
const paginatedMessages = useMemo(() => {
|
|
216
212
|
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
|
|
@@ -221,7 +217,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
221
217
|
setCurrentPage(1);
|
|
222
218
|
}, [searchQuery, selectedTypes, selectedSchemaType]);
|
|
223
219
|
|
|
224
|
-
// Load from query string on mount
|
|
225
220
|
useEffect(() => {
|
|
226
221
|
if (typeof window === 'undefined') return;
|
|
227
222
|
|
|
@@ -233,13 +228,11 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
233
228
|
const specFilename = params.get('specFilename');
|
|
234
229
|
|
|
235
230
|
if (id && version) {
|
|
236
|
-
// Find the matching message
|
|
237
231
|
const matchingMessage = schemas.find((msg) => {
|
|
238
232
|
const idMatch = msg.data.id === id;
|
|
239
233
|
const versionMatch = msg.data.version === version;
|
|
240
234
|
const collectionMatch = !collection || msg.collection === collection;
|
|
241
235
|
|
|
242
|
-
// For services, also match spec type and filename
|
|
243
236
|
if (msg.collection === 'services') {
|
|
244
237
|
const specTypeMatch = !specType || msg.specType === specType;
|
|
245
238
|
const msgSpecFile = getSpecFile(msg);
|
|
@@ -254,7 +247,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
254
247
|
setSelectedMessage(matchingMessage);
|
|
255
248
|
setSelectedVersion(matchingMessage.data.version);
|
|
256
249
|
|
|
257
|
-
// Scroll to the selected item after a brief delay to ensure DOM is ready
|
|
258
250
|
setTimeout(() => {
|
|
259
251
|
if (selectedItemRef.current) {
|
|
260
252
|
selectedItemRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
@@ -264,7 +256,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
264
256
|
}
|
|
265
257
|
}, [schemas]);
|
|
266
258
|
|
|
267
|
-
// Auto-select first message when filters change (only if no query params)
|
|
268
259
|
useEffect(() => {
|
|
269
260
|
if (typeof window === 'undefined') return;
|
|
270
261
|
|
|
@@ -278,24 +269,19 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
278
269
|
}
|
|
279
270
|
}, [filteredMessages, selectedMessage]);
|
|
280
271
|
|
|
281
|
-
// Get the message to display (based on selected version)
|
|
282
272
|
const displayMessage = useMemo(() => {
|
|
283
273
|
if (!selectedMessage) return null;
|
|
284
274
|
|
|
285
275
|
const groupKey = getGroupKey(selectedMessage);
|
|
286
|
-
|
|
287
276
|
const versions = messagesByIdAndVersions.get(groupKey);
|
|
288
|
-
if (!versions) return selectedMessage;
|
|
289
277
|
|
|
290
|
-
|
|
278
|
+
if (!versions) return selectedMessage;
|
|
291
279
|
if (!selectedVersion) return versions[0];
|
|
292
280
|
|
|
293
|
-
// Find the message with the selected version
|
|
294
281
|
const versionedMessage = versions.find((v) => v.data.version === selectedVersion);
|
|
295
282
|
return versionedMessage || versions[0];
|
|
296
283
|
}, [selectedMessage, selectedVersion, messagesByIdAndVersions]);
|
|
297
284
|
|
|
298
|
-
// Save filter states to localStorage
|
|
299
285
|
useEffect(() => {
|
|
300
286
|
if (typeof window !== 'undefined') {
|
|
301
287
|
localStorage.setItem('schemaRegistrySearchQuery', searchQuery);
|
|
@@ -314,7 +300,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
314
300
|
}
|
|
315
301
|
}, [selectedSchemaType]);
|
|
316
302
|
|
|
317
|
-
// Keyboard shortcut for search (Cmd+K or Ctrl+K)
|
|
318
303
|
useEffect(() => {
|
|
319
304
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
320
305
|
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
@@ -322,11 +307,11 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
322
307
|
searchInputRef.current?.focus();
|
|
323
308
|
}
|
|
324
309
|
};
|
|
310
|
+
|
|
325
311
|
window.addEventListener('keydown', handleKeyDown);
|
|
326
312
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
327
313
|
}, []);
|
|
328
314
|
|
|
329
|
-
// Get available versions for the selected message
|
|
330
315
|
const availableVersions = useMemo(() => {
|
|
331
316
|
if (!displayMessage) return [];
|
|
332
317
|
const groupKey = getGroupKey(displayMessage);
|
|
@@ -337,14 +322,12 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
337
322
|
|
|
338
323
|
const handleVersionChange = (newVersion: string) => {
|
|
339
324
|
setSelectedVersion(newVersion);
|
|
340
|
-
// Update URL with new version
|
|
341
325
|
const versionedMessage = availableVersions.find((v) => v.data.version === newVersion);
|
|
342
326
|
if (versionedMessage) {
|
|
343
327
|
updateUrlParams(versionedMessage);
|
|
344
328
|
}
|
|
345
329
|
};
|
|
346
330
|
|
|
347
|
-
// Calculate stats
|
|
348
331
|
const stats = useMemo(() => {
|
|
349
332
|
return {
|
|
350
333
|
total: latestMessages.length,
|
|
@@ -356,7 +339,6 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
356
339
|
};
|
|
357
340
|
}, [latestMessages]);
|
|
358
341
|
|
|
359
|
-
// Toggle type selection (multi-select)
|
|
360
342
|
const toggleType = (type: CollectionMessageTypes | 'specifications' | 'data-contracts') => {
|
|
361
343
|
setSelectedTypes((prev) => {
|
|
362
344
|
const next = new Set(prev);
|
|
@@ -369,26 +351,35 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
369
351
|
});
|
|
370
352
|
};
|
|
371
353
|
|
|
372
|
-
// Clear all type filters
|
|
373
354
|
const clearTypeFilters = () => {
|
|
374
355
|
setSelectedTypes(new Set());
|
|
375
356
|
};
|
|
376
357
|
|
|
377
|
-
const hasActiveFilters = searchQuery || selectedTypes.size > 0 || selectedSchemaType !== 'all';
|
|
358
|
+
const hasActiveFilters = searchQuery.length > 0 || selectedTypes.size > 0 || selectedSchemaType !== 'all';
|
|
359
|
+
const activeFilterCount = (selectedTypes.size > 0 ? 1 : 0) + (selectedSchemaType !== 'all' ? 1 : 0);
|
|
360
|
+
const collectionTabs = [
|
|
361
|
+
{ key: 'all', label: 'All', count: stats.total },
|
|
362
|
+
{ key: 'events', label: 'Events', count: stats.events },
|
|
363
|
+
{ key: 'commands', label: 'Commands', count: stats.commands },
|
|
364
|
+
{ key: 'queries', label: 'Queries', count: stats.queries },
|
|
365
|
+
{ key: 'specifications', label: 'Specs', count: stats.specifications },
|
|
366
|
+
{ key: 'data-contracts', label: 'Contracts', count: stats.dataContracts },
|
|
367
|
+
].filter((tab) => tab.count > 0);
|
|
378
368
|
|
|
379
369
|
return (
|
|
380
|
-
<div className="h-full
|
|
370
|
+
<div className="flex h-full min-h-0 flex-col overflow-hidden">
|
|
381
371
|
<style
|
|
382
372
|
dangerouslySetInnerHTML={{
|
|
383
373
|
__html: '[data-theme="dark"] .schema-icon { filter: brightness(1.8) saturate(0.8); }',
|
|
384
374
|
}}
|
|
385
375
|
/>
|
|
386
|
-
<div className="flex-1
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
{
|
|
390
|
-
|
|
391
|
-
|
|
376
|
+
<div className="flex flex-1 min-h-0 gap-0 overflow-hidden">
|
|
377
|
+
<div
|
|
378
|
+
className="fixed top-0 z-20 flex h-screen flex-col overflow-hidden border-r border-[rgb(var(--ec-page-border))] bg-linear-to-b from-[rgb(var(--ec-page-bg))] via-[rgb(var(--ec-page-bg))] to-[rgb(var(--ec-accent)/0.06)]"
|
|
379
|
+
style={{ left: 'var(--ec-vertical-nav-width)', width: 'var(--ec-schema-sidebar-width, 360px)' }}
|
|
380
|
+
>
|
|
381
|
+
<div className="flex h-[60px] flex-shrink-0 items-center justify-between gap-2 border-b border-[rgb(var(--ec-page-border))] px-4">
|
|
382
|
+
<div className="relative min-w-0 flex-1">
|
|
392
383
|
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
393
384
|
<MagnifyingGlassIcon className="h-4 w-4 text-[rgb(var(--ec-icon-color))]" />
|
|
394
385
|
</div>
|
|
@@ -398,177 +389,144 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
398
389
|
placeholder="Search schemas..."
|
|
399
390
|
value={searchQuery}
|
|
400
391
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
401
|
-
className="w-full rounded-lg border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-dropdown-bg))] py-2 pl-9 pr-
|
|
392
|
+
className="w-full rounded-lg border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-dropdown-bg))] py-2 pl-9 pr-3 text-[12px] text-[rgb(var(--ec-page-text))] placeholder:text-[rgb(var(--ec-icon-color))] transition-all focus:border-[rgb(var(--ec-accent))] focus:outline-hidden focus:ring-1 focus:ring-[rgb(var(--ec-accent)/0.3)]"
|
|
402
393
|
/>
|
|
403
|
-
{searchQuery ? (
|
|
404
|
-
<button onClick={() => setSearchQuery('')} className="absolute inset-y-0 right-0 flex items-center pr-2.5">
|
|
405
|
-
<XMarkIcon className="h-4 w-4 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))]" />
|
|
406
|
-
</button>
|
|
407
|
-
) : (
|
|
408
|
-
<div className="absolute inset-y-0 right-0 flex items-center pr-2.5 pointer-events-none">
|
|
409
|
-
<kbd className="hidden sm:inline-flex items-center gap-0.5 rounded border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 text-[10px] font-medium text-[rgb(var(--ec-page-text-muted))]">
|
|
410
|
-
<span className="text-[11px]">⌘</span>K
|
|
411
|
-
</kbd>
|
|
412
|
-
</div>
|
|
413
|
-
)}
|
|
414
394
|
</div>
|
|
395
|
+
|
|
396
|
+
{schemaTypes.length > 0 && (
|
|
397
|
+
<button
|
|
398
|
+
onClick={() => setShowFormatFilters((prev) => !prev)}
|
|
399
|
+
aria-pressed={showFormatFilters || selectedSchemaType !== 'all'}
|
|
400
|
+
className={`relative inline-flex h-9 w-9 items-center justify-center rounded-lg border transition-all ${
|
|
401
|
+
showFormatFilters || selectedSchemaType !== 'all'
|
|
402
|
+
? 'border-[rgb(var(--ec-accent)/0.5)] bg-[rgb(var(--ec-accent))] text-white shadow-[0_10px_28px_rgb(var(--ec-accent)/0.3)]'
|
|
403
|
+
: 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-page-text-muted)/0.45)] hover:text-[rgb(var(--ec-page-text))]'
|
|
404
|
+
}`}
|
|
405
|
+
>
|
|
406
|
+
<AdjustmentsHorizontalIcon className="h-4.5 w-4.5" />
|
|
407
|
+
{activeFilterCount > 0 && (
|
|
408
|
+
<span className="absolute -right-1 -top-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full border border-[rgb(var(--ec-page-bg))] bg-[rgb(var(--ec-page-text))] px-1 text-[10px] font-semibold tabular-nums text-[rgb(var(--ec-page-bg))]">
|
|
409
|
+
{activeFilterCount}
|
|
410
|
+
</span>
|
|
411
|
+
)}
|
|
412
|
+
</button>
|
|
413
|
+
)}
|
|
415
414
|
</div>
|
|
416
415
|
|
|
417
|
-
{
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-accent))] bg-[rgb(var(--ec-accent)/0.08)]'
|
|
426
|
-
: 'border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-page-text-muted))]'
|
|
427
|
-
}`}
|
|
428
|
-
>
|
|
429
|
-
All formats
|
|
430
|
-
</button>
|
|
431
|
-
{schemaTypes.map((type) => {
|
|
432
|
-
const labels: Record<string, string> = {
|
|
433
|
-
json: 'JSON Schema',
|
|
434
|
-
asyncapi: 'AsyncAPI',
|
|
435
|
-
openapi: 'OpenAPI',
|
|
436
|
-
graphql: 'GraphQL',
|
|
437
|
-
avro: 'Avro',
|
|
438
|
-
avsc: 'Avro',
|
|
439
|
-
proto: 'Protobuf',
|
|
440
|
-
yaml: 'YAML',
|
|
441
|
-
yml: 'YAML',
|
|
442
|
-
xml: 'XML',
|
|
443
|
-
xsd: 'XML Schema',
|
|
444
|
-
};
|
|
445
|
-
return (
|
|
416
|
+
{(showFormatFilters || selectedSchemaType !== 'all' || selectedTypes.size > 0) && (
|
|
417
|
+
<div className="flex-shrink-0 border-b border-[rgb(var(--ec-page-border))] px-4 py-3">
|
|
418
|
+
<div className="rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.45)] p-3">
|
|
419
|
+
<div className="mb-3 flex items-center justify-between gap-3">
|
|
420
|
+
<span className="text-[11px] font-semibold uppercase tracking-[0.2em] text-[rgb(var(--ec-page-text-muted))]">
|
|
421
|
+
Filters
|
|
422
|
+
</span>
|
|
423
|
+
{hasActiveFilters && (
|
|
446
424
|
<button
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
}`}
|
|
425
|
+
onClick={() => {
|
|
426
|
+
setSearchQuery('');
|
|
427
|
+
clearTypeFilters();
|
|
428
|
+
setSelectedSchemaType('all');
|
|
429
|
+
}}
|
|
430
|
+
className="text-[11px] font-medium text-[rgb(var(--ec-accent))] hover:opacity-80"
|
|
454
431
|
>
|
|
455
|
-
|
|
432
|
+
Reset
|
|
456
433
|
</button>
|
|
457
|
-
)
|
|
458
|
-
|
|
434
|
+
)}
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<div>
|
|
438
|
+
<div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.18em] text-[rgb(var(--ec-page-text-muted))]">
|
|
439
|
+
Type
|
|
440
|
+
</div>
|
|
441
|
+
<div className="flex flex-wrap gap-1.5">
|
|
442
|
+
{collectionTabs.map((tab) => {
|
|
443
|
+
const isAll = tab.key === 'all';
|
|
444
|
+
const isActive = isAll ? selectedTypes.size === 0 : selectedTypes.has(tab.key as CollectionMessageTypes);
|
|
445
|
+
|
|
446
|
+
return (
|
|
447
|
+
<button
|
|
448
|
+
key={tab.key}
|
|
449
|
+
onClick={() => {
|
|
450
|
+
if (isAll) {
|
|
451
|
+
clearTypeFilters();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
toggleType(tab.key as CollectionMessageTypes | 'specifications' | 'data-contracts');
|
|
455
|
+
}}
|
|
456
|
+
className={`inline-flex items-center gap-1 rounded-md border px-2 py-1 text-[10px] font-medium transition-all ${
|
|
457
|
+
isActive
|
|
458
|
+
? 'border-[rgb(var(--ec-accent)/0.5)] bg-[rgb(var(--ec-accent)/0.16)] text-[rgb(var(--ec-page-text))] shadow-[0_0_0_1px_rgb(var(--ec-accent)/0.2)]'
|
|
459
|
+
: 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-page-text-muted)/0.3)] hover:text-[rgb(var(--ec-page-text))]'
|
|
460
|
+
}`}
|
|
461
|
+
>
|
|
462
|
+
<span>{tab.label}</span>
|
|
463
|
+
<span
|
|
464
|
+
className={`rounded-sm px-1 py-0.5 text-[8px] font-semibold tabular-nums ${
|
|
465
|
+
isActive
|
|
466
|
+
? 'bg-[rgb(var(--ec-accent)/0.18)] text-[rgb(var(--ec-page-text))]'
|
|
467
|
+
: 'bg-[rgb(var(--ec-content-hover))] text-[rgb(var(--ec-page-text-muted))]'
|
|
468
|
+
}`}
|
|
469
|
+
>
|
|
470
|
+
{tab.count}
|
|
471
|
+
</span>
|
|
472
|
+
</button>
|
|
473
|
+
);
|
|
474
|
+
})}
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
|
|
478
|
+
{schemaTypes.length > 0 && (
|
|
479
|
+
<div className="mt-3">
|
|
480
|
+
<div className="mb-2 flex items-center justify-between gap-3">
|
|
481
|
+
<span className="text-[10px] font-semibold uppercase tracking-[0.18em] text-[rgb(var(--ec-page-text-muted))]">
|
|
482
|
+
Format
|
|
483
|
+
</span>
|
|
484
|
+
{selectedSchemaType !== 'all' && (
|
|
485
|
+
<button
|
|
486
|
+
onClick={() => setSelectedSchemaType('all')}
|
|
487
|
+
className="text-[10px] font-medium text-[rgb(var(--ec-accent))] hover:opacity-80"
|
|
488
|
+
>
|
|
489
|
+
Clear
|
|
490
|
+
</button>
|
|
491
|
+
)}
|
|
492
|
+
</div>
|
|
493
|
+
<div className="flex flex-wrap gap-1.5">
|
|
494
|
+
<button
|
|
495
|
+
onClick={() => setSelectedSchemaType('all')}
|
|
496
|
+
className={`rounded-md border px-2 py-1 text-[10px] font-medium transition-all ${
|
|
497
|
+
selectedSchemaType === 'all'
|
|
498
|
+
? 'border-[rgb(var(--ec-accent)/0.45)] bg-[rgb(var(--ec-accent)/0.16)] text-[rgb(var(--ec-page-text))]'
|
|
499
|
+
: 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
500
|
+
}`}
|
|
501
|
+
>
|
|
502
|
+
All formats
|
|
503
|
+
</button>
|
|
504
|
+
{schemaTypes.map((type) => (
|
|
505
|
+
<button
|
|
506
|
+
key={type}
|
|
507
|
+
onClick={() => setSelectedSchemaType(selectedSchemaType === type ? 'all' : type)}
|
|
508
|
+
className={`rounded-md border px-2 py-1 text-[10px] font-medium transition-all ${
|
|
509
|
+
selectedSchemaType === type
|
|
510
|
+
? 'border-[rgb(var(--ec-accent)/0.45)] bg-[rgb(var(--ec-accent)/0.16)] text-[rgb(var(--ec-page-text))]'
|
|
511
|
+
: 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
512
|
+
}`}
|
|
513
|
+
>
|
|
514
|
+
{SCHEMA_TYPE_LABELS[type] || type.charAt(0).toUpperCase() + type.slice(1)}
|
|
515
|
+
</button>
|
|
516
|
+
))}
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
)}
|
|
459
520
|
</div>
|
|
460
521
|
</div>
|
|
461
522
|
)}
|
|
462
523
|
|
|
463
|
-
|
|
464
|
-
<div className="flex-shrink-0 px-2.5 border-b border-[rgb(var(--ec-page-border))]">
|
|
465
|
-
<div className="flex items-center gap-3 overflow-x-auto">
|
|
466
|
-
<button
|
|
467
|
-
onClick={() => {
|
|
468
|
-
clearTypeFilters();
|
|
469
|
-
}}
|
|
470
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
471
|
-
selectedTypes.size === 0
|
|
472
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
473
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
474
|
-
}`}
|
|
475
|
-
>
|
|
476
|
-
All
|
|
477
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
478
|
-
{stats.total}
|
|
479
|
-
</span>
|
|
480
|
-
</button>
|
|
481
|
-
{stats.events > 0 && (
|
|
482
|
-
<button
|
|
483
|
-
onClick={() => toggleType('events')}
|
|
484
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
485
|
-
selectedTypes.has('events')
|
|
486
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
487
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
488
|
-
}`}
|
|
489
|
-
>
|
|
490
|
-
<BoltIcon className="h-3 w-3 text-orange-400" />
|
|
491
|
-
Events
|
|
492
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
493
|
-
{stats.events}
|
|
494
|
-
</span>
|
|
495
|
-
</button>
|
|
496
|
-
)}
|
|
497
|
-
{stats.commands > 0 && (
|
|
498
|
-
<button
|
|
499
|
-
onClick={() => toggleType('commands')}
|
|
500
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
501
|
-
selectedTypes.has('commands')
|
|
502
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
503
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
504
|
-
}`}
|
|
505
|
-
>
|
|
506
|
-
<ChatBubbleLeftIcon className="h-3 w-3 text-blue-400" />
|
|
507
|
-
Commands
|
|
508
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
509
|
-
{stats.commands}
|
|
510
|
-
</span>
|
|
511
|
-
</button>
|
|
512
|
-
)}
|
|
513
|
-
{stats.queries > 0 && (
|
|
514
|
-
<button
|
|
515
|
-
onClick={() => toggleType('queries')}
|
|
516
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
517
|
-
selectedTypes.has('queries')
|
|
518
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
519
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
520
|
-
}`}
|
|
521
|
-
>
|
|
522
|
-
<MagnifyingGlassSolidIcon className="h-3 w-3 text-green-400" />
|
|
523
|
-
Queries
|
|
524
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
525
|
-
{stats.queries}
|
|
526
|
-
</span>
|
|
527
|
-
</button>
|
|
528
|
-
)}
|
|
529
|
-
{stats.specifications > 0 && (
|
|
530
|
-
<button
|
|
531
|
-
onClick={() => toggleType('specifications')}
|
|
532
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
533
|
-
selectedTypes.has('specifications')
|
|
534
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
535
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
536
|
-
}`}
|
|
537
|
-
>
|
|
538
|
-
<CodeBracketIcon className="h-3 w-3 text-[rgb(var(--ec-accent)/0.7)]" />
|
|
539
|
-
Specs
|
|
540
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
541
|
-
{stats.specifications}
|
|
542
|
-
</span>
|
|
543
|
-
</button>
|
|
544
|
-
)}
|
|
545
|
-
{stats.dataContracts > 0 && (
|
|
546
|
-
<button
|
|
547
|
-
onClick={() => toggleType('data-contracts')}
|
|
548
|
-
className={`inline-flex items-center gap-1.5 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${
|
|
549
|
-
selectedTypes.has('data-contracts')
|
|
550
|
-
? 'border-[rgb(var(--ec-accent))] text-[rgb(var(--ec-page-text))]'
|
|
551
|
-
: 'border-transparent text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
552
|
-
}`}
|
|
553
|
-
>
|
|
554
|
-
<DocumentCheckIcon className="h-3 w-3 text-purple-400" />
|
|
555
|
-
Contracts
|
|
556
|
-
<span className="tabular-nums text-[11px] text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 rounded-md">
|
|
557
|
-
{stats.dataContracts}
|
|
558
|
-
</span>
|
|
559
|
-
</button>
|
|
560
|
-
)}
|
|
561
|
-
</div>
|
|
562
|
-
</div>
|
|
563
|
-
|
|
564
|
-
{/* Schema List */}
|
|
565
|
-
<div className="flex-1 overflow-y-auto">
|
|
524
|
+
<div className="flex-1 overflow-y-auto px-3 py-3">
|
|
566
525
|
{paginatedMessages.length > 0 ? (
|
|
567
|
-
<div className="
|
|
526
|
+
<div className="space-y-3">
|
|
568
527
|
{paginatedMessages.map((message) => {
|
|
569
528
|
const groupKey = getGroupKey(message);
|
|
570
529
|
const isSelected = selectedGroupKey === groupKey;
|
|
571
|
-
|
|
572
530
|
const versions = messagesByIdAndVersions.get(groupKey) || [message];
|
|
573
531
|
|
|
574
532
|
return (
|
|
@@ -588,12 +546,12 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
588
546
|
})}
|
|
589
547
|
</div>
|
|
590
548
|
) : (
|
|
591
|
-
<div className="flex flex-col items-center justify-center
|
|
592
|
-
<div className="flex items-center justify-center
|
|
549
|
+
<div className="flex h-full flex-col items-center justify-center rounded-[1.5rem] border border-dashed border-[rgb(var(--ec-page-border))] p-8 text-center">
|
|
550
|
+
<div className="mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-[rgb(var(--ec-content-hover))]">
|
|
593
551
|
<MagnifyingGlassIcon className="h-5 w-5 text-[rgb(var(--ec-icon-color))]" />
|
|
594
552
|
</div>
|
|
595
|
-
<h3 className="text-sm font-semibold text-[rgb(var(--ec-page-text))]
|
|
596
|
-
<p className="text-sm text-[rgb(var(--ec-page-text-muted))]
|
|
553
|
+
<h3 className="mb-1 text-sm font-semibold text-[rgb(var(--ec-page-text))]">No schemas found</h3>
|
|
554
|
+
<p className="mb-4 max-w-[220px] text-sm leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
597
555
|
{searchQuery ? `No results for "${searchQuery}"` : 'Try adjusting your filters'}
|
|
598
556
|
</p>
|
|
599
557
|
{hasActiveFilters && (
|
|
@@ -612,12 +570,13 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
612
570
|
)}
|
|
613
571
|
</div>
|
|
614
572
|
|
|
615
|
-
{/* Pagination */}
|
|
616
573
|
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={setCurrentPage} />
|
|
617
574
|
</div>
|
|
618
575
|
|
|
619
|
-
|
|
620
|
-
|
|
576
|
+
<div
|
|
577
|
+
className="flex-1 min-h-0 min-w-0 overflow-hidden bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))]"
|
|
578
|
+
style={{ marginLeft: 'var(--ec-schema-sidebar-width, 360px)' }}
|
|
579
|
+
>
|
|
621
580
|
{displayMessage ? (
|
|
622
581
|
<SchemaDetailsPanel
|
|
623
582
|
message={displayMessage}
|
|
@@ -627,13 +586,13 @@ export default function SchemaExplorer({ schemas, apiAccessEnabled = false }: Sc
|
|
|
627
586
|
apiAccessEnabled={apiAccessEnabled}
|
|
628
587
|
/>
|
|
629
588
|
) : (
|
|
630
|
-
<div className="h-full
|
|
631
|
-
<div className="
|
|
632
|
-
<div className="
|
|
589
|
+
<div className="flex h-full items-center justify-center">
|
|
590
|
+
<div className="max-w-xs text-center">
|
|
591
|
+
<div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-[rgb(var(--ec-content-hover))]">
|
|
633
592
|
<DocumentTextIcon className="h-7 w-7 text-[rgb(var(--ec-icon-color))]" />
|
|
634
593
|
</div>
|
|
635
|
-
<h3 className="text-base font-semibold text-[rgb(var(--ec-page-text))]
|
|
636
|
-
<p className="text-sm text-[rgb(var(--ec-page-text-muted))]
|
|
594
|
+
<h3 className="mb-1 text-base font-semibold text-[rgb(var(--ec-page-text))]">Select a schema</h3>
|
|
595
|
+
<p className="text-sm leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
637
596
|
Choose a schema from the list to view details, compare versions, and access raw code
|
|
638
597
|
</p>
|
|
639
598
|
</div>
|