@finos/legend-extension-dsl-data-space 10.4.255 → 10.4.257

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 (85) hide show
  1. package/lib/__lib__/DSL_DataSpace_Event.d.ts +1 -0
  2. package/lib/__lib__/DSL_DataSpace_Event.d.ts.map +1 -1
  3. package/lib/__lib__/DSL_DataSpace_Event.js +1 -0
  4. package/lib/__lib__/DSL_DataSpace_Event.js.map +1 -1
  5. package/lib/components/DataSpaceDataAccess.d.ts.map +1 -1
  6. package/lib/components/DataSpaceDataAccess.js +3 -16
  7. package/lib/components/DataSpaceDataAccess.js.map +1 -1
  8. package/lib/components/DataSpaceDescription.d.ts.map +1 -1
  9. package/lib/components/DataSpaceDescription.js +2 -6
  10. package/lib/components/DataSpaceDescription.js.map +1 -1
  11. package/lib/components/DataSpaceQualityEmote.d.ts +22 -0
  12. package/lib/components/DataSpaceQualityEmote.d.ts.map +1 -0
  13. package/lib/components/DataSpaceQualityEmote.js +133 -0
  14. package/lib/components/DataSpaceQualityEmote.js.map +1 -0
  15. package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
  16. package/lib/components/DataSpaceQuickStart.js +7 -19
  17. package/lib/components/DataSpaceQuickStart.js.map +1 -1
  18. package/lib/components/DataSpaceViewer.d.ts.map +1 -1
  19. package/lib/components/DataSpaceViewer.js +40 -21
  20. package/lib/components/DataSpaceViewer.js.map +1 -1
  21. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.d.ts +2 -0
  22. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.d.ts.map +1 -1
  23. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.js +1 -0
  24. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.js.map +1 -1
  25. package/lib/components/index.d.ts +1 -0
  26. package/lib/components/index.d.ts.map +1 -1
  27. package/lib/components/index.js +1 -0
  28. package/lib/components/index.js.map +1 -1
  29. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.d.ts +2 -1
  30. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.d.ts.map +1 -1
  31. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js +4 -0
  32. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js.map +1 -1
  33. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.d.ts.map +1 -1
  34. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.js +5 -1
  35. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.js.map +1 -1
  36. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.d.ts.map +1 -1
  37. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.js +39 -1
  38. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.js.map +1 -1
  39. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.d.ts +2 -1
  40. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.d.ts.map +1 -1
  41. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.js +4 -0
  42. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.js.map +1 -1
  43. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.d.ts.map +1 -1
  44. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.js +6 -4
  45. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.js.map +1 -1
  46. package/lib/index.css +2 -2
  47. package/lib/index.css.map +1 -1
  48. package/lib/package.json +1 -1
  49. package/lib/stores/DataSpaceLayoutState.d.ts +7 -34
  50. package/lib/stores/DataSpaceLayoutState.d.ts.map +1 -1
  51. package/lib/stores/DataSpaceLayoutState.js +22 -159
  52. package/lib/stores/DataSpaceLayoutState.js.map +1 -1
  53. package/lib/stores/DataSpaceQualityState.d.ts +49 -0
  54. package/lib/stores/DataSpaceQualityState.d.ts.map +1 -0
  55. package/lib/stores/DataSpaceQualityState.js +84 -0
  56. package/lib/stores/DataSpaceQualityState.js.map +1 -0
  57. package/lib/stores/DataSpaceViewerDiagramViewerState.js +1 -2
  58. package/lib/stores/DataSpaceViewerDiagramViewerState.js.map +1 -1
  59. package/lib/stores/DataSpaceViewerState.d.ts +11 -8
  60. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  61. package/lib/stores/DataSpaceViewerState.js +20 -13
  62. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  63. package/lib/stores/query/DataSpaceAdvancedSearchState.d.ts.map +1 -1
  64. package/lib/stores/query/DataSpaceAdvancedSearchState.js +7 -1
  65. package/lib/stores/query/DataSpaceAdvancedSearchState.js.map +1 -1
  66. package/package.json +14 -14
  67. package/src/__lib__/DSL_DataSpace_Event.ts +1 -0
  68. package/src/components/DataSpaceDataAccess.tsx +9 -68
  69. package/src/components/DataSpaceDescription.tsx +8 -41
  70. package/src/components/DataSpaceQualityEmote.tsx +223 -0
  71. package/src/components/DataSpaceQuickStart.tsx +37 -103
  72. package/src/components/DataSpaceViewer.tsx +156 -112
  73. package/src/components/__test-utils__/DataSpaceViewerTestUtils.ts +3 -0
  74. package/src/components/index.ts +5 -0
  75. package/src/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.ts +5 -0
  76. package/src/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.ts +6 -0
  77. package/src/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.ts +56 -0
  78. package/src/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.ts +5 -0
  79. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.ts +6 -3
  80. package/src/stores/DataSpaceLayoutState.ts +25 -209
  81. package/src/stores/DataSpaceQualityState.ts +117 -0
  82. package/src/stores/DataSpaceViewerDiagramViewerState.ts +1 -1
  83. package/src/stores/DataSpaceViewerState.ts +45 -19
  84. package/src/stores/query/DataSpaceAdvancedSearchState.ts +9 -2
  85. package/tsconfig.json +2 -0
