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

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 (61) 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/DataSpaceQualityEmote.d.ts +22 -0
  6. package/lib/components/DataSpaceQualityEmote.d.ts.map +1 -0
  7. package/lib/components/DataSpaceQualityEmote.js +133 -0
  8. package/lib/components/DataSpaceQualityEmote.js.map +1 -0
  9. package/lib/components/DataSpaceViewer.d.ts.map +1 -1
  10. package/lib/components/DataSpaceViewer.js +22 -21
  11. package/lib/components/DataSpaceViewer.js.map +1 -1
  12. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.d.ts +2 -0
  13. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.d.ts.map +1 -1
  14. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.js +1 -0
  15. package/lib/components/__test-utils__/DataSpaceViewerTestUtils.js.map +1 -1
  16. package/lib/components/index.d.ts +1 -0
  17. package/lib/components/index.d.ts.map +1 -1
  18. package/lib/components/index.js +1 -0
  19. package/lib/components/index.js.map +1 -1
  20. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.d.ts +2 -1
  21. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.d.ts.map +1 -1
  22. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js +4 -0
  23. package/lib/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js.map +1 -1
  24. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.d.ts.map +1 -1
  25. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.js +5 -1
  26. package/lib/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.js.map +1 -1
  27. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.d.ts.map +1 -1
  28. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.js +39 -1
  29. package/lib/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.js.map +1 -1
  30. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.d.ts +2 -1
  31. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.d.ts.map +1 -1
  32. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.js +4 -0
  33. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.js.map +1 -1
  34. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.d.ts.map +1 -1
  35. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.js +6 -4
  36. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.js.map +1 -1
  37. package/lib/index.css +2 -2
  38. package/lib/index.css.map +1 -1
  39. package/lib/package.json +1 -1
  40. package/lib/stores/DataSpaceQualityState.d.ts +49 -0
  41. package/lib/stores/DataSpaceQualityState.d.ts.map +1 -0
  42. package/lib/stores/DataSpaceQualityState.js +84 -0
  43. package/lib/stores/DataSpaceQualityState.js.map +1 -0
  44. package/lib/stores/DataSpaceViewerState.d.ts +4 -0
  45. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  46. package/lib/stores/DataSpaceViewerState.js +5 -0
  47. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  48. package/package.json +14 -14
  49. package/src/__lib__/DSL_DataSpace_Event.ts +1 -0
  50. package/src/components/DataSpaceQualityEmote.tsx +223 -0
  51. package/src/components/DataSpaceViewer.tsx +117 -111
  52. package/src/components/__test-utils__/DataSpaceViewerTestUtils.ts +3 -0
  53. package/src/components/index.ts +5 -0
  54. package/src/graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.ts +5 -0
  55. package/src/graph-manager/action/changeDetection/DSL_DataSpace_ObserverHelper.ts +6 -0
  56. package/src/graph-manager/protocol/pure/DSL_DataSpace_PureProtocolProcessorPlugin.ts +56 -0
  57. package/src/graph-manager/protocol/pure/v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.ts +5 -0
  58. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.ts +6 -3
  59. package/src/stores/DataSpaceQualityState.ts +117 -0
  60. package/src/stores/DataSpaceViewerState.ts +13 -0
  61. package/tsconfig.json +2 -0
@@ -45,6 +45,7 @@ import { useApplicationStore } from '@finos/legend-application';
45
45
  import { DataSpaceLegendAIIntegration } from './DataSpaceLegendAIIntegration.js';
46
46
  import { DSL_DATASPACE_EVENT } from '../__lib__/DSL_DataSpace_Event.js';
47
47
  import { guaranteeNonNullable } from '@finos/legend-shared';
48
+ import { DataSpaceQualityEmote } from './DataSpaceQualityEmote.js';
48
49
 
