@finos/legend-extension-dsl-data-space 9.2.3 → 9.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/lib/components/DSL_DataSpace_LegendApplicationPlugin.d.ts +2 -1
  2. package/lib/components/DSL_DataSpace_LegendApplicationPlugin.d.ts.map +1 -1
  3. package/lib/components/DSL_DataSpace_LegendApplicationPlugin.js +8 -0
  4. package/lib/components/DSL_DataSpace_LegendApplicationPlugin.js.map +1 -1
  5. package/lib/components/DataSpaceDataAccess.d.ts.map +1 -1
  6. package/lib/components/DataSpaceDataAccess.js +70 -66
  7. package/lib/components/DataSpaceDataAccess.js.map +1 -1
  8. package/lib/components/DataSpaceDiagramViewer.js +1 -1
  9. package/lib/components/DataSpaceDiagramViewer.js.map +1 -1
  10. package/lib/components/DataSpaceModelsDocumentation.d.ts.map +1 -1
  11. package/lib/components/DataSpaceModelsDocumentation.js +337 -34
  12. package/lib/components/DataSpaceModelsDocumentation.js.map +1 -1
  13. package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
  14. package/lib/components/DataSpaceQuickStart.js +33 -12
  15. package/lib/components/DataSpaceQuickStart.js.map +1 -1
  16. package/lib/components/DataSpaceViewer.d.ts.map +1 -1
  17. package/lib/components/DataSpaceViewer.js +1 -1
  18. package/lib/components/DataSpaceViewer.js.map +1 -1
  19. package/lib/components/DataSpaceWiki.d.ts.map +1 -1
  20. package/lib/components/DataSpaceWiki.js +0 -1
  21. package/lib/components/DataSpaceWiki.js.map +1 -1
  22. package/lib/graphManager/action/analytics/DataSpaceAnalysis.d.ts +45 -9
  23. package/lib/graphManager/action/analytics/DataSpaceAnalysis.d.ts.map +1 -1
  24. package/lib/graphManager/action/analytics/DataSpaceAnalysis.js +55 -12
  25. package/lib/graphManager/action/analytics/DataSpaceAnalysis.js.map +1 -1
  26. package/lib/graphManager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.d.ts.map +1 -1
  27. package/lib/graphManager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js +51 -8
  28. package/lib/graphManager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js.map +1 -1
  29. package/lib/graphManager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts +15 -3
  30. package/lib/graphManager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts.map +1 -1
  31. package/lib/graphManager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js +16 -2
  32. package/lib/graphManager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js.map +1 -1
  33. package/lib/index.css +2 -2
  34. package/lib/index.css.map +1 -1
  35. package/lib/package.json +7 -10
  36. package/lib/stores/DataSpaceModelsDocumentationState.d.ts +93 -0
  37. package/lib/stores/DataSpaceModelsDocumentationState.d.ts.map +1 -0
  38. package/lib/stores/DataSpaceModelsDocumentationState.js +396 -0
  39. package/lib/stores/DataSpaceModelsDocumentationState.js.map +1 -0
  40. package/lib/stores/DataSpaceViewerState.d.ts +5 -0
  41. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  42. package/lib/stores/DataSpaceViewerState.js +6 -1
  43. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  44. package/package.json +18 -21
  45. package/src/components/DSL_DataSpace_LegendApplicationPlugin.ts +10 -0
  46. package/src/components/DataSpaceDataAccess.tsx +101 -96
  47. package/src/components/DataSpaceDiagramViewer.tsx +1 -1
  48. package/src/components/DataSpaceModelsDocumentation.tsx +1043 -46
  49. package/src/components/DataSpaceQuickStart.tsx +69 -15
  50. package/src/components/DataSpaceViewer.tsx +2 -4
  51. package/src/components/DataSpaceWiki.tsx +0 -2
  52. package/src/graphManager/action/analytics/DataSpaceAnalysis.ts +71 -19
  53. package/src/graphManager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.ts +97 -29
  54. package/src/graphManager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.ts +22 -3
  55. package/src/stores/DataSpaceModelsDocumentationState.ts +588 -0
  56. package/src/stores/DataSpaceViewerState.ts +14 -0
  57. package/tsconfig.json +1 -1
  58. package/lib/graphManager/action/analytics/HACKY__DataSpaceUsageShowcase.d.ts +0 -57
  59. package/lib/graphManager/action/analytics/HACKY__DataSpaceUsageShowcase.d.ts.map +0 -1
  60. package/lib/graphManager/action/analytics/HACKY__DataSpaceUsageShowcase.js +0 -209
  61. package/lib/graphManager/action/analytics/HACKY__DataSpaceUsageShowcase.js.map +0 -1
  62. package/src/graphManager/action/analytics/HACKY__DataSpaceUsageShowcase.ts +0 -313
@@ -15,17 +15,1029 @@
15
15
  */
16
16
 
17
17
  import { observer } from 'mobx-react-lite';
18
- import { AnchorLinkIcon, SearchIcon } from '@finos/legend-art';
18
+ import {
19
+ AnchorLinkIcon,
20
+ BasePopover,
21
+ ChevronDownIcon,
22
+ ChevronRightIcon,
23
+ ClockIcon,
24
+ CogIcon,
25
+ DropdownMenu,
26
+ FilterIcon,
27
+ InfoCircleIcon,
28
+ MenuContent,
29
+ MenuContentItem,
30
+ MoreVerticalIcon,
31
+ SearchIcon,
32
+ TimesIcon,
33
+ Tooltip,
34
+ clsx,
35
+ type TreeNodeContainerProps,
36
+ TreeView,
37
+ PackageIcon,
38
+ CheckSquareIcon,
39
+ MinusSquareIcon,
40
+ EmptySquareIcon,
41
+ CaretRightIcon,
42
+ CaretLeftIcon,
43
+ } from '@finos/legend-art';
19
44
  import { type DataSpaceViewerState } from '../stores/DataSpaceViewerState.js';