@@ -15,15 +15,16 @@
15
15
  */
16
16
 
17
17
  import { NAVIGATION_ZONE_SEPARATOR } from '@finos/legend-application';
18
- import { action, computed, makeObservable, observable } from 'mobx';
18
+ import { makeObservable, override } from 'mobx';
19
19
  import { type DataSpaceViewerState } from './DataSpaceViewerState.js';
20
- import { at, guaranteeNonNullable, isNonNullable } from '@finos/legend-shared';
20
+ import { at, guaranteeNonNullable } from '@finos/legend-shared';
21
21
  import {
22
22
  DATA_SPACE_VIEWER_ACTIVITY_MODE,
23
23
  extractActivityFromAnchor,
24
24
  generateAnchorForActivity,
25
25
  generateAnchorForDiagram,
26
26
  } from './DataSpaceViewerNavigation.js';
27
+ import { BaseLayoutState } from '@finos/legend-extension-dsl-data-product';
27
28
 
28
29
  export const DATA_SPACE_WIKI_PAGE_SECTIONS = [
29
30
  DATA_SPACE_VIEWER_ACTIVITY_MODE.DESCRIPTION,
@@ -37,234 +38,49 @@ const DATA_SPACE_WIKI_PAGE_ANCHORS = DATA_SPACE_WIKI_PAGE_SECTIONS.map(
37
38
  (activity) => generateAnchorForActivity(activity),
38
39
  );
39
40
 
40
- type DataSpacePageNavigationCommand = {
41
- anchor: string;
42
- };
43
-
44
- export class CollapseState {
45
- private readonly collapsedKeys = new Set<string>();
41
+ export class DataSpaceLayoutState extends BaseLayoutState {
42
+ private dataSpaceViewerState!: DataSpaceViewerState;
46
43
 
47
44
  constructor() {
48
- makeObservable<CollapseState, 'collapsedKeys'>(this, {
49
- collapsedKeys: observable,
50
- toggleSectionCollapse: action,
51
- toggleAllSectionsCollapse: action,
45
+ super();
46
+ makeObservable(this, {
47
+ isWikiPageFullyRendered: override,
52
48
  });
53
49
  }
54
50
 
55
- isSectionCollapsed(key: string): boolean {
56
- return this.collapsedKeys.has(key);
51
+ setViewerState(dataSpaceViewerState: DataSpaceViewerState): void {
52
+ this.dataSpaceViewerState = dataSpaceViewerState;
57
53
  }
58
54
 
59
- toggleSectionCollapse(key: string): void {
60
- if (this.collapsedKeys.has(key)) {
61
- this.collapsedKeys.delete(key);
62
- } else {
63
- this.collapsedKeys.add(key);
64
- }
55
+ protected getValidAnchors(): string[] {
56
+ return DATA_SPACE_WIKI_PAGE_ANCHORS;
65
57
  }
66
58
 
67
- areAllSectionsCollapsed(keys: string[]): boolean {
68
- return keys.length > 0 && keys.every((key) => this.collapsedKeys.has(key));
59
+ protected get expectedGridCount(): number {
60
+ return 0;
69
61
  }
70
62
 
71
- toggleAllSectionsCollapse(keys: string[]): void {
72
- const shouldCollapse = !this.areAllSectionsCollapsed(keys);
73
- keys.forEach((key) => {
74
- if (shouldCollapse) {
75
- this.collapsedKeys.add(key);
76
- } else {
77
- this.collapsedKeys.delete(key);
78
- }
79
- });
80
- }
81
- }
82
-
83
- export class DataSpaceLayoutState {
84
- readonly dataSpaceViewerState: DataSpaceViewerState;
85
-
86
- currentNavigationZone = '';
87
- isExpandedModeEnabled = false;
88
-
89
- frame?: HTMLElement | undefined;
90
- header?: HTMLElement | undefined;
91
- isTopScrollerVisible = false;
92
-
93
- private wikiPageAnchorIndex = new Map<string, HTMLElement>();
94
- wikiPageNavigationCommand?: DataSpacePageNavigationCommand | undefined;
95
- private wikiPageVisibleAnchors: string[] = [];
96
- private wikiPageScrollIntersectionObserver?: IntersectionObserver | undefined;
97
-
98
- readonly sectionCollapseState = new CollapseState();
99
-
100
- constructor(dataSpaceViewerState: DataSpaceViewerState) {
101
- makeObservable<
102
- DataSpaceLayoutState,
103
- | 'wikiPageAnchorIndex'
104
- | 'wikiPageVisibleAnchors'
105
- | 'updatePageVisibleAnchors'
106
- >(this, {
107
- currentNavigationZone: observable,
108
- isExpandedModeEnabled: observable,
109
- isTopScrollerVisible: observable,
110
- wikiPageAnchorIndex: observable,
111
- wikiPageVisibleAnchors: observable,
112
- frame: observable.ref,
113
- wikiPageNavigationCommand: observable.ref,
114
- isWikiPageFullyRendered: computed,
115
- registerWikiPageScrollObserver: action,
116
- setCurrentNavigationZone: action,
117
- enableExpandedMode: action,
118
- setFrame: action,
119
- setTopScrollerVisible: action,
120
- setWikiPageAnchor: action,
121
- unsetWikiPageAnchor: action,
122
- setWikiPageAnchorToNavigate: action,
123
- updatePageVisibleAnchors: action,
124
- });
125
-
126
- this.dataSpaceViewerState = dataSpaceViewerState;
127
- }
128
-
129
- setCurrentNavigationZone(val: string): void {
130
- this.currentNavigationZone = val;
131
- }
132
-
133
- get isWikiPageFullyRendered(): boolean {
63
+ override get isWikiPageFullyRendered(): boolean {
134
64
  return (
135
- Boolean(this.frame) &&
65
+ super.isWikiPageFullyRendered &&
136
66
  DATA_SPACE_WIKI_PAGE_SECTIONS.includes(
137
67
  this.dataSpaceViewerState.currentActivity,
138
- ) &&
139
- DATA_SPACE_WIKI_PAGE_ANCHORS.every((anchor) =>
140
- this.wikiPageAnchorIndex.has(anchor),
141
- ) &&
142
- Array.from(this.wikiPageAnchorIndex.values()).every(isNonNullable)
68
+ )
143
69
  );
144
70
  }
145
71
 
146
- registerWikiPageScrollObserver(): void {
147
- if (this.frame && this.isWikiPageFullyRendered) {
148
- const wikiPageIntersectionObserver = new IntersectionObserver(
149
- (entries, observer) => {
150
- const anchorsWithVisibilityChanged = entries
151
- .map((entry) => {
152
- for (const [key, element] of this.wikiPageAnchorIndex.entries()) {
153
- if (element === entry.target) {
154
- return { key, isIntersecting: entry.isIntersecting };
155
- }
156
- }
157
- return undefined;
158
- })
159
- .filter(isNonNullable);
160
- anchorsWithVisibilityChanged.forEach((entry) => {
161
- this.updatePageVisibleAnchors(entry.key, entry.isIntersecting);
162
- });
163
- // NOTE: sync scroll with menu/address is quite a delicate piece of work
164
- // as it interferes with programatic scroll operations we do elsewhere.
165
- // This is particularly bad when we do a programatic `smooth` scroll, which
166
- // mimic user scrolling behavior and would tangle up with this observer
167
- // Since currently, there's no good mechanism to detect scroll end event, and as such,
168
- // there is no good way to temporarily disable this logic while doing the programmatic
169
- // smooth scroll as such, we avoid supporting programatic smooth scrolling for now
170
- // See https://github.com/w3c/csswg-drafts/issues/3744
171
- // See https://developer.mozilla.org/en-US/docs/Web/API/Document/scrollend_event
172
- if (
173
- // if current navigation zone is not set, do not update zone
174
- this.currentNavigationZone === '' ||
175
- // if there is no visible anchors, do not update zone
176
- !this.wikiPageVisibleAnchors.length ||
177
- // if some of the current visible anchors match or is parent section of the current
178
- // navigation zone, do not update zone
179
- this.wikiPageVisibleAnchors.some(
180
- (visibleAnchor) =>
181
- this.currentNavigationZone === visibleAnchor ||
182
- this.currentNavigationZone.startsWith(
183
- `${visibleAnchor}${NAVIGATION_ZONE_SEPARATOR}`,
184
- ),
185
- )
186
- ) {
187
- return;
188
- }
189
- const anchor = at(this.wikiPageVisibleAnchors, 0);
190
- this.dataSpaceViewerState.syncZoneWithNavigation(anchor);
191
- const anchorChunks = anchor.split(NAVIGATION_ZONE_SEPARATOR);
192
- const activity = anchorChunks[0];
193
- if (activity) {
194
- this.dataSpaceViewerState.setCurrentActivity(
195
- extractActivityFromAnchor(
196
- activity,
197
- ) as DATA_SPACE_VIEWER_ACTIVITY_MODE,
198
- );
199
- }
200
- },
201
- {
202
- root: this.frame,
203
- threshold: 0.5,
204
- },
205
- );
206
- Array.from(this.wikiPageAnchorIndex.values()).forEach((el) =>
207
- wikiPageIntersectionObserver.observe(el),
72
+ protected override onWikiPageVisibleAnchorsSettled(): void {
73
+ const anchor = at(this.wikiPageVisibleAnchors, 0);
74
+ this.dataSpaceViewerState.syncZoneWithNavigation(anchor);
75
+ const activity = anchor.split(NAVIGATION_ZONE_SEPARATOR)[0];
76
+ if (activity) {
77
+ this.dataSpaceViewerState.setCurrentActivity(
78
+ extractActivityFromAnchor(activity) as DATA_SPACE_VIEWER_ACTIVITY_MODE,
208
79
  );
209
- this.wikiPageScrollIntersectionObserver = wikiPageIntersectionObserver;
210
80
  }
211
81
  }
212
82
 
213
- unregisterWikiPageScrollObserver(): void {
214
- this.wikiPageScrollIntersectionObserver?.disconnect();
215
- this.wikiPageScrollIntersectionObserver = undefined;
216
- this.wikiPageVisibleAnchors = [];
217
- }
218
-
219
- private updatePageVisibleAnchors(
220
- changedAnchor: string,
221
- isIntersecting: boolean,
222
- ): void {
223
- if (isIntersecting) {
224
- const anchors = this.wikiPageVisibleAnchors.filter(
225
- (anchor) => changedAnchor !== anchor,
226
- );
227
- // NOTE: the newly visible anchors should be the furthest one in
228
- // the direction of scroll
229
- anchors.push(changedAnchor);
230
- this.wikiPageVisibleAnchors = anchors;
231
- } else {
232
- this.wikiPageVisibleAnchors = this.wikiPageVisibleAnchors.filter(
233
- (anchor) => changedAnchor !== anchor,
234
- );
235
- }
236
- }
237
-
238
- enableExpandedMode(val: boolean): void {
239
- this.isExpandedModeEnabled = val;
240
- }
241
-
242
- setFrame(val: HTMLElement | undefined): void {
243
- this.frame = val;
244
- }
245
-
246
- setTopScrollerVisible(val: boolean): void {
247
- this.isTopScrollerVisible = val;
248
- }
249
-
250
- setWikiPageAnchor(anchorKey: string, element: HTMLElement): void {
251
- // do not allow overriding existing anchor
252
- if (!this.wikiPageAnchorIndex.has(anchorKey)) {
253
- this.wikiPageAnchorIndex.set(anchorKey, element);
254
- }
255
- }
256
-
257
- unsetWikiPageAnchor(anchorKey: string): void {
258
- this.wikiPageAnchorIndex.delete(anchorKey);
259
- }
260
-
261
- setWikiPageAnchorToNavigate(
262
- val: DataSpacePageNavigationCommand | undefined,
263
- ): void {
264
- this.wikiPageNavigationCommand = val;
265
- }
266
-
267
- navigateWikiPageAnchor(): void {
83
+ override navigateWikiPageAnchor(): void {
268
84
  if (
269
85
  this.frame &&
270
86
  this.wikiPageNavigationCommand &&
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { action, flow, makeObservable, observable } from 'mobx';
18
+ import {
19
+ ActionState,
20
+ assertErrorThrown,
21
+ LogEvent,
22
+ type GeneratorFn,
23
+ } from '@finos/legend-shared';
24
+ import type { DataSpaceViewerState } from './DataSpaceViewerState.js';
25
+ import { DSL_DATASPACE_EVENT } from '../__lib__/DSL_DataSpace_Event.js';
26
+
27
+ export enum DATA_SPACE_QUALITY_LEVEL {
28
+ DIAMOND = 'DIAMOND',
29
+ PLATINUM = 'PLATINUM',
30
+ GOLD = 'GOLD',
31
+ SILVER = 'SILVER',
32
+ BRONZE = 'BRONZE',
33
+ }
34
+
35
+ // A step-by-step breakdown of every criterion behind the quality rating, so the UI can show
36
+ // users a roadmap of what's already done and what's needed for the next tier.
37
+ export type DataSpaceQualityBreakdown = {
38
+ isDescriptionDocumented: boolean;
39
+ isExecutablesPresent: boolean;
40
+ isModelsDocumentationPresent: boolean;
41
+ isEveryServiceDocumented: boolean;
42
+ attributeCoverage?: number;
43
+ documentedAttributeCount: number;
44
+ totalAttributeCount: number;
45
+ };
46
+
47
+ export type DataSpaceQualityResult = {
48
+ qualityLevel: DATA_SPACE_QUALITY_LEVEL;
49
+ qualityBreakdown: DataSpaceQualityBreakdown;
50
+ };
51
+
52
+ // The actual scoring (description/executables/Models Documentation checks, attribute
53
+ // coverage thresholds) lives server-side — see vendor-data-marketplace's
54
+ // `doc-quality/dataspace` endpoint — since SingleStore already has the dataspace's
55
+ // description and per-attribute documentation ingested for search. This state calls the
56
+ // host app's injected `fetchDataSpaceQuality` action (see DataSpaceViewerState) and stores
57
+ // the result. If the host app didn't wire that action up (e.g. a non-Marketplace consumer
58
+ // of DataSpaceViewerState), or the call fails, qualityLevel/qualityBreakdown stay undefined
59
+ // and the badge simply doesn't render.
60
+ export class DataSpaceQualityState {
61
+ readonly dataSpaceViewerState: DataSpaceViewerState;
62
+ qualityLevel: DATA_SPACE_QUALITY_LEVEL | undefined;
63
+ qualityBreakdown: DataSpaceQualityBreakdown | undefined;
64
+ readonly computingQualityState = ActionState.create();
65
+
66
+ constructor(dataSpaceViewerState: DataSpaceViewerState) {
67
+ makeObservable(this, {
68
+ qualityLevel: observable,
69
+ qualityBreakdown: observable,
70
+ setQualityLevel: action,
71
+ setQualityBreakdown: action,
72
+ computeQuality: flow,
73
+ });
74
+
75
+ this.dataSpaceViewerState = dataSpaceViewerState;
76
+ }
77
+
78
+ setQualityLevel(val: DATA_SPACE_QUALITY_LEVEL | undefined): void {
79
+ this.qualityLevel = val;
80
+ }
81
+
82
+ setQualityBreakdown(val: DataSpaceQualityBreakdown | undefined): void {
83
+ this.qualityBreakdown = val;
84
+ }
85
+
86
+ get isSupported(): boolean {
87
+ return this.dataSpaceViewerState.fetchDataSpaceQuality !== undefined;
88
+ }
89
+
90
+ *computeQuality(): GeneratorFn<void> {
91
+ if (!this.computingQualityState.isInInitialState) {
92
+ return;
93
+ }
94
+ const fetchDataSpaceQuality =
95
+ this.dataSpaceViewerState.fetchDataSpaceQuality;
96
+ if (!fetchDataSpaceQuality) {
97
+ this.computingQualityState.complete(false);
98
+ return;
99
+ }
100
+ this.computingQualityState.inProgress();
101
+ try {
102
+ const result = (yield fetchDataSpaceQuality()) as DataSpaceQualityResult;
103
+ this.setQualityLevel(result.qualityLevel);
104
+ this.setQualityBreakdown(result.qualityBreakdown);
105
+ this.computingQualityState.complete();
106
+ } catch (error) {
107
+ assertErrorThrown(error);
108
+ // A cosmetic badge failing to load isn't worth a user-facing toast — just log it and
109
+ // leave qualityLevel/qualityBreakdown undefined so the badge doesn't render.
110
+ this.dataSpaceViewerState.applicationStore.logService.warn(
111
+ LogEvent.create(DSL_DATASPACE_EVENT.ERROR_FETCH_DATA_SPACE_QUALITY),
112
+ error,
113
+ );
114
+ this.computingQualityState.complete(false);
115
+ }
116
+ }
117
+ }
@@ -30,9 +30,9 @@ export class DataSpaceViewerDiagramViewerState
30
30
  super(
31
31
  dataSpaceViewerState.applicationStore,
32
32
  dataSpaceViewerState.dataSpaceAnalysisResult.diagrams,
33
+ dataSpaceViewerState.layoutState.sectionCollapseState,
33
34
  {
34
35
  queryClass: dataSpaceViewerState.queryClass,
35
- collapseState: dataSpaceViewerState.layoutState.sectionCollapseState,
36
36
  },
37
37
  );
38
38
  this.dataSpaceViewerState = dataSpaceViewerState;
@@ -55,23 +55,25 @@ import {
55
55
  type DataSpaceMappingProviderAccessConfig,
56
56
  DataSpaceMappingProviderAccessState,
57
57
  } from './DataSpaceMappingProviderAccessState.js';
58
+ import {
59
+ DataSpaceQualityState,
60
+ type DataSpaceQualityResult,
61
+ } from './DataSpaceQualityState.js';
62
+ import { BaseViewerState } from '@finos/legend-extension-dsl-data-product';
58
63
 
59
- export class DataSpaceViewerState {
60
- readonly applicationStore: GenericLegendApplicationStore;
64
+ export class DataSpaceViewerState extends BaseViewerState<
65
+ DataSpaceAnalysisResult,
66
+ DataSpaceLayoutState
67
+ > {
61
68
  readonly graphManagerState: GraphManagerState;
62
- readonly layoutState: DataSpaceLayoutState;
63
69
 
64
- readonly dataSpaceAnalysisResult: DataSpaceAnalysisResult;
65
70
  readonly groupId: string;
66
71
  readonly artifactId: string;
67
72
  readonly versionId: string;
68
73
  readonly retrieveGraphData: () => GraphData;
69
- readonly queryDataSpace: (executionContextKey: string) => void;
74
+ readonly queryDataSpace: (executionContextKey: string | undefined) => void;
70
75
  readonly viewProject: (path: string | undefined) => void;
71
76
  readonly viewSDLCProject: (path: string | undefined) => Promise<void>;
72
- readonly onZoneChange?:
73
- | ((zone: NavigationZone | undefined) => void)
74
- | undefined;
75
77
  readonly queryClass: (_class: Class) => void;
76
78
  readonly openServiceQuery: (servicePath: string) => void;
77
79
  readonly onQuickStartTabChange?:
@@ -88,10 +90,14 @@ export class DataSpaceViewerState {
88
90
  readonly mappingProviderAccessConfig?:
89
91
  | DataSpaceMappingProviderAccessConfig
90
92
  | undefined;
93
+ readonly fetchDataSpaceQuality?:
94
+ | (() => Promise<DataSpaceQualityResult>)
95
+ | undefined;
91
96
 
92
97
  readonly diagramViewerState: DataSpaceViewerDiagramViewerState;
93
98
  readonly modelsDocumentationState: DataSpaceViewerModelsDocumentationState;
94
99
  readonly quickStartState: DataSpaceQuickStartState;
100
+ readonly qualityState: DataSpaceQualityState;
95
101
  legendAIConfig: LegendAIConfig;
96
102
  executableStates: DataSpaceViewerExecutableState[] = [];
97
103
 
@@ -119,7 +125,7 @@ export class DataSpaceViewerState {
119
125
  dataSpaceAnalysisResult: DataSpaceAnalysisResult,
120
126
  actions: {
121
127
  retrieveGraphData: () => GraphData;
122
- queryDataSpace: (executionContextKey: string) => void;
128
+ queryDataSpace: (executionContextKey: string | undefined) => void;
123
129
  viewProject: (path: string | undefined) => void;
124
130
  viewSDLCProject: (path: string | undefined) => Promise<void>;
125
131
  queryClass: (_class: Class) => void;
@@ -139,8 +145,21 @@ export class DataSpaceViewerState {
139
145
  mappingProviderAccessConfig?:
140
146
  | DataSpaceMappingProviderAccessConfig
141
147
  | undefined;
148
+ fetchDataSpaceQuality?:
149
+ | (() => Promise<DataSpaceQualityResult>)
150
+ | undefined;
142
151
  },
143
152
  ) {
153
+ super(
154
+ dataSpaceAnalysisResult,
155
+ applicationStore,
156
+ new DataSpaceLayoutState(),
157
+ {
158
+ onZoneChange: actions.onZoneChange,
159
+ },
160
+ );
161
+ this.layoutState.setViewerState(this);
162
+
144
163
  makeObservable(this, {
145
164
  currentActivity: observable,
146
165
  currentExecutionContext: observable,
@@ -157,11 +176,8 @@ export class DataSpaceViewerState {
157
176
  refreshCurrentMappingProviderAccessState: action,
158
177
  });
159
178
 
160
- this.applicationStore = applicationStore;
161
179
  this.graphManagerState = graphManagerState;
162
- this.layoutState = new DataSpaceLayoutState(this);
163
180
 
164
- this.dataSpaceAnalysisResult = dataSpaceAnalysisResult;
165
181
  this.executableStates = this.dataSpaceAnalysisResult.executables.map(
166
182
  (exec) => new DataSpaceViewerExecutableState(this, exec),
167
183
  );
@@ -172,12 +188,12 @@ export class DataSpaceViewerState {
172
188
  this.queryDataSpace = actions.queryDataSpace;
173
189
  this.viewProject = actions.viewProject;
174
190
  this.viewSDLCProject = actions.viewSDLCProject;
175
- this.onZoneChange = actions.onZoneChange;
176
191
  this.queryClass = actions.queryClass;
177
192
  this.openServiceQuery = actions.openServiceQuery;
178
193
  this.onQuickStartTabChange = actions.onQuickStartTabChange;
179
194
  this.viewDataProduct = actions.viewDataProduct;
180
195
  this.mappingProviderAccessConfig = actions.mappingProviderAccessConfig;
196
+ this.fetchDataSpaceQuality = actions.fetchDataSpaceQuality;
181
197
 
182
198
  this.currentExecutionContext =
183
199
  dataSpaceAnalysisResult.defaultExecutionContext ??
@@ -202,10 +218,21 @@ export class DataSpaceViewerState {
202
218
  );
203
219
  this.diagramViewerState = new DataSpaceViewerDiagramViewerState(this);
204
220
  this.quickStartState = new DataSpaceQuickStartState(this);
221
+ this.qualityState = new DataSpaceQualityState(this);
205
222
  this.legendAIConfig = DEFAULT_LEGEND_AI_CONFIG;
206
223
  this.initMappingProviderAccessState();
207
224
  }
208
225
 
226
+ get dataSpaceAnalysisResult(): DataSpaceAnalysisResult {
227
+ return this.product;
228
+ }
229
+
230
+ protected getValidSections(): string[] {
231
+ return DATA_SPACE_WIKI_PAGE_SECTIONS.map((activity) =>
232
+ generateAnchorForActivity(activity),
233
+ );
234
+ }
235
+
209
236
  get isVerified(): boolean {
210
237
  return Boolean(
211
238
  this.dataSpaceAnalysisResult.stereotypes.find(
@@ -216,6 +243,10 @@ export class DataSpaceViewerState {
216
243
  );
217
244
  }
218
245
 
246
+ override get documentationUrl(): string | undefined {
247
+ return this.dataSpaceAnalysisResult.supportInfo?.documentationUrl;
248
+ }
249
+
219
250
  get currentMappingProviderAccessState():
220
251
  | DataSpaceMappingProviderAccessState
221
252
  | undefined {
@@ -305,12 +336,7 @@ export class DataSpaceViewerState {
305
336
  this.currentRuntime = val;
306
337
  }
307
338
 
308
- syncZoneWithNavigation(zone: NavigationZone): void {
309
- this.layoutState.setCurrentNavigationZone(zone);
310
- this.onZoneChange?.(zone);
311
- }
312
-
313
- changeZone(zone: NavigationZone, force = false): void {
339
+ override changeZone(zone: NavigationZone, force = false): void {
314
340
  if (force) {
315
341
  this.layoutState.setCurrentNavigationZone('');
316
342
  }
@@ -211,14 +211,21 @@ export class DataSpaceAdvancedSearchState {
211
211
  new GraphDataWithOrigin(
212
212
  new LegendSDLC(groupId, artifactId, versionId),
213
213
  ),
214
- queryDataSpace: (executionContextKey: string) =>
214
+ queryDataSpace: (executionContextKey: string | undefined) => {
215
+ if (executionContextKey === undefined) {
216
+ this.applicationStore.notificationService.notifyError(
217
+ 'No execution context present on dataspace',
218
+ );
219
+ return;
220
+ }
215
221
  generateDataSpaceQueryCreatorRoute(
216
222
  groupId,
217
223
  artifactId,
218
224
  versionId,
219
225
  analysisResult.path,
220
226
  executionContextKey,
221
- ),
227
+ );
228
+ },
222
229
  viewProject: (path: string | undefined) =>
223
230
  this.viewProject(groupId, artifactId, versionId, path),
224
231
  viewSDLCProject: (path: string | undefined) =>
package/tsconfig.json CHANGED
@@ -88,6 +88,7 @@
88
88
  "./src/stores/DataSpaceLayoutState.ts",
89
89
  "./src/stores/DataSpaceMappingProviderAccessState.ts",
90
90
  "./src/stores/DataSpaceModelsDocumentationState.ts",
91
+ "./src/stores/DataSpaceQualityState.ts",
91
92
  "./src/stores/DataSpaceQuickStartState.ts",
92
93
  "./src/stores/DataSpaceViewerDiagramViewerState.ts",
93
94
  "./src/stores/DataSpaceViewerExecutableState.ts",
@@ -105,6 +106,7 @@
105
106
  "./src/components/DataSpaceLegendAIIntegration.tsx",
106
107
  "./src/components/DataSpaceMarkdownTextViewer.tsx",
107
108
  "./src/components/DataSpacePlaceholder.tsx",
109
+ "./src/components/DataSpaceQualityEmote.tsx",
108
110
  "./src/components/DataSpaceQuickStart.tsx",
109
111
  "./src/components/DataSpaceSupportPanel.tsx",
110
112
  "./src/components/DataSpaceViewer.tsx",