49
50
  const DataSpaceHeader = observer(
50
51
  (props: {
@@ -91,128 +92,133 @@ const DataSpaceHeader = observer(
91
92
  </div>
92
93
  )}
93
94
  </div>
94
- <div className="data-space__viewer__header__actions">
95
- {dataSpaceViewerState.currentExecutionContext && (
95
+ <div className="data-space__viewer__header__actions-group">
96
+ <DataSpaceQualityEmote
97
+ qualityState={dataSpaceViewerState.qualityState}
98
+ />
99
+ <div className="data-space__viewer__header__actions">
100
+ {dataSpaceViewerState.currentExecutionContext && (
101
+ <ControlledDropdownMenu
102
+ className="data-space__viewer__header__execution-context-selector"
103
+ menuProps={{
104
+ anchorOrigin: { vertical: 'bottom', horizontal: 'center' },
105
+ transformOrigin: { vertical: 'top', horizontal: 'center' },
106
+ elevation: 7,
107
+ }}
108
+ title={`Current Execution Context: ${dataSpaceViewerState.currentExecutionContext.name}\nClick to switch`}
109
+ content={
110
+ <MenuContent>
111
+ {Array.from(
112
+ dataSpaceViewerState.dataSpaceAnalysisResult.executionContextsIndex.values(),
113
+ ).map((context) => (
114
+ <MenuContentItem
115
+ key={context.name}
116
+ className={clsx(
117
+ 'data-space__viewer__header__execution-context-selector__option',
118
+ {
119
+ 'data-space__viewer__header__execution-context-selector__option--active':
120
+ context ===
121
+ dataSpaceViewerState.currentExecutionContext,
122
+ },
123
+ )}
124
+ onClick={() =>
125
+ dataSpaceViewerState.setCurrentExecutionContext(
126
+ context,
127
+ )
128
+ }
129
+ >
130
+ {context.name}
131
+ </MenuContentItem>
132
+ ))}
133
+ </MenuContent>
134
+ }
135
+ >
136
+ <div className="data-space__viewer__header__execution-context-selector__trigger">
137
+ <div className="data-space__viewer__header__execution-context-selector__trigger__icon">
138
+ <PlayIcon />
139
+ </div>
140
+ <div className="data-space__viewer__header__execution-context-selector__trigger__label">
141
+ {dataSpaceViewerState.currentExecutionContext.name}
142
+ </div>
143
+ <div className="data-space__viewer__header__execution-context-selector__trigger__dropdown-icon">
144
+ <CaretDownIcon />
145
+ </div>
146
+ </div>
147
+ </ControlledDropdownMenu>
148
+ )}
96
149
  <ControlledDropdownMenu
97
- className="data-space__viewer__header__execution-context-selector"
150
+ className="data-space__viewer__header__actions-selector"
98
151
  menuProps={{
99
- anchorOrigin: { vertical: 'bottom', horizontal: 'center' },
100
- transformOrigin: { vertical: 'top', horizontal: 'center' },
152
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
153
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
101
154
  elevation: 7,
102
155
  }}
103
- title={`Current Execution Context: ${dataSpaceViewerState.currentExecutionContext.name}\nClick to switch`}
156
+ title="More Actions..."
104
157
  content={
105
158
  <MenuContent>
106
- {Array.from(
107
- dataSpaceViewerState.dataSpaceAnalysisResult.executionContextsIndex.values(),
108
- ).map((context) => (
109
- <MenuContentItem
110
- key={context.name}
111
- className={clsx(
112
- 'data-space__viewer__header__execution-context-selector__option',
113
- {
114
- 'data-space__viewer__header__execution-context-selector__option--active':
115
- context ===
116
- dataSpaceViewerState.currentExecutionContext,
117
- },
118
- )}
119
- onClick={() =>
120
- dataSpaceViewerState.setCurrentExecutionContext(
121
- context,
122
- )
159
+ {dataSpaceViewerState.currentExecutionContext && (
160
+ <>
161
+ <MenuContentItem
162
+ onClick={() =>
163
+ dataSpaceViewerState.queryDataSpace(
164
+ guaranteeNonNullable(
165
+ dataSpaceViewerState.currentExecutionContext,
166
+ ).name,
167
+ )
168
+ }
169
+ >
170
+ Query Data Space
171
+ </MenuContentItem>
172
+ <MenuContentDivider />
173
+ </>
174
+ )}
175
+ <MenuContentItem
176
+ onClick={() =>
177
+ dataSpaceViewerState.viewProject(analysisResult.path)
178
+ }
179
+ >
180
+ View Project
181
+ </MenuContentItem>
182
+ <MenuContentItem
183
+ onClick={() => {
184
+ dataSpaceViewerState
185
+ .viewSDLCProject(analysisResult.path)
186
+ .catch(applicationStore.alertUnhandledError);
187
+ }}
188
+ >
189
+ View SDLC Project
190
+ </MenuContentItem>
191
+ <MenuContentDivider />
192
+ <MenuContentItem
193
+ onClick={() => {
194
+ const documentationUrl =
195
+ analysisResult.supportInfo?.documentationUrl;
196
+ if (documentationUrl) {
197
+ applicationStore.navigationService.navigator.visitAddress(
198
+ documentationUrl,
199
+ );
123
200
  }
124
- >
125
- {context.name}
126
- </MenuContentItem>
127
- ))}
201
+ }}
202
+ >
203
+ Read Documentation
204
+ </MenuContentItem>
205
+ <MenuContentItem
206
+ onClick={() =>
207
+ dataSpaceViewerState.changeZone(
208
+ generateAnchorForActivity(
209
+ DATA_SPACE_VIEWER_ACTIVITY_MODE.SUPPORT,
210
+ ),
211
+ )
212
+ }
213
+ >
214
+ Get Help
215
+ </MenuContentItem>
128
216
  </MenuContent>
129
217
  }
130
218
  >
131
- <div className="data-space__viewer__header__execution-context-selector__trigger">
132
- <div className="data-space__viewer__header__execution-context-selector__trigger__icon">
133
- <PlayIcon />
134
- </div>
135
- <div className="data-space__viewer__header__execution-context-selector__trigger__label">
136
- {dataSpaceViewerState.currentExecutionContext.name}
137
- </div>
138
- <div className="data-space__viewer__header__execution-context-selector__trigger__dropdown-icon">
139
- <CaretDownIcon />
140
- </div>
141
- </div>
219
+ <MoreVerticalIcon />
142
220
  </ControlledDropdownMenu>
143
- )}
144
- <ControlledDropdownMenu
145
- className="data-space__viewer__header__actions-selector"
146
- menuProps={{
147
- anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
148
- transformOrigin: { vertical: 'top', horizontal: 'right' },
149
- elevation: 7,
150
- }}
151
- title="More Actions..."
152
- content={
153
- <MenuContent>
154
- {dataSpaceViewerState.currentExecutionContext && (
155
- <>
156
- <MenuContentItem
157
- onClick={() =>
158
- dataSpaceViewerState.queryDataSpace(
159
- guaranteeNonNullable(
160
- dataSpaceViewerState.currentExecutionContext,
161
- ).name,
162
- )
163
- }
164
- >
165
- Query Data Space
166
- </MenuContentItem>
167
- <MenuContentDivider />
168
- </>
169
- )}
170
- <MenuContentItem
171
- onClick={() =>
172
- dataSpaceViewerState.viewProject(analysisResult.path)
173
- }
174
- >
175
- View Project
176
- </MenuContentItem>
177
- <MenuContentItem
178
- onClick={() => {
179
- dataSpaceViewerState
180
- .viewSDLCProject(analysisResult.path)
181
- .catch(applicationStore.alertUnhandledError);
182
- }}
183
- >
184
- View SDLC Project
185
- </MenuContentItem>
186
- <MenuContentDivider />
187
- <MenuContentItem
188
- onClick={() => {
189
- const documentationUrl =
190
- analysisResult.supportInfo?.documentationUrl;
191
- if (documentationUrl) {
192
- applicationStore.navigationService.navigator.visitAddress(
193
- documentationUrl,
194
- );
195
- }
196
- }}
197
- >
198
- Read Documentation
199
- </MenuContentItem>
200
- <MenuContentItem
201
- onClick={() =>
202
- dataSpaceViewerState.changeZone(
203
- generateAnchorForActivity(
204
- DATA_SPACE_VIEWER_ACTIVITY_MODE.SUPPORT,
205
- ),
206
- )
207
- }
208
- >
209
- Get Help
210
- </MenuContentItem>
211
- </MenuContent>
212
- }
213
- >
214
- <MoreVerticalIcon />
215
- </ControlledDropdownMenu>
221
+ </div>
216
222
  </div>
217
223
  </div>
218
224
  </div>
@@ -40,6 +40,7 @@ import {
40
40
  DSL_DataSpace_getGraphManagerExtension,
41
41
  } from '../../graph-manager/index.js';
42
42
  import { DataSpaceViewerState } from '../../stores/DataSpaceViewerState.js';
43
+ import type { DataSpaceQualityResult } from '../../stores/DataSpaceQualityState.js';
43
44
 
44
45
  class TEST__LegendApplicationPluginManager
45
46
  extends LegendApplicationPluginManager<LegendApplicationPlugin>
@@ -113,6 +114,7 @@ export type TEST__DataSpaceViewerActionOverrides = {
113
114
  dataProductPath: string,
114
115
  ) => void)
115
116
  | undefined;
117
+ fetchDataSpaceQuality?: (() => Promise<DataSpaceQualityResult>) | undefined;
116
118
  };
117
119
 
118
120
  /**
@@ -182,6 +184,7 @@ export const TEST__getDataSpaceViewerState = async (
182
184
  queryClass: () => undefined,
183
185
  openServiceQuery: () => undefined,
184
186
  viewDataProduct: overrides?.viewDataProduct,
187
+ fetchDataSpaceQuality: overrides?.fetchDataSpaceQuality,
185
188
  },
186
189
  );
187
190
  return { viewerState, applicationStore };
@@ -22,6 +22,11 @@ export { DSL_DataSpace_LegendApplicationPlugin } from './DSL_DataSpace_LegendApp
22
22
  export { DataSpaceViewer } from './DataSpaceViewer.js';
23
23
  export * from '../stores/DSL_DataSpace_LegendApplicationPlugin_Extension.js';
24
24
  export { DataSpaceViewerState } from '../stores/DataSpaceViewerState.js';
25
+ export {
26
+ DATA_SPACE_QUALITY_LEVEL,
27
+ type DataSpaceQualityBreakdown,
28
+ type DataSpaceQualityResult,
29
+ } from '../stores/DataSpaceQualityState.js';
25
30
  export {
26
31
  DataSpaceQueryBuilderState,
27
32
  resolveUsableDataSpaceClasses,
@@ -27,6 +27,7 @@ import {
27
27
  type RawLambda,
28
28
  type DataElementReference,
29
29
  type OperationalMetadata,
30
+ type RelationElement,
30
31
  PackageableElement,
31
32
  ConcreteFunctionDefinition,
32
33
  generateFunctionPrettyName,
@@ -90,6 +91,7 @@ export abstract class DataSpaceExecutable implements Hashable {
90
91
  executionContextKey?: string | undefined;
91
92
  title!: string;
92
93
  description?: string | undefined;
94
+ sampleValues?: RelationElement | undefined;
93
95
 
94
96
  get hashCode(): string {
95
97
  return hashArray([
@@ -98,6 +100,7 @@ export abstract class DataSpaceExecutable implements Hashable {
98
100
  this.title,
99
101
  this.description ?? '',
100
102
  this.executionContextKey ?? '',
103
+ this.sampleValues ?? '',
101
104
  ]);
102
105
  }
103
106
  }
@@ -115,6 +118,7 @@ export class DataSpacePackageableElementExecutable
115
118
  this.title,
116
119
  this.description ?? '',
117
120
  this.executionContextKey ?? '',
121
+ this.sampleValues ?? '',
118
122
  this.executable.value instanceof ConcreteFunctionDefinition
119
123
  ? generateFunctionPrettyName(this.executable.value, {
120
124
  fullPath: true,
@@ -140,6 +144,7 @@ export class DataSpaceExecutableTemplate
140
144
  this.description ?? '',
141
145
  this.query,
142
146
  this.executionContextKey ?? '',
147
+ this.sampleValues ?? '',
143
148
  ]);
144
149
  }
145
150
  }
@@ -20,6 +20,7 @@ import {
20
20
  type OperationalMetadata,
21
21
  observe_PackageableElementReference,
22
22
  observe_RawLambda,
23
+ observe_RelationElement,
23
24
  observe_StereotypeReference,
24
25
  observe_TaggedValue,
25
26
  skipObserved,
@@ -109,7 +110,12 @@ const observe_Abstract_DataSpaceExecutable = (
109
110
  executionContextKey: observable,
110
111
  title: observable,
111
112
  description: observable,
113
+ sampleValues: observable,
112
114
  });
115
+
116
+ if (metamodel.sampleValues) {
117
+ observe_RelationElement(metamodel.sampleValues);
118
+ }
113
119
  };
114
120
 
115
121
  const observe_DataSpacePackageableElementExecutable = skipObserved(
@@ -123,6 +123,10 @@ import {
123
123
  QueryDataSpaceExecutionContextInfo,
124
124
  generateFunctionPrettyName,
125
125
  ConcreteFunctionDefinition,
126
+ V1_RelationElement,
127
+ V1_RelationRowTestData,
128
+ RelationElement,
129
+ RelationRowTestData,
126
130
  } from '@finos/legend-graph';
127
131
  import { V1_resolveDiagram } from '@finos/legend-extension-dsl-diagram/graph';
128
132
  import { V1_MappingIncludeDataSpace } from './v1/model/packageableElements/mapping/V1_DSL_DataSpace_MappingIncludeDataSpace.js';
@@ -239,6 +243,34 @@ export const V1_transformDataSpaceSupportFullInfo = (
239
243
  return fullInfo;
240
244
  };
241
245
 
246
+ const V1_buildDataSpaceExecutableSampleValues = (
247
+ protocol: V1_RelationElement,
248
+ ): RelationElement => {
249
+ const sampleValues = new RelationElement();
250
+ sampleValues.columns = protocol.columns;
251
+ sampleValues.paths = protocol.paths;
252
+ sampleValues.rows = protocol.rows.map((row) => {
253
+ const rowData = new RelationRowTestData();
254
+ rowData.values = row.values;
255
+ return rowData;
256
+ });
257
+ return sampleValues;
258
+ };
259
+
260
+ const V1_transformDataSpaceExecutableSampleValues = (
261
+ metamodel: RelationElement,
262
+ ): V1_RelationElement => {
263
+ const sampleValues = new V1_RelationElement();
264
+ sampleValues.columns = metamodel.columns;
265
+ sampleValues.paths = metamodel.paths;
266
+ sampleValues.rows = metamodel.rows.map((row) => {
267
+ const rowData = new V1_RelationRowTestData();
268
+ rowData.values = row.values;
269
+ return rowData;
270
+ });
271
+ return sampleValues;
272
+ };
273
+
242
274
  export class DSL_DataSpace_PureProtocolProcessorPlugin
243
275
  extends PureProtocolProcessorPlugin
244
276
  implements DSL_Mapping_PureProtocolProcessorPlugin_Extension
@@ -384,6 +416,12 @@ export class DSL_DataSpace_PureProtocolProcessorPlugin
384
416
  executable.executionContextKey =
385
417
  executableProtocol.executionContextKey;
386
418
  }
419
+ if (executableProtocol.sampleValues) {
420
+ executable.sampleValues =
421
+ V1_buildDataSpaceExecutableSampleValues(
422
+ executableProtocol.sampleValues,
423
+ );
424
+ }
387
425
  return executable;
388
426
  } else if (
389
427
  executableProtocol instanceof
@@ -400,6 +438,12 @@ export class DSL_DataSpace_PureProtocolProcessorPlugin
400
438
  executable.executionContextKey =
401
439
  executableProtocol.executionContextKey;
402
440
  }
441
+ if (executableProtocol.sampleValues) {
442
+ executable.sampleValues =
443
+ V1_buildDataSpaceExecutableSampleValues(
444
+ executableProtocol.sampleValues,
445
+ );
446
+ }
403
447
  try {
404
448
  executable.executable = context.resolveElement(
405
449
  executableProtocol.executable.path,
@@ -641,6 +685,12 @@ export class DSL_DataSpace_PureProtocolProcessorPlugin
641
685
  executable.query.accept_RawValueSpecificationVisitor(
642
686
  new V1_RawValueSpecificationTransformer(context),
643
687
  ) as V1_RawLambda;
688
+ if (executable.sampleValues) {
689
+ executableProtocol.sampleValues =
690
+ V1_transformDataSpaceExecutableSampleValues(
691
+ executable.sampleValues,
692
+ );
693
+ }
644
694
  return executableProtocol;
645
695
  } else if (
646
696
  executable instanceof DataSpacePackageableElementExecutable
@@ -656,6 +706,12 @@ export class DSL_DataSpace_PureProtocolProcessorPlugin
656
706
  executableProtocol.executionContextKey =
657
707
  executable.executionContextKey;
658
708
  }
709
+ if (executable.sampleValues) {
710
+ executableProtocol.sampleValues =
711
+ V1_transformDataSpaceExecutableSampleValues(
712
+ executable.sampleValues,
713
+ );
714
+ }
659
715
  if (
660
716
  executable.executable.value instanceof
661
717
  ConcreteFunctionDefinition
@@ -25,6 +25,7 @@ import {
25
25
  type V1_DataProductOperationalMetadata,
26
26
  V1_PackageableElement,
27
27
  type V1_DataElementReference,
28
+ type V1_RelationElement,
28
29
  } from '@finos/legend-graph';
29
30
 
30
31
  export class V1_DataSpaceMappingProvider implements Hashable {
@@ -81,6 +82,7 @@ export abstract class V1_DataSpaceExecutable implements Hashable {
81
82
  executionContextKey?: string | undefined;
82
83
  title!: string;
83
84
  description?: string | undefined;
85
+ sampleValues?: V1_RelationElement | undefined;
84
86
 
85
87
  get hashCode(): string {
86
88
  return hashArray([
@@ -89,6 +91,7 @@ export abstract class V1_DataSpaceExecutable implements Hashable {
89
91
  this.title,
90
92
  this.description ?? '',
91
93
  this.executionContextKey ?? '',
94
+ this.sampleValues ?? '',
92
95
  ]);
93
96
  }
94
97
  }
@@ -106,6 +109,7 @@ export class V1_DataSpacePackageableElementExecutable
106
109
  this.title,
107
110
  this.description ?? '',
108
111
  this.executionContextKey ?? '',
112
+ this.sampleValues ?? '',
109
113
  this.executable.path,
110
114
  ]);
111
115
  }
@@ -125,6 +129,7 @@ export class V1_DataSpaceTemplateExecutable
125
129
  this.description ?? '',
126
130
  this.query,
127
131
  this.executionContextKey ?? '',
132
+ this.sampleValues ?? '',
128
133
  ]);
129
134
  }
130
135
  }
@@ -33,6 +33,7 @@ import {
33
33
  V1_rawLambdaModelSchema,
34
34
  V1_dataElementReferenceModelSchema,
35
35
  V1_DataProductOperationalMetadata,
36
+ V1_relationElementModelSchema,
36
37
  } from '@finos/legend-graph';
37
38
  import {
38
39
  type PlainObject,
@@ -205,10 +206,11 @@ const V1_dataSpacePackageableElementExecutableModelSchema = createModelSchema(
205
206
  V1_DATA_SPACE_PACKAGEABLE_ELEMENT_EXECUTABLE,
206
207
  ),
207
208
  description: optional(primitive()),
209
+ executable: usingModelSchema(V1_packageableElementPointerModelSchema),
208
210
  executionContextKey: optional(primitive()),
209
211
  id: optional(primitive()),
212
+ sampleValues: optional(usingModelSchema(V1_relationElementModelSchema)),
210
213
  title: primitive(),
211
- executable: usingModelSchema(V1_packageableElementPointerModelSchema),
212
214
  },
213
215
  );
214
216
 
@@ -217,10 +219,11 @@ const V1_dataSpaceTemplateExecutableModelSchema = createModelSchema(
217
219
  {
218
220
  _type: usingConstantValueSchema(V1_DATA_SPACE_TEMPLATE_EXECUTABLE),
219
221
  description: optional(primitive()),
220
- title: primitive(),
222
+ executionContextKey: optional(primitive()),
221
223
  id: primitive(),
222
224
  query: usingModelSchema(V1_rawLambdaModelSchema),
223
- executionContextKey: optional(primitive()),
225
+ sampleValues: optional(usingModelSchema(V1_relationElementModelSchema)),
226
+ title: primitive(),
224
227
  },
225
228
  );
226
229
 
@@ -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
+ }