20
- import { AgGridReact } from '@ag-grid-community/react';
21
- import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
22
45
  import { DataSpaceWikiPlaceholder } from './DataSpacePlaceholder.js';
46
+ import {
47
+ DataSpaceAssociationDocumentationEntry,
48
+ DataSpaceBasicDocumentationEntry,
49
+ DataSpaceClassDocumentationEntry,
50
+ DataSpaceEnumerationDocumentationEntry,
51
+ DataSpaceModelDocumentationEntry,
52
+ DataSpacePropertyDocumentationEntry,
53
+ type NormalizedDataSpaceDocumentationEntry,
54
+ } from '../graphManager/action/analytics/DataSpaceAnalysis.js';
55
+ import { debounce, isNonNullable, prettyCONSTName } from '@finos/legend-shared';
56
+ import { useApplicationStore } from '@finos/legend-application';
57
+ import {
58
+ CORE_PURE_PATH,
59
+ ELEMENT_PATH_DELIMITER,
60
+ MILESTONING_STEREOTYPE,
61
+ PROPERTY_ACCESSOR,
62
+ getMultiplicityDescription,
63
+ } from '@finos/legend-graph';
64
+ import { useMemo, useRef } from 'react';
65
+ import {
66
+ type ModelsDocumentationFilterTreeNodeData,
67
+ type DataSpaceViewerModelsDocumentationState,
68
+ ModelsDocumentationFilterTreeTypeNodeData,
69
+ ModelsDocumentationFilterTreeElementNodeData,
70
+ ModelsDocumentationFilterTreePackageNodeData,
71
+ ModelsDocumentationFilterTreeNodeCheckType,
72
+ uncheckFilterTreeNode,
73
+ checkFilterTreeNode,
74
+ uncheckAllFilterTree,
75
+ ModelsDocumentationFilterTreeRootNodeData,
76
+ } from '../stores/DataSpaceModelsDocumentationState.js';
77
+ import {
78
+ DataGrid,
79
+ type DataGridCellRendererParams,
80
+ } from '@finos/legend-lego/data-grid';
81
+ import { FuzzySearchAdvancedConfigMenu } from '@finos/legend-application/components';
82
+
83
+ const getMilestoningLabel = (val: string | undefined): string | undefined => {
84
+ switch (val) {
85
+ case MILESTONING_STEREOTYPE.BITEMPORAL:
86
+ return 'Bi-temporal';
87
+ case MILESTONING_STEREOTYPE.BUSINESS_TEMPORAL:
88
+ return 'Business Temporal';
89
+ case MILESTONING_STEREOTYPE.PROCESSING_TEMPORAL:
90
+ return 'Processing Temporal';
91
+ default:
92
+ return undefined;
93
+ }
94
+ };
95
+
96
+ const ElementInfoTooltip: React.FC<{
97
+ entry: DataSpaceModelDocumentationEntry;
98
+ children: React.ReactElement;
99
+ }> = (props) => {
100
+ const { entry, children } = props;
101
+
102
+ return (
103
+ <Tooltip
104
+ arrow={false}
105
+ placement="bottom-end"
106
+ disableInteractive={true}
107
+ classes={{
108
+ tooltip: 'data-space__viewer__tooltip',
109
+ tooltipPlacementRight: 'data-space__viewer__tooltip--right',
110
+ }}
111
+ TransitionProps={{
112
+ // disable transition
113
+ // NOTE: somehow, this is the only workaround we have, if for example
114
+ // we set `appear = true`, the tooltip will jump out of position
115
+ timeout: 0,
116
+ }}
117
+ title={
118
+ <div className="data-space__viewer__tooltip__content">
119
+ <div className="data-space__viewer__tooltip__item">
120
+ <div className="data-space__viewer__tooltip__item__label">Name</div>
121
+ <div className="data-space__viewer__tooltip__item__value">
122
+ {entry.name}
123
+ </div>
124
+ </div>
125
+ <div className="data-space__viewer__tooltip__item">
126
+ <div className="data-space__viewer__tooltip__item__label">Path</div>
127
+ <div className="data-space__viewer__tooltip__item__value">
128
+ {entry.path}
129
+ </div>
130
+ </div>
131
+ {entry instanceof DataSpaceClassDocumentationEntry &&
132
+ entry.milestoning !== undefined && (
133
+ <div className="data-space__viewer__tooltip__item">
134
+ <div className="data-space__viewer__tooltip__item__label">
135
+ Milestoning
136
+ </div>
137
+ <div className="data-space__viewer__tooltip__item__value">
138
+ {getMilestoningLabel(entry.milestoning)}
139
+ </div>
140
+ </div>
141
+ )}
142
+ </div>
143
+ }
144
+ >
145
+ {children}
146
+ </Tooltip>
147
+ );
148
+ };
149
+
150
+ const PropertyInfoTooltip: React.FC<{
151
+ entry: DataSpacePropertyDocumentationEntry;
152
+ elementEntry: DataSpaceModelDocumentationEntry;
153
+ children: React.ReactElement;
154
+ }> = (props) => {
155
+ const { entry, elementEntry, children } = props;
156
+
157
+ return (
158
+ <Tooltip
159
+ arrow={false}
160
+ placement="bottom-end"
161
+ disableInteractive={true}
162
+ classes={{
163
+ tooltip: 'data-space__viewer__tooltip',
164
+ tooltipPlacementRight: 'data-space__viewer__tooltip--right',
165
+ }}
166
+ TransitionProps={{
167
+ // disable transition
168
+ // NOTE: somehow, this is the only workaround we have, if for example
169
+ // we set `appear = true`, the tooltip will jump out of position
170
+ timeout: 0,
171
+ }}
172
+ title={
173
+ <div className="data-space__viewer__tooltip__content">
174
+ <div className="data-space__viewer__tooltip__item">
175
+ <div className="data-space__viewer__tooltip__item__label">Name</div>
176
+ <div className="data-space__viewer__tooltip__item__value">
177
+ {entry.name}
178
+ </div>
179
+ </div>
180
+ <div className="data-space__viewer__tooltip__item">
181
+ <div className="data-space__viewer__tooltip__item__label">
182
+ Owner
183
+ </div>
184
+ <div className="data-space__viewer__tooltip__item__value">
185
+ {elementEntry.path}
186
+ </div>
187
+ </div>
188
+ {entry.type && (
189
+ <div className="data-space__viewer__tooltip__item">
190
+ <div className="data-space__viewer__tooltip__item__label">
191
+ Type
192
+ </div>
193
+ <div className="data-space__viewer__tooltip__item__value">
194
+ {entry.type}
195
+ </div>
196
+ </div>
197
+ )}
198
+ {entry.multiplicity && (
199
+ <div className="data-space__viewer__tooltip__item">
200
+ <div className="data-space__viewer__tooltip__item__label">
201
+ Multiplicity
202
+ </div>
203
+ <div className="data-space__viewer__tooltip__item__value">
204
+ {getMultiplicityDescription(entry.multiplicity)}
205
+ </div>
206
+ </div>
207
+ )}
208
+ {entry.milestoning && (
209
+ <div className="data-space__viewer__tooltip__item">
210
+ <div className="data-space__viewer__tooltip__item__label">
211
+ Milestoning
212
+ </div>
213
+ <div className="data-space__viewer__tooltip__item__value">
214
+ {getMilestoningLabel(entry.milestoning)}
215
+ </div>
216
+ </div>
217
+ )}
218
+ </div>
219
+ }
220
+ >
221
+ {children}
222
+ </Tooltip>
223
+ );
224
+ };
225
+
226
+ const ElementContentCellRenderer = observer(
227
+ (
228
+ params: DataGridCellRendererParams<NormalizedDataSpaceDocumentationEntry> & {
229
+ dataSpaceViewerState: DataSpaceViewerState;
230
+ },
231
+ ) => {
232
+ const { data, dataSpaceViewerState } = params;
233
+ const applicationStore = useApplicationStore();
234
+ const showHumanizedForm =
235
+ dataSpaceViewerState.modelsDocumentationState.showHumanizedForm;
236
+
237
+ if (!data) {
238
+ return null;
239
+ }
240
+
241
+ const copyPath = (): void => {
242
+ applicationStore.clipboardService
243
+ .copyTextToClipboard(data.elementEntry.path)
244
+ .catch(applicationStore.alertUnhandledError);
245
+ };
246
+ const label = showHumanizedForm
247
+ ? prettyCONSTName(data.elementEntry.name)
248
+ : data.elementEntry.name;
249
+
250
+ if (data.elementEntry instanceof DataSpaceClassDocumentationEntry) {
251
+ return (
252
+ <div
253
+ className="data-space__viewer__models-documentation__grid__cell"
254
+ title={`Class: ${data.elementEntry.path}`}
255
+ >
256
+ <div className="data-space__viewer__models-documentation__grid__cell__label">
257
+ <div className="data-space__viewer__models-documentation__grid__cell__label__icon data-space__viewer__models-documentation__grid__cell__label__icon--class">
258
+ C
259
+ </div>
260
+ <div className="data-space__viewer__models-documentation__grid__cell__label__text">
261
+ {label}
262
+ </div>
263
+ {data.elementEntry.milestoning && (
264
+ <div
265
+ className="data-space__viewer__models-documentation__grid__cell__label__milestoning-badge"
266
+ title={`Milestoning: ${getMilestoningLabel(
267
+ data.elementEntry.milestoning,
268
+ )}`}
269
+ >
270
+ <ClockIcon />
271
+ </div>
272
+ )}
273
+ </div>
274
+ <div className="data-space__viewer__models-documentation__grid__cell__actions">
275
+ <ElementInfoTooltip entry={data.elementEntry}>
276
+ <div className="data-space__viewer__models-documentation__grid__cell__action">
277
+ <InfoCircleIcon className="data-space__viewer__models-documentation__grid__cell__action__info" />
278
+ </div>
279
+ </ElementInfoTooltip>
280
+ <DropdownMenu
281
+ className="data-space__viewer__models-documentation__grid__cell__action"
282
+ menuProps={{
283
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
284
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
285
+ elevation: 7,
286
+ }}
287
+ content={
288
+ <MenuContent>
289
+ <MenuContentItem onClick={copyPath}>
290
+ Copy Path
291
+ </MenuContentItem>
292
+ <MenuContentItem disabled={true}>
293
+ Preview Data
294
+ </MenuContentItem>
295
+ </MenuContent>
296
+ }
297
+ >
298
+ <MoreVerticalIcon />
299
+ </DropdownMenu>
300
+ </div>
301
+ </div>
302
+ );
303
+ } else if (
304
+ data.elementEntry instanceof DataSpaceEnumerationDocumentationEntry
305
+ ) {
306
+ return (
307
+ <div
308
+ className="data-space__viewer__models-documentation__grid__cell"
309
+ title={`Enumeration: ${data.elementEntry.path}`}
310
+ >
311
+ <div className="data-space__viewer__models-documentation__grid__cell__label">
312
+ <div className="data-space__viewer__models-documentation__grid__cell__label__icon data-space__viewer__models-documentation__grid__cell__label__icon--enumeration">
313
+ E
314
+ </div>
315
+ <div className="data-space__viewer__models-documentation__grid__cell__label__text">
316
+ {label}
317
+ </div>
318
+ </div>
319
+ <div className="data-space__viewer__models-documentation__grid__cell__actions">
320
+ <ElementInfoTooltip entry={data.elementEntry}>
321
+ <div className="data-space__viewer__models-documentation__grid__cell__action">
322
+ <InfoCircleIcon className="data-space__viewer__models-documentation__grid__cell__action__info" />
323
+ </div>
324
+ </ElementInfoTooltip>
325
+ <DropdownMenu
326
+ className="data-space__viewer__models-documentation__grid__cell__action"
327
+ menuProps={{
328
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
329
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
330
+ elevation: 7,
331
+ }}
332
+ content={
333
+ <MenuContent>
334
+ <MenuContentItem onClick={copyPath}>
335
+ Copy Path
336
+ </MenuContentItem>
337
+ </MenuContent>
338
+ }
339
+ >
340
+ <MoreVerticalIcon />
341
+ </DropdownMenu>
342
+ </div>
343
+ </div>
344
+ );
345
+ } else if (
346
+ data.elementEntry instanceof DataSpaceAssociationDocumentationEntry
347
+ ) {
348
+ return (
349
+ <div
350
+ className="data-space__viewer__models-documentation__grid__cell"
351
+ title={`Association: ${data.elementEntry.path}`}
352
+ >
353
+ <div className="data-space__viewer__models-documentation__grid__cell__label">
354
+ <div className="data-space__viewer__models-documentation__grid__cell__label__icon data-space__viewer__models-documentation__grid__cell__label__icon--association">
355
+ A
356
+ </div>
357
+ <div className="data-space__viewer__models-documentation__grid__cell__label__text">
358
+ {label}
359
+ </div>
360
+ </div>
361
+ <div className="data-space__viewer__models-documentation__grid__cell__actions">
362
+ <ElementInfoTooltip entry={data.elementEntry}>
363
+ <div className="data-space__viewer__models-documentation__grid__cell__action">
364
+ <InfoCircleIcon className="data-space__viewer__models-documentation__grid__cell__action__info" />
365
+ </div>
366
+ </ElementInfoTooltip>
367
+ <DropdownMenu
368
+ className="data-space__viewer__models-documentation__grid__cell__action"
369
+ menuProps={{
370
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
371
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
372
+ elevation: 7,
373
+ }}
374
+ content={
375
+ <MenuContent>
376
+ <MenuContentItem onClick={copyPath}>
377
+ Copy Path
378
+ </MenuContentItem>
379
+ </MenuContent>
380
+ }
381
+ >
382
+ <MoreVerticalIcon />
383
+ </DropdownMenu>
384
+ </div>
385
+ </div>
386
+ );
387
+ }
388
+ return null;
389
+ },
390
+ );
391
+
392
+ const SubElementDocContentCellRenderer = observer(
393
+ (
394
+ params: DataGridCellRendererParams<NormalizedDataSpaceDocumentationEntry> & {
395
+ dataSpaceViewerState: DataSpaceViewerState;
396
+ },
397
+ ) => {
398
+ const { data, dataSpaceViewerState } = params;
399
+ const applicationStore = useApplicationStore();
400
+ const showHumanizedForm =
401
+ dataSpaceViewerState.modelsDocumentationState.showHumanizedForm;
402
+
403
+ if (!data) {
404
+ return null;
405
+ }
406
+
407
+ const label = showHumanizedForm ? prettyCONSTName(data.text) : data.text;
408
+
409
+ if (data.entry instanceof DataSpaceModelDocumentationEntry) {
410
+ return null;
411
+ } else if (data.entry instanceof DataSpacePropertyDocumentationEntry) {
412
+ return (
413
+ <div
414
+ className="data-space__viewer__models-documentation__grid__cell"
415
+ title={`Property: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`}
416
+ >
417
+ <div className="data-space__viewer__models-documentation__grid__cell__label">
418
+ <div className="data-space__viewer__models-documentation__grid__cell__label__icon data-space__viewer__models-documentation__grid__cell__label__icon--property">
419
+ P
420
+ </div>
421
+ <div className="data-space__viewer__models-documentation__grid__cell__label__text">
422
+ {label}
423
+ </div>
424
+ {data.entry.milestoning && (
425
+ <div
426
+ className="data-space__viewer__models-documentation__grid__cell__label__milestoning-badge"
427
+ title={`Milestoning: ${getMilestoningLabel(
428
+ data.entry.milestoning,
429
+ )}`}
430
+ >
431
+ <ClockIcon />
432
+ </div>
433
+ )}
434
+ </div>
435
+ <div className="data-space__viewer__models-documentation__grid__cell__actions">
436
+ <PropertyInfoTooltip
437
+ entry={data.entry}
438
+ elementEntry={data.elementEntry}
439
+ >
440
+ <div className="data-space__viewer__models-documentation__grid__cell__action">
441
+ <InfoCircleIcon className="data-space__viewer__models-documentation__grid__cell__action__info" />
442
+ </div>
443
+ </PropertyInfoTooltip>
444
+ <DropdownMenu
445
+ className="data-space__viewer__models-documentation__grid__cell__action"
446
+ menuProps={{
447
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
448
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
449
+ elevation: 7,
450
+ }}
451
+ content={
452
+ <MenuContent>
453
+ <MenuContentItem disabled={true}>
454
+ Preview Data
455
+ </MenuContentItem>
456
+ </MenuContent>
457
+ }
458
+ >
459
+ <MoreVerticalIcon />
460
+ </DropdownMenu>
461
+ </div>
462
+ </div>
463
+ );
464
+ } else if (data.entry instanceof DataSpaceBasicDocumentationEntry) {
465
+ const copyValue = (): void => {
466
+ applicationStore.clipboardService
467
+ .copyTextToClipboard(
468
+ data.elementEntry.path + PROPERTY_ACCESSOR + data.entry.name,
469
+ )
470
+ .catch(applicationStore.alertUnhandledError);
471
+ };
472
+ return (
473
+ <div
474
+ className="data-space__viewer__models-documentation__grid__cell"
475
+ title={`Enum: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`}
476
+ >
477
+ <div className="data-space__viewer__models-documentation__grid__cell__label">
478
+ <div className="data-space__viewer__models-documentation__grid__cell__label__icon data-space__viewer__models-documentation__grid__cell__label__icon--enum">
479
+ e
480
+ </div>
481
+ <div className="data-space__viewer__models-documentation__grid__cell__label__text">
482
+ {label}
483
+ </div>
484
+ </div>
485
+ <div className="data-space__viewer__models-documentation__grid__cell__actions">
486
+ <DropdownMenu
487
+ className="data-space__viewer__models-documentation__grid__cell__action"
488
+ menuProps={{
489
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
490
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
491
+ elevation: 7,
492
+ }}
493
+ content={
494
+ <MenuContent>
495
+ <MenuContentItem onClick={copyValue}>
496
+ Copy Value
497
+ </MenuContentItem>
498
+ </MenuContent>
499
+ }
500
+ >
501
+ <MoreVerticalIcon />
502
+ </DropdownMenu>
503
+ </div>
504
+ </div>
505
+ );
506
+ }
507
+ return null;
508
+ },
509
+ );
510
+
511
+ const ElementDocumentationCellRenderer = (
512
+ params: DataGridCellRendererParams<NormalizedDataSpaceDocumentationEntry> & {
513
+ dataSpaceViewerState: DataSpaceViewerState;
514
+ },
515
+ ): React.ReactNode => {
516
+ const data = params.data;
517
+ if (!data) {
518
+ return null;
519
+ }
520
+ return data.documentation.trim() ? (
521
+ data.documentation
522
+ ) : (
523
+ <div className="data-space__viewer__grid__empty-cell">
524
+ No documentation provided
525
+ </div>
526
+ );
527
+ };
528
+
529
+ const DataSpaceModelsDocumentationGridPanel = observer(
530
+ (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
531
+ const { dataSpaceViewerState } = props;
532
+ const documentationState = dataSpaceViewerState.modelsDocumentationState;
533
+
534
+ return (
535
+ <div
536
+ className={clsx(
537
+ 'data-space__viewer__models-documentation__grid data-space__viewer__grid ag-theme-balham-dark',
538
+ {
539
+ 'data-space__viewer__models-documentation__grid--shrink':
540
+ documentationState.showFilterPanel,
541
+ },
542
+ )}
543
+ >
544
+ <DataGrid
545
+ rowData={documentationState.filteredSearchResults}
546
+ overlayNoRowsTemplate={`<div class="data-space__viewer__grid--empty">No documentation found</div>`}
547
+ // highlight element row
548
+ getRowClass={(params) =>
549
+ params.data?.entry instanceof DataSpaceModelDocumentationEntry
550
+ ? 'data-space__viewer__models-documentation__grid__element-row'
551
+ : undefined
552
+ }
553
+ alwaysShowVerticalScroll={true}
554
+ gridOptions={{
555
+ suppressScrollOnNewData: true,
556
+ getRowId: (rowData) => rowData.data.uuid,
557
+ }}
558
+ suppressFieldDotNotation={true}
559
+ columnDefs={[
560
+ {
561
+ minWidth: 50,
562
+ sortable: true,
563
+ resizable: true,
564
+ cellRendererParams: {
565
+ dataSpaceViewerState,
566
+ },
567
+ cellRenderer: ElementContentCellRenderer,
568
+ headerName: 'Model',
569
+ flex: 1,
570
+ },
571
+ {
572
+ minWidth: 50,
573
+ sortable: false,
574
+ resizable: true,
575
+ cellRendererParams: {
576
+ dataSpaceViewerState,
577
+ },
578
+ cellRenderer: SubElementDocContentCellRenderer,
579
+ headerName: '',
580
+ flex: 1,
581
+ },
582
+ {
583
+ minWidth: 50,
584
+ sortable: false,
585
+ resizable: false,
586
+ headerClass: 'data-space__viewer__grid__last-column-header',
587
+ cellRenderer: ElementDocumentationCellRenderer,
588
+ headerName: 'Documentation',
589
+ flex: 1,
590
+ wrapText: true,
591
+ autoHeight: true,
592
+ },
593
+ ]}
594
+ />
595
+ </div>
596
+ );
597
+ },
598
+ );
599
+
600
+ const getFilterTreeNodeIcon = (
601
+ node: ModelsDocumentationFilterTreeNodeData,
602
+ ): React.ReactNode | undefined => {
603
+ if (node instanceof ModelsDocumentationFilterTreeElementNodeData) {
604
+ if (node.typePath === CORE_PURE_PATH.CLASS) {
605
+ return (
606
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--class">
607
+ C
608
+ </div>
609
+ );
610
+ } else if (node.typePath === CORE_PURE_PATH.ENUMERATION) {
611
+ return (
612
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--enumeration">
613
+ E
614
+ </div>
615
+ );
616
+ } else if (node.typePath === CORE_PURE_PATH.ASSOCIATION) {
617
+ return (
618
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--association">
619
+ A
620
+ </div>
621
+ );
622
+ }
623
+ } else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) {
624
+ return (
625
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--package">
626
+ <PackageIcon />
627
+ </div>
628
+ );
629
+ } else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) {
630
+ switch (node.typePath) {
631
+ case CORE_PURE_PATH.CLASS:
632
+ return (
633
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--class">
634
+ C
635
+ </div>
636
+ );
637
+ case CORE_PURE_PATH.ENUMERATION:
638
+ return (
639
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--enumeration">
640
+ E
641
+ </div>
642
+ );
643
+ case CORE_PURE_PATH.ASSOCIATION:
644
+ return (
645
+ <div className="data-space__viewer__models-documentation__filter__tree__node__type-icon data-space__viewer__models-documentation__filter__tree__node__type-icon--association">
646
+ A
647
+ </div>
648
+ );
649
+ default:
650
+ return undefined;
651
+ }
652
+ }
653
+ return undefined;
654
+ };
655
+
656
+ const getFilterNodeCount = (
657
+ node: ModelsDocumentationFilterTreeNodeData,
658
+ documentationState: DataSpaceViewerModelsDocumentationState,
659
+ ): number | undefined => {
660
+ if (node instanceof ModelsDocumentationFilterTreeElementNodeData) {
661
+ return documentationState.searchResults.filter(
662
+ (result) => node.elementPath === result.elementEntry.path,
663
+ ).length;
664
+ } else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) {
665
+ return documentationState.searchResults.filter(
666
+ (result) =>
667
+ node.packagePath === result.elementEntry.path ||
668
+ result.elementEntry.path.startsWith(
669
+ `${node.packagePath}${ELEMENT_PATH_DELIMITER}`,
670
+ ),
671
+ ).length;
672
+ } else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) {
673
+ return node.typePath === CORE_PURE_PATH.CLASS
674
+ ? documentationState.searchResults.filter(
675
+ (entry) =>
676
+ entry.elementEntry instanceof DataSpaceClassDocumentationEntry,
677
+ ).length
678
+ : node.typePath === CORE_PURE_PATH.ENUMERATION
679
+ ? documentationState.searchResults.filter(
680
+ (entry) =>
681
+ entry.elementEntry instanceof
682
+ DataSpaceEnumerationDocumentationEntry,
683
+ ).length
684
+ : node.typePath === CORE_PURE_PATH.ASSOCIATION
685
+ ? documentationState.searchResults.filter(
686
+ (entry) =>
687
+ entry.elementEntry instanceof
688
+ DataSpaceAssociationDocumentationEntry,
689
+ ).length
690
+ : undefined;
691
+ } else if (node instanceof ModelsDocumentationFilterTreeRootNodeData) {
692
+ return documentationState.searchResults.length;
693
+ }
694
+ return undefined;
695
+ };
696
+
697
+ const DataSpaceModelsDocumentationFilterTreeNodeContainer = observer(
698
+ (
699
+ props: TreeNodeContainerProps<
700
+ ModelsDocumentationFilterTreeNodeData,
701
+ {
702
+ documentationState: DataSpaceViewerModelsDocumentationState;
703
+ refreshTreeData: () => void;
704
+ uncheckTree: () => void;
705
+ updateFilter: () => void;
706
+ }
707
+ >,
708
+ ) => {
709
+ const { node, level, innerProps } = props;
710
+ const { documentationState, refreshTreeData, uncheckTree, updateFilter } =
711
+ innerProps;
712
+ const isExpandable = Boolean(node.childrenIds.length);
713
+ const expandIcon = isExpandable ? (
714
+ node.isOpen ? (
715
+ <ChevronDownIcon />
716
+ ) : (
717
+ <ChevronRightIcon />
718
+ )
719
+ ) : (
720
+ <div />
721
+ );
722
+ const checkerIcon =
723
+ node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED ? (
724
+ <CheckSquareIcon />
725
+ ) : node.checkType ===
726
+ ModelsDocumentationFilterTreeNodeCheckType.PARTIALLY_CHECKED ? (
727
+ <MinusSquareIcon />
728
+ ) : (
729
+ <EmptySquareIcon />
730
+ );
731
+ const nodeCount = getFilterNodeCount(node, documentationState);
732
+ const toggleChecker: React.MouseEventHandler<Element> = (event) => {
733
+ event.stopPropagation();
734
+
735
+ if (
736
+ node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED
737
+ ) {
738
+ uncheckFilterTreeNode(node);
739
+ } else {
740
+ checkFilterTreeNode(node);
741
+ }
742
+
743
+ refreshTreeData();
744
+ updateFilter();
745
+ };
746
+ const toggleExpandNode: React.MouseEventHandler<Element> = (event) => {
747
+ event.stopPropagation();
748
+
749
+ if (isExpandable) {
750
+ node.setIsOpen(!node.isOpen);
751
+ refreshTreeData();
752
+ }
753
+ };
754
+ const onNodeClick = (): void => {
755
+ uncheckTree();
756
+ checkFilterTreeNode(node);
757
+
758
+ if (isExpandable && !node.isOpen) {
759
+ node.setIsOpen(true);
760
+ }
761
+ refreshTreeData();
762
+ updateFilter();
763
+ };
764
+
765
+ return (
766
+ <div
767
+ className="tree-view__node__container data-space__viewer__models-documentation__filter__tree__node__container"
768
+ style={{
769
+ paddingLeft: `${(level - 1) * 1.4}rem`,
770
+ display: 'flex',
771
+ }}
772
+ onClick={onNodeClick}
773
+ >
774
+ <div
775
+ className="data-space__viewer__models-documentation__filter__tree__node__expand-icon"
776
+ onClick={toggleExpandNode}
777
+ >
778
+ {expandIcon}
779
+ </div>
780
+ <div
781
+ className="data-space__viewer__models-documentation__filter__tree__node__checker"
782
+ onClick={toggleChecker}
783
+ >
784
+ {checkerIcon}
785
+ </div>
786
+ {getFilterTreeNodeIcon(node)}
787
+ <div className="tree-view__node__label data-space__viewer__models-documentation__filter__tree__node__label">
788
+ {node.label}
789
+ </div>
790
+ {nodeCount !== undefined && (
791
+ <div className="tree-view__node__label data-space__viewer__models-documentation__filter__tree__node__count">
792
+ {nodeCount}
793
+ </div>
794
+ )}
795
+ </div>
796
+ );
797
+ },
798
+ );
799
+
800
+ const DataSpaceModelsDocumentationFilterPanel = observer(
801
+ (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
802
+ const { dataSpaceViewerState } = props;
803
+ const documentationState = dataSpaceViewerState.modelsDocumentationState;
804
+ const resetAll = (): void => documentationState.resetAllFilters();
805
+ const resetTypeFilter = (): void => documentationState.resetTypeFilter();
806
+ const resetPackageFilter = (): void =>
807
+ documentationState.resetPackageFilter();
808
+
809
+ return (
810
+ <div className="data-space__viewer__models-documentation__filter__panel">
811
+ <div className="data-space__viewer__models-documentation__filter__group">
812
+ <div className="data-space__viewer__models-documentation__filter__group__header">
813
+ <div className="data-space__viewer__models-documentation__filter__group__header__label">
814
+ Filter
815
+ </div>
816
+ <div className="data-space__viewer__models-documentation__filter__group__header__actions">
817
+ <button
818
+ className="data-space__viewer__models-documentation__filter__group__header__reset"
819
+ tabIndex={-1}
820
+ disabled={!documentationState.isFilterCustomized}
821
+ onClick={resetAll}
822
+ >
823
+ Reset All
824
+ </button>
825
+ </div>
826
+ </div>
827
+ </div>
828
+ <div className="data-space__viewer__models-documentation__filter__group data-space__viewer__models-documentation__filter__group--by-type">
829
+ <div className="data-space__viewer__models-documentation__filter__group__header">
830
+ <div className="data-space__viewer__models-documentation__filter__group__header__label">
831
+ Filter by Type
832
+ </div>
833
+ <div className="data-space__viewer__models-documentation__filter__group__header__actions">
834
+ <button
835
+ className="data-space__viewer__models-documentation__filter__group__header__reset"
836
+ tabIndex={-1}
837
+ disabled={!documentationState.isTypeFilterCustomized}
838
+ onClick={resetTypeFilter}
839
+ >
840
+ Reset
841
+ </button>
842
+ </div>
843
+ </div>
844
+ <div className="data-space__viewer__models-documentation__filter__group__content">
845
+ <TreeView
846
+ components={{
847
+ TreeNodeContainer:
848
+ DataSpaceModelsDocumentationFilterTreeNodeContainer,
849
+ }}
850
+ treeData={documentationState.typeFilterTreeData}
851
+ getChildNodes={(node) =>
852
+ node.childrenIds
853
+ .map((id) =>
854
+ documentationState.typeFilterTreeData.nodes.get(id),
855
+ )
856
+ .filter(isNonNullable)
857
+ .sort((a, b) => a.label.localeCompare(b.label))
858
+ }
859
+ innerProps={{
860
+ documentationState,
861
+ refreshTreeData: (): void =>
862
+ documentationState.resetTypeFilterTreeData(),
863
+ uncheckTree: (): void =>
864
+ uncheckAllFilterTree(documentationState.typeFilterTreeData),
865
+ updateFilter: (): void => documentationState.updateTypeFilter(),
866
+ }}
867
+ />
868
+ </div>
869
+ </div>
870
+ <div className="data-space__viewer__models-documentation__filter__group data-space__viewer__models-documentation__filter__group--by-package">
871
+ <div className="data-space__viewer__models-documentation__filter__group__header">
872
+ <div className="data-space__viewer__models-documentation__filter__group__header__label">
873
+ Filter by Package
874
+ </div>
875
+ <div className="data-space__viewer__models-documentation__filter__group__header__actions">
876
+ <button
877
+ className="data-space__viewer__models-documentation__filter__group__header__reset"
878
+ tabIndex={-1}
879
+ disabled={!documentationState.isPackageFilterCustomized}
880
+ onClick={resetPackageFilter}
881
+ >
882
+ Reset
883
+ </button>
884
+ </div>
885
+ </div>
886
+ <div className="data-space__viewer__models-documentation__filter__group__content">
887
+ <TreeView
888
+ components={{
889
+ TreeNodeContainer:
890
+ DataSpaceModelsDocumentationFilterTreeNodeContainer,
891
+ }}
892
+ treeData={documentationState.packageFilterTreeData}
893
+ getChildNodes={(node) =>
894
+ node.childrenIds
895
+ .map((id) =>
896
+ documentationState.packageFilterTreeData.nodes.get(id),
897
+ )
898
+ .filter(isNonNullable)
899
+ .sort((a, b) => a.label.localeCompare(b.label))
900
+ }
901
+ innerProps={{
902
+ documentationState,
903
+ refreshTreeData: (): void =>
904
+ documentationState.resetPackageFilterTreeData(),
905
+ uncheckTree: (): void =>
906
+ uncheckAllFilterTree(
907
+ documentationState.packageFilterTreeData,
908
+ ),
909
+ updateFilter: (): void =>
910
+ documentationState.updatePackageFilter(),
911
+ }}
912
+ />
913
+ </div>
914
+ </div>
915
+ </div>
916
+ );
917
+ },
918
+ );
919
+
920
+ const DataSpaceModelsDocumentationSearchBar = observer(
921
+ (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
922
+ const { dataSpaceViewerState } = props;
923
+ const searchInputRef = useRef<HTMLInputElement>(null);
924
+ const searchConfigTriggerRef = useRef<HTMLButtonElement>(null);
925
+ const documentationState = dataSpaceViewerState.modelsDocumentationState;
926
+ const searchText = documentationState.searchText;
927
+ const debouncedSearch = useMemo(
928
+ () => debounce(() => documentationState.search(), 100),
929
+ [documentationState],
930
+ );
931
+ const onSearchTextChange: React.ChangeEventHandler<HTMLInputElement> = (
932
+ event,
933
+ ) => {
934
+ documentationState.setSearchText(event.target.value);
935
+ debouncedSearch.cancel();
936
+ debouncedSearch();
937
+ };
938
+
939
+ // actions
940
+ const clearSearchText = (): void => {
941
+ documentationState.resetSearch();
942
+ searchInputRef.current?.focus();
943
+ };
944
+ const toggleSearchConfigMenu = (): void =>
945
+ documentationState.setShowSearchConfigurationMenu(
946
+ !documentationState.showSearchConfigurationMenu,
947
+ );
948
+ const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
949
+ if (event.code === 'Escape') {
950
+ searchInputRef.current?.select();
951
+ }
952
+ };
953
+
954
+ // search config menu
955
+ const closeSearchConfigMenu = (): void =>
956
+ documentationState.setShowSearchConfigurationMenu(false);
957
+ const onSearchConfigMenuOpen = (): void => searchInputRef.current?.focus();
958
+
959
+ return (
960
+ <div className="data-space__viewer__models-documentation__search">
961
+ <input
962
+ ref={searchInputRef}
963
+ onKeyDown={onKeyDown}
964
+ className="data-space__viewer__models-documentation__search__input input--dark"
965
+ spellCheck={false}
966
+ onChange={onSearchTextChange}
967
+ value={searchText}
968
+ placeholder="Search documentation"
969
+ />
970
+ <button
971
+ ref={searchConfigTriggerRef}
972
+ className={clsx(
973
+ 'data-space__viewer__models-documentation__search__input__config__trigger',
974
+ {
975
+ 'data-space__viewer__models-documentation__search__input__config__trigger--toggled':
976
+ documentationState.showSearchConfigurationMenu,
977
+ 'data-space__viewer__models-documentation__search__input__config__trigger--active':
978
+ documentationState.searchConfigurationState
979
+ .isAdvancedSearchActive,
980
+ },
981
+ )}
982
+ tabIndex={-1}
983
+ onClick={toggleSearchConfigMenu}
984
+ title={`${
985
+ documentationState.searchConfigurationState.isAdvancedSearchActive
986
+ ? 'Advanced search is currently active\n'
987
+ : ''
988
+ }Click to toggle search config menu`}
989
+ >
990
+ <CogIcon />
991
+ </button>
992
+ <BasePopover
993
+ open={Boolean(documentationState.showSearchConfigurationMenu)}
994
+ TransitionProps={{
995
+ onEnter: onSearchConfigMenuOpen,
996
+ }}
997
+ anchorEl={searchConfigTriggerRef.current}
998
+ onClose={closeSearchConfigMenu}
999
+ anchorOrigin={{
1000
+ vertical: 'bottom',
1001
+ horizontal: 'center',
1002
+ }}
1003
+ transformOrigin={{
1004
+ vertical: 'top',
1005
+ horizontal: 'center',
1006
+ }}
1007
+ >
1008
+ <FuzzySearchAdvancedConfigMenu
1009
+ configState={documentationState.searchConfigurationState}
1010
+ />
1011
+ </BasePopover>
1012
+ {!searchText ? (
1013
+ <div className="data-space__viewer__models-documentation__search__input__search__icon">
1014
+ <SearchIcon />
1015
+ </div>
1016
+ ) : (
1017
+ <button
1018
+ className="data-space__viewer__models-documentation__search__input__clear-btn"
1019
+ tabIndex={-1}
1020
+ onClick={clearSearchText}
1021
+ title="Clear"
1022
+ >
1023
+ <TimesIcon />
1024
+ </button>
1025
+ )}
1026
+ </div>
1027
+ );
1028
+ },
1029
+ );
23
1030
 
