@eventcatalog/core 2.47.1 → 2.48.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/catalog-to-astro-content-directory.cjs +16 -1
- package/dist/catalog-to-astro-content-directory.js +2 -2
- package/dist/{chunk-SFA7F3CQ.js → chunk-IZMM7ZGY.js} +8 -1
- package/dist/{chunk-EXAALOQA.js → chunk-LDBRNJIL.js} +9 -1
- package/dist/{chunk-QWDFTW7H.js → chunk-M35UFAGG.js} +1 -1
- package/dist/{chunk-WWYOMQLW.js → chunk-WAVFA46U.js} +1 -1
- package/dist/{chunk-DCLTVJDP.js → chunk-XE6PFSH5.js} +2 -2
- package/dist/{chunk-YJYT2E6S.js → chunk-ZI5ZP7I2.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +54 -40
- package/dist/eventcatalog.js +6 -6
- package/dist/map-catalog-to-astro.cjs +9 -1
- package/dist/map-catalog-to-astro.js +1 -1
- package/dist/watcher.cjs +14 -17
- package/dist/watcher.js +2 -3
- package/eventcatalog/src/components/SideNav/ListViewSideBar/components/MessageList.tsx +1 -0
- package/eventcatalog/src/components/SideNav/ListViewSideBar/components/SpecificationList.tsx +2 -0
- package/eventcatalog/src/components/SideNav/ListViewSideBar/index.tsx +310 -106
- package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +86 -7
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +10 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +0 -2
- package/eventcatalog/tsconfig.json +1 -0
- package/package.json +1 -1
|
@@ -54,6 +54,7 @@ const MessageList: React.FC<MessageListProps> = ({ messages, decodedCurrentPath,
|
|
|
54
54
|
<li key={message.id} data-active={decodedCurrentPath === message.href}>
|
|
55
55
|
<a
|
|
56
56
|
href={message.href}
|
|
57
|
+
data-active={decodedCurrentPath === message.href}
|
|
57
58
|
className={`flex items-center justify-between px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
58
59
|
decodedCurrentPath.includes(message.href) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
59
60
|
}`}
|
package/eventcatalog/src/components/SideNav/ListViewSideBar/components/SpecificationList.tsx
CHANGED
|
@@ -26,6 +26,7 @@ const SpecificationList: React.FC<SpecificationListProps> = ({ specifications, i
|
|
|
26
26
|
<a
|
|
27
27
|
key={`${spec.name}-asyncapi`}
|
|
28
28
|
href={buildUrl(`/docs/services/${id}/${version}/asyncapi/${spec.filenameWithoutExtension}`)}
|
|
29
|
+
data-active={window.location.href.includes(`docs/services/${id}/${version}/asyncapi`)}
|
|
29
30
|
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md justify-between ${
|
|
30
31
|
window.location.href.includes(`docs/services/${id}/${version}/asyncapi`) ? 'bg-purple-100' : 'hover:bg-purple-100'
|
|
31
32
|
}`}
|
|
@@ -42,6 +43,7 @@ const SpecificationList: React.FC<SpecificationListProps> = ({ specifications, i
|
|
|
42
43
|
<a
|
|
43
44
|
key={`${spec.name}-openapi`}
|
|
44
45
|
href={buildUrl(`/docs/services/${id}/${version}/spec/${spec.filenameWithoutExtension}`)}
|
|
46
|
+
data-active={window.location.href.includes(`docs/services/${id}/${version}/spec/${spec.filenameWithoutExtension}`)}
|
|
45
47
|
className={`items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md flex justify-between ${
|
|
46
48
|
window.location.href.includes(`docs/services/${id}/${version}/spec/${spec.filenameWithoutExtension}`)
|
|
47
49
|
? 'bg-purple-100'
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
|
|
2
|
-
import { ChevronDownIcon } from '@heroicons/react/24/outline';
|
|
2
|
+
import { ChevronDownIcon, ChevronDoubleDownIcon, ChevronDoubleUpIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
|
3
3
|
import { buildUrl, buildUrlWithParams } from '@utils/url-builder';
|
|
4
4
|
import CollapsibleGroup from './components/CollapsibleGroup';
|
|
5
5
|
import MessageList from './components/MessageList';
|
|
6
6
|
import SpecificationsList from './components/SpecificationList';
|
|
7
7
|
import type { MessageItem, ServiceItem, ListViewSideBarProps, DomainItem, FlowItem, Resources } from './types';
|
|
8
|
+
import { PanelLeft } from 'lucide-react';
|
|
8
9
|
const STORAGE_KEY = 'EventCatalog:catalogSidebarCollapsedGroups';
|
|
9
10
|
const DEBOUNCE_DELAY = 300; // 300ms debounce delay
|
|
10
11
|
|
|
@@ -98,6 +99,7 @@ const ServiceItem = React.memo(
|
|
|
98
99
|
<div className="space-y-0.5 border-gray-200/80 border-l pl-3 ml-[9px] mt-1">
|
|
99
100
|
<a
|
|
100
101
|
href={`${item.href}`}
|
|
102
|
+
data-active={decodedCurrentPath === item.href}
|
|
101
103
|
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
102
104
|
decodedCurrentPath === item.href ? 'bg-purple-100' : 'hover:bg-purple-100'
|
|
103
105
|
}`}
|
|
@@ -110,6 +112,7 @@ const ServiceItem = React.memo(
|
|
|
110
112
|
serviceName: item.name,
|
|
111
113
|
serviceId: item.id,
|
|
112
114
|
})}
|
|
115
|
+
data-active={window.location.href.includes(`serviceId=${item.id}`)}
|
|
113
116
|
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
114
117
|
window.location.href.includes(`serviceId=${item.id}`) ? 'bg-purple-100' : 'hover:bg-purple-100'
|
|
115
118
|
}`}
|
|
@@ -204,6 +207,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
204
207
|
const [searchTerm, setSearchTerm] = useState('');
|
|
205
208
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
|
|
206
209
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
210
|
+
const [isExpanded, setIsExpanded] = useState(true);
|
|
207
211
|
const [collapsedGroups, setCollapsedGroups] = useState<{ [key: string]: boolean }>(() => {
|
|
208
212
|
if (typeof window !== 'undefined') {
|
|
209
213
|
const saved = window.localStorage.getItem(STORAGE_KEY);
|
|
@@ -241,9 +245,55 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
241
245
|
);
|
|
242
246
|
};
|
|
243
247
|
|
|
248
|
+
// Enhanced domain filtering that considers parent-subdomain relationships
|
|
249
|
+
const filterDomains = (domains: any[]) => {
|
|
250
|
+
const filteredDomains: any[] = [];
|
|
251
|
+
|
|
252
|
+
domains.forEach((domain: any) => {
|
|
253
|
+
const domainMatches = filterItem(domain);
|
|
254
|
+
|
|
255
|
+
// Check if this domain is a subdomain of another domain
|
|
256
|
+
const isSubdomain = domains.some((parentDomain: any) => {
|
|
257
|
+
const subdomains = parentDomain.domains || [];
|
|
258
|
+
return subdomains.some((subdomain: any) => subdomain.data.id === domain.id);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// If this is a parent domain, check if any of its subdomains match
|
|
262
|
+
let hasMatchingSubdomains = false;
|
|
263
|
+
if (!isSubdomain) {
|
|
264
|
+
const subdomains = domain.domains || [];
|
|
265
|
+
hasMatchingSubdomains = domains.some((potentialSubdomain: any) =>
|
|
266
|
+
subdomains.some((subdomain: any) => subdomain.data.id === potentialSubdomain.id && filterItem(potentialSubdomain))
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Include domain if:
|
|
271
|
+
// 1. The domain itself matches the search
|
|
272
|
+
// 2. It's a parent domain and has matching subdomains
|
|
273
|
+
// 3. It's a subdomain and matches the search
|
|
274
|
+
if (domainMatches || hasMatchingSubdomains || (isSubdomain && domainMatches)) {
|
|
275
|
+
filteredDomains.push(domain);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// If this is a subdomain that matches, also include its parent domain
|
|
279
|
+
if (isSubdomain && domainMatches) {
|
|
280
|
+
const parentDomain = domains.find((parentDomain: any) => {
|
|
281
|
+
const subdomains = parentDomain.domains || [];
|
|
282
|
+
return subdomains.some((subdomain: any) => subdomain.data.id === domain.id);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
if (parentDomain && !filteredDomains.some((d: any) => d.id === parentDomain.id)) {
|
|
286
|
+
filteredDomains.push(parentDomain);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
return filteredDomains;
|
|
292
|
+
};
|
|
293
|
+
|
|
244
294
|
return {
|
|
245
295
|
'context-map': data['context-map']?.filter(filterItem) || [],
|
|
246
|
-
domains: data.domains
|
|
296
|
+
domains: data.domains ? filterDomains(data.domains) : [],
|
|
247
297
|
services:
|
|
248
298
|
data.services
|
|
249
299
|
?.map((service: ServiceItem) => ({
|
|
@@ -295,7 +345,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
295
345
|
const activeElement = document.querySelector('[data-active="true"]');
|
|
296
346
|
if (activeElement) {
|
|
297
347
|
// Add y offset to the scroll position
|
|
298
|
-
activeElement.scrollIntoView({ behavior: '
|
|
348
|
+
activeElement.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
299
349
|
}
|
|
300
350
|
}, []);
|
|
301
351
|
|
|
@@ -310,6 +360,65 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
310
360
|
setSearchTerm(e.target.value);
|
|
311
361
|
}, []);
|
|
312
362
|
|
|
363
|
+
const collapseAll = useCallback(() => {
|
|
364
|
+
const newCollapsedState: { [key: string]: boolean } = {};
|
|
365
|
+
|
|
366
|
+
// Collapse all domains
|
|
367
|
+
filteredData.domains?.forEach((domain: any) => {
|
|
368
|
+
newCollapsedState[domain.href] = true;
|
|
369
|
+
newCollapsedState[`${domain.href}-entities`] = true;
|
|
370
|
+
newCollapsedState[`${domain.href}-subdomains`] = true;
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Collapse all services
|
|
374
|
+
filteredData.services?.forEach((service: any) => {
|
|
375
|
+
newCollapsedState[service.href] = true;
|
|
376
|
+
newCollapsedState[`${service.href}-specifications`] = true;
|
|
377
|
+
newCollapsedState[`${service.href}-receives`] = true;
|
|
378
|
+
newCollapsedState[`${service.href}-sends`] = true;
|
|
379
|
+
newCollapsedState[`${service.href}-entities`] = true;
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
setCollapsedGroups(newCollapsedState);
|
|
383
|
+
setIsExpanded(false);
|
|
384
|
+
}, [filteredData]);
|
|
385
|
+
|
|
386
|
+
const expandAll = useCallback(() => {
|
|
387
|
+
const newCollapsedState: { [key: string]: boolean } = {};
|
|
388
|
+
|
|
389
|
+
// Expand all domains
|
|
390
|
+
filteredData.domains?.forEach((domain: any) => {
|
|
391
|
+
newCollapsedState[domain.href] = false;
|
|
392
|
+
newCollapsedState[`${domain.href}-entities`] = false;
|
|
393
|
+
newCollapsedState[`${domain.href}-subdomains`] = false;
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Expand all services
|
|
397
|
+
filteredData.services?.forEach((service: any) => {
|
|
398
|
+
newCollapsedState[service.href] = false;
|
|
399
|
+
newCollapsedState[`${service.href}-specifications`] = false;
|
|
400
|
+
newCollapsedState[`${service.href}-receives`] = false;
|
|
401
|
+
newCollapsedState[`${service.href}-sends`] = false;
|
|
402
|
+
newCollapsedState[`${service.href}-entities`] = false;
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
setCollapsedGroups(newCollapsedState);
|
|
406
|
+
setIsExpanded(true);
|
|
407
|
+
}, [filteredData]);
|
|
408
|
+
|
|
409
|
+
const toggleExpandCollapse = useCallback(() => {
|
|
410
|
+
if (isExpanded) {
|
|
411
|
+
collapseAll();
|
|
412
|
+
} else {
|
|
413
|
+
expandAll();
|
|
414
|
+
}
|
|
415
|
+
}, [isExpanded, collapseAll, expandAll]);
|
|
416
|
+
|
|
417
|
+
const hideSidebar = useCallback(() => {
|
|
418
|
+
// Dispatch custom event that the Astro layout will listen for
|
|
419
|
+
window.dispatchEvent(new CustomEvent('sidebarToggle', { detail: { action: 'hide' } }));
|
|
420
|
+
}, []);
|
|
421
|
+
|
|
313
422
|
const isDomainSubDomain = useMemo(() => {
|
|
314
423
|
return (domain: any) => {
|
|
315
424
|
const domains = data.domains || [];
|
|
@@ -320,6 +429,128 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
320
429
|
};
|
|
321
430
|
}, [data.domains]);
|
|
322
431
|
|
|
432
|
+
// Helper function to get parent domains (domains that are not subdomains)
|
|
433
|
+
const getParentDomains = useMemo(() => {
|
|
434
|
+
return (domains: any[]) => {
|
|
435
|
+
return domains.filter((domain: any) => !isDomainSubDomain(domain));
|
|
436
|
+
};
|
|
437
|
+
}, [isDomainSubDomain]);
|
|
438
|
+
|
|
439
|
+
// Helper function to get subdomains for a specific parent domain
|
|
440
|
+
const getSubdomainsForParent = useMemo(() => {
|
|
441
|
+
return (parentDomain: any, allDomains: any[]) => {
|
|
442
|
+
const subdomains = parentDomain.domains || [];
|
|
443
|
+
return allDomains.filter((domain: any) => subdomains.some((subdomain: any) => subdomain.data.id === domain.id));
|
|
444
|
+
};
|
|
445
|
+
}, []);
|
|
446
|
+
|
|
447
|
+
// Component to render a single domain item
|
|
448
|
+
const DomainItem = React.memo(
|
|
449
|
+
({ item, isSubdomain = false, nestingLevel = 0 }: { item: any; isSubdomain?: boolean; nestingLevel?: number }) => {
|
|
450
|
+
const marginLeft = nestingLevel > 0 ? `ml-${nestingLevel * 4}` : '';
|
|
451
|
+
|
|
452
|
+
return (
|
|
453
|
+
<div className={`flex items-center ${marginLeft}`}>
|
|
454
|
+
<button
|
|
455
|
+
onClick={(e) => {
|
|
456
|
+
e.stopPropagation();
|
|
457
|
+
toggleGroupCollapse(item.href);
|
|
458
|
+
}}
|
|
459
|
+
className="p-1 hover:bg-gray-100 rounded-md"
|
|
460
|
+
>
|
|
461
|
+
<div className={`transition-transform duration-150 ${collapsedGroups[item.href] ? '' : 'rotate-180'}`}>
|
|
462
|
+
<ChevronDownIcon className="h-3 w-3 text-gray-500" />
|
|
463
|
+
</div>
|
|
464
|
+
</button>
|
|
465
|
+
<button
|
|
466
|
+
onClick={(e) => {
|
|
467
|
+
e.stopPropagation();
|
|
468
|
+
toggleGroupCollapse(item.href);
|
|
469
|
+
}}
|
|
470
|
+
className={`flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
|
|
471
|
+
decodedCurrentPath === item.href ? 'bg-purple-100' : 'hover:bg-purple-100'
|
|
472
|
+
}`}
|
|
473
|
+
>
|
|
474
|
+
<span className="truncate">
|
|
475
|
+
<HighlightedText text={item.label} searchTerm={debouncedSearchTerm} />
|
|
476
|
+
</span>
|
|
477
|
+
<span className="text-yellow-600 ml-2 text-[10px] font-medium bg-yellow-50 px-2 py-0.5 rounded">
|
|
478
|
+
{isSubdomain ? 'SUBDOMAIN' : 'DOMAIN'}
|
|
479
|
+
</span>
|
|
480
|
+
</button>
|
|
481
|
+
</div>
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
// Component to render domain content (Overview, Architecture, etc.)
|
|
487
|
+
const DomainContent = React.memo(({ item, nestingLevel = 0 }: { item: any; nestingLevel?: number }) => {
|
|
488
|
+
const marginLeft = nestingLevel > 0 ? `ml-${nestingLevel * 4}` : '';
|
|
489
|
+
|
|
490
|
+
return (
|
|
491
|
+
<div
|
|
492
|
+
className={`overflow-hidden transition-[height] duration-150 ease-out ${collapsedGroups[item.href] ? 'h-0' : 'h-auto'}`}
|
|
493
|
+
>
|
|
494
|
+
<div className={`space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1 ${marginLeft}`}>
|
|
495
|
+
<a
|
|
496
|
+
href={`${item.href}`}
|
|
497
|
+
data-active={decodedCurrentPath === item.href}
|
|
498
|
+
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
499
|
+
decodedCurrentPath === item.href ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
500
|
+
}`}
|
|
501
|
+
>
|
|
502
|
+
<span className="truncate">Overview</span>
|
|
503
|
+
</a>
|
|
504
|
+
{!isVisualizer && (
|
|
505
|
+
<a
|
|
506
|
+
href={buildUrlWithParams('/architecture/docs/services', {
|
|
507
|
+
serviceIds: item.services.map((service: any) => service.data.id).join(','),
|
|
508
|
+
domainId: item.id,
|
|
509
|
+
domainName: item.name,
|
|
510
|
+
})}
|
|
511
|
+
data-active={window.location.href.includes(`domainId=${item.id}`)}
|
|
512
|
+
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
513
|
+
window.location.href.includes(`domainId=${item.id}`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
514
|
+
}`}
|
|
515
|
+
>
|
|
516
|
+
<span className="truncate">Architecture</span>
|
|
517
|
+
</a>
|
|
518
|
+
)}
|
|
519
|
+
{!isVisualizer && (
|
|
520
|
+
<a
|
|
521
|
+
href={buildUrl(`/docs/domains/${item.id}/language`)}
|
|
522
|
+
data-active={decodedCurrentPath.includes(`/docs/domains/${item.id}/language`)}
|
|
523
|
+
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
524
|
+
decodedCurrentPath.includes(`/docs/domains/${item.id}/language`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
525
|
+
}`}
|
|
526
|
+
>
|
|
527
|
+
<span className="truncate">Ubiquitous Language</span>
|
|
528
|
+
</a>
|
|
529
|
+
)}
|
|
530
|
+
{item.entities.length > 0 && !isVisualizer && (
|
|
531
|
+
<CollapsibleGroup
|
|
532
|
+
isCollapsed={collapsedGroups[`${item.href}-entities`]}
|
|
533
|
+
onToggle={() => toggleGroupCollapse(`${item.href}-entities`)}
|
|
534
|
+
title={
|
|
535
|
+
<button
|
|
536
|
+
onClick={(e) => {
|
|
537
|
+
e.stopPropagation();
|
|
538
|
+
toggleGroupCollapse(`${item.href}-entities`);
|
|
539
|
+
}}
|
|
540
|
+
className="truncate underline ml-2 text-xs mb-1 py-1"
|
|
541
|
+
>
|
|
542
|
+
Entities ({item.entities.length})
|
|
543
|
+
</button>
|
|
544
|
+
}
|
|
545
|
+
>
|
|
546
|
+
<MessageList messages={item.entities} decodedCurrentPath={decodedCurrentPath} searchTerm={debouncedSearchTerm} />
|
|
547
|
+
</CollapsibleGroup>
|
|
548
|
+
)}
|
|
549
|
+
</div>
|
|
550
|
+
</div>
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
|
|
323
554
|
if (!isInitialized) return null;
|
|
324
555
|
|
|
325
556
|
const hasNoResults =
|
|
@@ -332,13 +563,35 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
332
563
|
|
|
333
564
|
return (
|
|
334
565
|
<nav ref={navRef} className="space-y-4 text-gray-800 px-3 py-4">
|
|
335
|
-
<
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
566
|
+
<div className="flex gap-2">
|
|
567
|
+
<input
|
|
568
|
+
type="text"
|
|
569
|
+
value={searchTerm}
|
|
570
|
+
onChange={handleSearchChange}
|
|
571
|
+
placeholder="Quick search..."
|
|
572
|
+
className="flex-1 p-2 text-sm rounded-md border border-gray-200 h-[30px]"
|
|
573
|
+
/>
|
|
574
|
+
<div className="flex gap-1">
|
|
575
|
+
<button
|
|
576
|
+
onClick={toggleExpandCollapse}
|
|
577
|
+
title={isExpanded ? 'Collapse All' : 'Expand All'}
|
|
578
|
+
className="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-200 h-[30px] flex items-center justify-center"
|
|
579
|
+
>
|
|
580
|
+
{isExpanded ? (
|
|
581
|
+
<ChevronDoubleUpIcon className="h-4 w-4 text-gray-600" />
|
|
582
|
+
) : (
|
|
583
|
+
<ChevronDoubleDownIcon className="h-4 w-4 text-gray-600" />
|
|
584
|
+
)}
|
|
585
|
+
</button>
|
|
586
|
+
<button
|
|
587
|
+
onClick={hideSidebar}
|
|
588
|
+
title="Hide Sidebar"
|
|
589
|
+
className="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-200 h-[30px] flex items-center justify-center"
|
|
590
|
+
>
|
|
591
|
+
<PanelLeft className="h-4 w-4 text-gray-600" />
|
|
592
|
+
</button>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
342
595
|
<div className="space-y-2 divide-y divide-gray-200/80">
|
|
343
596
|
{hasNoResults ? (
|
|
344
597
|
<NoResultsFound searchTerm={debouncedSearchTerm} />
|
|
@@ -352,6 +605,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
352
605
|
<li key={item.href}>
|
|
353
606
|
<a
|
|
354
607
|
href={item.href}
|
|
608
|
+
data-active={decodedCurrentPath === item.href}
|
|
355
609
|
className={`flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
|
|
356
610
|
decodedCurrentPath === item.href ? 'bg-purple-100 text-purple-900' : 'hover:bg-purple-100'
|
|
357
611
|
}`}
|
|
@@ -372,104 +626,50 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
372
626
|
{filteredData['domains'] && (
|
|
373
627
|
<div className={`${isVisualizer ? 'pt-4 pb-2' : 'p-0'}`}>
|
|
374
628
|
<ul className="space-y-2">
|
|
375
|
-
{filteredData['domains'].map((
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
>
|
|
385
|
-
<div className=
|
|
386
|
-
<ChevronDownIcon className="h-3 w-3 text-gray-500" />
|
|
387
|
-
</div>
|
|
388
|
-
</button>
|
|
389
|
-
<button
|
|
390
|
-
onClick={(e) => {
|
|
391
|
-
e.stopPropagation();
|
|
392
|
-
toggleGroupCollapse(item.href);
|
|
393
|
-
}}
|
|
394
|
-
className={`flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
|
|
395
|
-
decodedCurrentPath === item.href
|
|
396
|
-
}`}
|
|
397
|
-
>
|
|
398
|
-
<span className="truncate">
|
|
399
|
-
<HighlightedText text={item.label} searchTerm={debouncedSearchTerm} />
|
|
400
|
-
</span>
|
|
401
|
-
<span className="text-yellow-600 ml-2 text-[10px] font-medium bg-yellow-50 px-2 py-0.5 rounded">
|
|
402
|
-
{isDomainSubDomain(item) ? 'SUBDOMAIN' : 'DOMAIN'}
|
|
403
|
-
</span>
|
|
404
|
-
</button>
|
|
405
|
-
</div>
|
|
406
|
-
<div
|
|
407
|
-
className={`overflow-hidden transition-[height] duration-150 ease-out ${
|
|
408
|
-
collapsedGroups[item.href] ? 'h-0' : 'h-auto'
|
|
409
|
-
}`}
|
|
410
|
-
>
|
|
411
|
-
<div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
|
|
412
|
-
<a
|
|
413
|
-
href={`${item.href}`}
|
|
414
|
-
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
415
|
-
decodedCurrentPath === item.href ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
416
|
-
}`}
|
|
417
|
-
>
|
|
418
|
-
<span className="truncate">Overview</span>
|
|
419
|
-
</a>
|
|
420
|
-
{!isVisualizer && (
|
|
421
|
-
<a
|
|
422
|
-
href={buildUrlWithParams('/architecture/docs/services', {
|
|
423
|
-
serviceIds: item.services.map((service: any) => service.data.id).join(','),
|
|
424
|
-
domainId: item.id,
|
|
425
|
-
domainName: item.name,
|
|
426
|
-
})}
|
|
427
|
-
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
428
|
-
window.location.href.includes(`domainId=${item.id}`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
|
|
429
|
-
}`}
|
|
430
|
-
>
|
|
431
|
-
<span className="truncate">Architecture</span>
|
|
432
|
-
</a>
|
|
433
|
-
)}
|
|
434
|
-
{!isVisualizer && (
|
|
435
|
-
<a
|
|
436
|
-
href={buildUrl(`/docs/domains/${item.id}/language`)}
|
|
437
|
-
className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
|
|
438
|
-
decodedCurrentPath.includes(`/docs/domains/${item.id}/language`)
|
|
439
|
-
? 'bg-purple-100 '
|
|
440
|
-
: 'hover:bg-purple-100'
|
|
441
|
-
}`}
|
|
442
|
-
>
|
|
443
|
-
<span className="truncate">Ubiquitous Language</span>
|
|
444
|
-
</a>
|
|
445
|
-
)}
|
|
446
|
-
{item.entities.length > 0 && !isVisualizer && (
|
|
629
|
+
{getParentDomains(filteredData['domains'] || []).map((parentDomain: any) => {
|
|
630
|
+
const subdomains = getSubdomainsForParent(parentDomain, filteredData['domains'] || []);
|
|
631
|
+
|
|
632
|
+
return (
|
|
633
|
+
<li key={parentDomain.href} className="space-y-0" data-active={decodedCurrentPath === parentDomain.href}>
|
|
634
|
+
<DomainItem item={parentDomain} isSubdomain={false} />
|
|
635
|
+
<DomainContent item={parentDomain} />
|
|
636
|
+
|
|
637
|
+
{/* Render nested subdomains */}
|
|
638
|
+
{subdomains.length > 0 && !collapsedGroups[parentDomain.href] && (
|
|
639
|
+
<div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-2">
|
|
447
640
|
<CollapsibleGroup
|
|
448
|
-
isCollapsed={collapsedGroups[`${
|
|
449
|
-
onToggle={() => toggleGroupCollapse(`${
|
|
641
|
+
isCollapsed={collapsedGroups[`${parentDomain.href}-subdomains`]}
|
|
642
|
+
onToggle={() => toggleGroupCollapse(`${parentDomain.href}-subdomains`)}
|
|
450
643
|
title={
|
|
451
644
|
<button
|
|
452
645
|
onClick={(e) => {
|
|
453
646
|
e.stopPropagation();
|
|
454
|
-
toggleGroupCollapse(`${
|
|
647
|
+
toggleGroupCollapse(`${parentDomain.href}-subdomains`);
|
|
455
648
|
}}
|
|
456
649
|
className="truncate underline ml-2 text-xs mb-1 py-1"
|
|
457
650
|
>
|
|
458
|
-
|
|
651
|
+
Subdomains ({subdomains.length})
|
|
459
652
|
</button>
|
|
460
653
|
}
|
|
461
654
|
>
|
|
462
|
-
<
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
655
|
+
<div className="space-y-2">
|
|
656
|
+
{subdomains.map((subdomain: any) => (
|
|
657
|
+
<div
|
|
658
|
+
key={subdomain.href}
|
|
659
|
+
className="space-y-0"
|
|
660
|
+
data-active={decodedCurrentPath === subdomain.href}
|
|
661
|
+
>
|
|
662
|
+
<DomainItem item={subdomain} isSubdomain={true} nestingLevel={1} />
|
|
663
|
+
<DomainContent item={subdomain} nestingLevel={1} />
|
|
664
|
+
</div>
|
|
665
|
+
))}
|
|
666
|
+
</div>
|
|
467
667
|
</CollapsibleGroup>
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
</
|
|
471
|
-
|
|
472
|
-
)
|
|
668
|
+
</div>
|
|
669
|
+
)}
|
|
670
|
+
</li>
|
|
671
|
+
);
|
|
672
|
+
})}
|
|
473
673
|
</ul>
|
|
474
674
|
</div>
|
|
475
675
|
)}
|
|
@@ -478,27 +678,30 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
478
678
|
<div className="pt-4 pb-2">
|
|
479
679
|
<ul className="space-y-4">
|
|
480
680
|
{filteredData['services'].map((item: any) => (
|
|
481
|
-
<
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
681
|
+
<li key={item.href} data-active={decodedCurrentPath === item.href}>
|
|
682
|
+
<ServiceItem
|
|
683
|
+
key={item.href}
|
|
684
|
+
item={item}
|
|
685
|
+
decodedCurrentPath={decodedCurrentPath}
|
|
686
|
+
collapsedGroups={collapsedGroups}
|
|
687
|
+
toggleGroupCollapse={toggleGroupCollapse}
|
|
688
|
+
isVisualizer={isVisualizer}
|
|
689
|
+
searchTerm={debouncedSearchTerm}
|
|
690
|
+
/>
|
|
691
|
+
</li>
|
|
490
692
|
))}
|
|
491
693
|
</ul>
|
|
492
694
|
</div>
|
|
493
695
|
)}
|
|
494
696
|
|
|
495
|
-
{filteredData['messagesNotInService'] && (
|
|
697
|
+
{filteredData['messagesNotInService'] && filteredData['messagesNotInService'].length > 0 && (
|
|
496
698
|
<div className="pt-4 pb-2">
|
|
497
699
|
<ul className="space-y-4">
|
|
498
700
|
{filteredData['messagesNotInService'].map((item: any) => (
|
|
499
701
|
<li key={item.href} className="space-y-0" data-active={decodedCurrentPath === item.href}>
|
|
500
702
|
<a
|
|
501
703
|
href={item.href}
|
|
704
|
+
data-active={decodedCurrentPath === item.href}
|
|
502
705
|
className={`flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
|
|
503
706
|
decodedCurrentPath === item.href ? 'bg-purple-100 text-purple-900' : 'hover:bg-purple-100'
|
|
504
707
|
}`}
|
|
@@ -525,6 +728,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
|
|
|
525
728
|
<li key={item.href} className="space-y-0" data-active={decodedCurrentPath === item.href}>
|
|
526
729
|
<a
|
|
527
730
|
href={item.href}
|
|
731
|
+
data-active={decodedCurrentPath === item.href}
|
|
528
732
|
className={`flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
|
|
529
733
|
decodedCurrentPath === item.href ? 'bg-cyan-100 text-cyan-900' : 'hover:bg-purple-100'
|
|
530
734
|
}`}
|