24
1031
  export const DataSpaceModelsDocumentation = observer(
25
1032
  (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
26
1033
  const { dataSpaceViewerState } = props;
27
1034
  const documentationEntries =
28
1035
  dataSpaceViewerState.dataSpaceAnalysisResult.elementDocs;
1036
+ const documentationState = dataSpaceViewerState.modelsDocumentationState;
1037
+ const toggleFilterPanel = (): void =>
1038
+ documentationState.setShowFilterPanel(
1039
+ !documentationState.showFilterPanel,
1040
+ );
29
1041
 
30
1042
  return (
31
1043
  <div className="data-space__viewer__wiki__section">
@@ -40,51 +1052,36 @@ export const DataSpaceModelsDocumentation = observer(
40
1052
  <div className="data-space__viewer__wiki__section__content">
41
1053
  {documentationEntries.length > 0 && (
42
1054
  <div className="data-space__viewer__models-documentation">
43
- <div className="data-space__viewer__models-documentation__search">
44
- <div className="data-space__viewer__models-documentation__search__input-group">
45
- <input className="data-space__viewer__models-documentation__search__input-group__input input" />
46
- <div className="data-space__viewer__models-documentation__search__input-group__icon">
47
- <SearchIcon />
1055
+ <div className="data-space__viewer__models-documentation__header">
1056
+ <button
1057
+ className="data-space__viewer__models-documentation__filter__toggler"
1058
+ title="Toggle Filter Panel"
1059
+ tabIndex={-1}
1060
+ onClick={toggleFilterPanel}
1061
+ >
1062
+ <div className="data-space__viewer__models-documentation__filter__toggler__arrow">
1063
+ {documentationState.showFilterPanel ? (
1064
+ <CaretLeftIcon />
1065
+ ) : (
1066
+ <CaretRightIcon />
1067
+ )}
48
1068
  </div>
49
- </div>
1069
+ <div className="data-space__viewer__models-documentation__filter__toggler__icon">
1070
+ <FilterIcon />
1071
+ </div>
1072
+ </button>
1073
+ <DataSpaceModelsDocumentationSearchBar
1074
+ dataSpaceViewerState={dataSpaceViewerState}
1075
+ />
50
1076
  </div>
51
- <div className="data-space__viewer__models-documentation__grid data-space__viewer__grid ag-theme-balham-dark">
52
- <AgGridReact
53
- rowData={documentationEntries}
54
- gridOptions={{
55
- suppressScrollOnNewData: true,
56
- getRowId: (rowData) => rowData.data.uuid,
57
- }}
58
- modules={[ClientSideRowModelModule]}
59
- suppressFieldDotNotation={true}
60
- columnDefs={[
61
- {
62
- minWidth: 50,
63
- sortable: true,
64
- resizable: true,
65
- field: 'elementPath',
66
- headerName: 'Model',
67
- flex: 1,
68
- },
69
- {
70
- minWidth: 50,
71
- sortable: false,
72
- resizable: true,
73
- field: 'subElementText',
74
- headerName: '',
75
- flex: 1,
76
- },
77
- {
78
- minWidth: 50,
79
- sortable: false,
80
- resizable: true,
81
- field: 'doc',
82
- headerName: 'Documentation',
83
- flex: 1,
84
- wrapText: true,
85
- autoHeight: true,
86
- },
87
- ]}
1077
+ <div className="data-space__viewer__models-documentation__content">
1078
+ {documentationState.showFilterPanel && (
1079
+ <DataSpaceModelsDocumentationFilterPanel
1080
+ dataSpaceViewerState={dataSpaceViewerState}
1081
+ />
1082
+ )}
1083
+ <DataSpaceModelsDocumentationGridPanel
1084
+ dataSpaceViewerState={dataSpaceViewerState}
88
1085
  />
89
1086
  </div>
90
1087
  </div>