@finos/legend-extension-dsl-data-quality 2.0.11 → 2.0.12

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 (89) hide show
  1. package/lib/__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.d.ts +21 -0
  2. package/lib/__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.d.ts.map +1 -0
  3. package/lib/__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.js +22 -0
  4. package/lib/__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.js.map +1 -0
  5. package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.d.ts +1 -0
  6. package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.d.ts.map +1 -1
  7. package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.js +8 -0
  8. package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.js.map +1 -1
  9. package/lib/components/DataQualityRelationGridResult.d.ts +33 -0
  10. package/lib/components/DataQualityRelationGridResult.d.ts.map +1 -0
  11. package/lib/components/DataQualityRelationGridResult.js +102 -0
  12. package/lib/components/DataQualityRelationGridResult.js.map +1 -0
  13. package/lib/components/DataQualityRelationTrialRuns.d.ts.map +1 -1
  14. package/lib/components/DataQualityRelationTrialRuns.js +20 -4
  15. package/lib/components/DataQualityRelationTrialRuns.js.map +1 -1
  16. package/lib/components/DataQualityRelationValidationConfigurationEditor.d.ts.map +1 -1
  17. package/lib/components/DataQualityRelationValidationConfigurationEditor.js +58 -30
  18. package/lib/components/DataQualityRelationValidationConfigurationEditor.js.map +1 -1
  19. package/lib/components/DataQualityRelationValidationEditor.d.ts.map +1 -1
  20. package/lib/components/DataQualityRelationValidationEditor.js +16 -9
  21. package/lib/components/DataQualityRelationValidationEditor.js.map +1 -1
  22. package/lib/components/DataQualityRelationValidationsEditor.d.ts +7 -0
  23. package/lib/components/DataQualityRelationValidationsEditor.d.ts.map +1 -0
  24. package/lib/components/DataQualityRelationValidationsEditor.js +38 -0
  25. package/lib/components/DataQualityRelationValidationsEditor.js.map +1 -0
  26. package/lib/components/DataQualityResultValues.d.ts +2 -0
  27. package/lib/components/DataQualityResultValues.d.ts.map +1 -1
  28. package/lib/components/DataQualityResultValues.js +8 -2
  29. package/lib/components/DataQualityResultValues.js.map +1 -1
  30. package/lib/components/DataQualityValidationDetailPanel.d.ts +1 -1
  31. package/lib/components/DataQualityValidationDetailPanel.d.ts.map +1 -1
  32. package/lib/components/DataQualityValidationDetailPanel.js +3 -3
  33. package/lib/components/DataQualityValidationDetailPanel.js.map +1 -1
  34. package/lib/components/states/DataQualityRelationResultState.d.ts +8 -0
  35. package/lib/components/states/DataQualityRelationResultState.d.ts.map +1 -1
  36. package/lib/components/states/DataQualityRelationResultState.js +3 -4
  37. package/lib/components/states/DataQualityRelationResultState.js.map +1 -1
  38. package/lib/components/states/DataQualityRelationValidationConfigurationState.d.ts +16 -6
  39. package/lib/components/states/DataQualityRelationValidationConfigurationState.d.ts.map +1 -1
  40. package/lib/components/states/DataQualityRelationValidationConfigurationState.js +126 -14
  41. package/lib/components/states/DataQualityRelationValidationConfigurationState.js.map +1 -1
  42. package/lib/components/states/DataQualityRelationValidationLambdaEditorState.js +1 -1
  43. package/lib/components/states/DataQualityRelationValidationLambdaEditorState.js.map +1 -1
  44. package/lib/components/states/DataQualityRelationValidationState.d.ts.map +1 -1
  45. package/lib/components/states/DataQualityRelationValidationState.js +6 -1
  46. package/lib/components/states/DataQualityRelationValidationState.js.map +1 -1
  47. package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.d.ts +1 -0
  48. package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.d.ts.map +1 -1
  49. package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js.map +1 -1
  50. package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.d.ts +1 -1
  51. package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.d.ts.map +1 -1
  52. package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.js +3 -1
  53. package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.js.map +1 -1
  54. package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.d.ts +1 -0
  55. package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.d.ts.map +1 -1
  56. package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.js +3 -0
  57. package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.js.map +1 -1
  58. package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.d.ts +2 -0
  59. package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.d.ts.map +1 -1
  60. package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.js +2 -0
  61. package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.js.map +1 -1
  62. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.d.ts.map +1 -1
  63. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.js +7 -2
  64. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.js.map +1 -1
  65. package/lib/index.css +2 -2
  66. package/lib/index.css.map +1 -1
  67. package/lib/package.json +1 -1
  68. package/package.json +4 -4
  69. package/src/__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.ts +21 -0
  70. package/src/components/DSL_DataQuality_LegendStudioApplicationPlugin.tsx +9 -0
  71. package/src/components/DataQualityRelationGridResult.tsx +182 -0
  72. package/src/components/DataQualityRelationTrialRuns.tsx +48 -7
  73. package/src/components/DataQualityRelationValidationConfigurationEditor.tsx +207 -73
  74. package/src/components/DataQualityRelationValidationEditor.tsx +53 -27
  75. package/src/components/DataQualityRelationValidationsEditor.tsx +101 -0
  76. package/src/components/DataQualityResultValues.tsx +22 -2
  77. package/src/components/DataQualityValidationDetailPanel.tsx +34 -24
  78. package/src/components/states/DataQualityRelationResultState.ts +19 -3
  79. package/src/components/states/DataQualityRelationValidationConfigurationState.ts +171 -21
  80. package/src/components/states/DataQualityRelationValidationLambdaEditorState.ts +1 -1
  81. package/src/components/states/DataQualityRelationValidationState.ts +9 -0
  82. package/src/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.ts +1 -0
  83. package/src/graph-manager/DSL_DataQuality_GraphModifierHelper.ts +4 -2
  84. package/src/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.ts +3 -0
  85. package/src/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.ts +2 -0
  86. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.ts +7 -2
  87. package/style/_data-quality-relation-validation-builder.scss +34 -9
  88. package/style/_data-quality-validation-builder.scss +34 -0
  89. package/tsconfig.json +3 -0
@@ -26,11 +26,13 @@ import { prettyDuration } from '@finos/legend-shared';
26
26
  import React, { useRef, useState } from 'react';
27
27
  import { DATA_QUALITY_VALIDATION_TEST_ID } from './constants/DataQualityConstants.js';
28
28
  import {
29
+ type SelectOption,
29
30
  BlankPanelContent,
30
31
  CaretDownIcon,
31
32
  ControlledDropdownMenu,
32
33
  CubesLoadingIndicator,
33
34
  CubesLoadingIndicatorIcon,
35
+ CustomSelectorInput,
34
36
  DebugIcon,
35
37
  ExclamationTriangleIcon,
36
38
  MenuContent,
@@ -56,7 +58,9 @@ export const DataQualityRelationTrialRuns = observer(
56
58
  const executionResult = resultState.executionResult;
57
59
 
58
60
  const runQuery = (): void => {
59
- resultState.handleRunValidation();
61
+ if (!resultState.isRunningValidation) {
62
+ resultState.handleRunValidation();
63
+ }
60
64
  };
61
65
 
62
66
  const cancelQuery = applicationStore.guardUnhandledError(() =>
@@ -128,6 +132,25 @@ export const DataQualityRelationTrialRuns = observer(
128
132
  const isLoading =
129
133
  resultState.isRunningValidation || resultState.isGeneratingPlan;
130
134
 
135
+ const selectedValidation = dataQualityRelationValidationConfigurationState
136
+ .resultState.validationToRun
137
+ ? {
138
+ label:
139
+ dataQualityRelationValidationConfigurationState.resultState
140
+ .validationToRun.name,
141
+ value:
142
+ dataQualityRelationValidationConfigurationState.resultState
143
+ .validationToRun,
144
+ }
145
+ : undefined;
146
+
147
+ const onValidationChange = (val: SelectOption | null): void => {
148
+ dataQualityRelationValidationConfigurationState.resetResultState();
149
+ dataQualityRelationValidationConfigurationState.resultState.setValidationToRun(
150
+ val?.value,
151
+ );
152
+ };
153
+
131
154
  return (
132
155
  <div
133
156
  data-testid={
@@ -138,11 +161,6 @@ export const DataQualityRelationTrialRuns = observer(
138
161
  <div className="panel__header">
139
162
  <div className="panel__header__title">
140
163
  <div className="panel__header__title__label">results</div>
141
- {resultState.validationToRun && (
142
- <div className="panel__header__title__label">
143
- {resultState.validationToRun.name}
144
- </div>
145
- )}
146
164
  {resultState.isRunningValidation && (
147
165
  <div className="panel__header__title__label__status">
148
166
  Running Validation...
@@ -168,6 +186,24 @@ export const DataQualityRelationTrialRuns = observer(
168
186
  )}
169
187
  </div>
170
188
  <div className="panel__header__actions data-quality-validation__result__header__actions">
189
+ <div className="data-quality-validation__result__validation">
190
+ <div className="data-quality-validation__result__validation__label">
191
+ Selected Validation
192
+ </div>
193
+ <CustomSelectorInput
194
+ className="data-quality-validation__result__validation__dropdown"
195
+ options={
196
+ dataQualityRelationValidationConfigurationState.validationOptions
197
+ }
198
+ onChange={onValidationChange}
199
+ value={selectedValidation}
200
+ darkMode={
201
+ !applicationStore.layoutService
202
+ .TEMPORARY__isLightColorThemeEnabled
203
+ }
204
+ placeholder={'Select validation to run'}
205
+ />
206
+ </div>
171
207
  <div className="data-quality-validation__result__limit">
172
208
  <div className="data-quality-validation__result__limit__label">
173
209
  preview row limit
@@ -259,7 +295,12 @@ export const DataQualityRelationTrialRuns = observer(
259
295
  )}
260
296
  {executionResult && !isLoading && (
261
297
  <div className="data-quality-validation__result__values">
262
- <DataQualityResultValues executionResult={executionResult} />
298
+ <DataQualityResultValues
299
+ executionResult={executionResult}
300
+ relationValidationConfigurationState={
301
+ dataQualityRelationValidationConfigurationState
302
+ }
303
+ />
263
304
  </div>
264
305
  )}
265
306
  </PanelContent>
@@ -27,39 +27,45 @@ import {
27
27
  } from './states/DataQualityRelationValidationConfigurationState.js';
28
28
  import React, { useCallback, useEffect } from 'react';
29
29
  import {
30
+ BlankPanelContent,
31
+ CaretDownIcon,
30
32
  clsx,
33
+ ControlledDropdownMenu,
31
34
  DragPreviewLayer,
35
+ MenuContent,
36
+ MenuContentItem,
32
37
  Panel,
33
38
  PanelContent,
34
39
  PanelLoadingIndicator,
40
+ PauseCircleIcon,
41
+ PlayIcon,
35
42
  PlusIcon,
36
43
  } from '@finos/legend-art';
37
- import { prettyCONSTName } from '@finos/legend-shared';
38
- import { LambdaEditor } from '@finos/legend-query-builder';
44
+ import { prettyCONSTName, returnUndefOnError } from '@finos/legend-shared';
45
+ import {
46
+ ExecutionPlanViewer,
47
+ LambdaEditor,
48
+ LambdaParameterValuesEditor,
49
+ } from '@finos/legend-query-builder';
39
50
  import {
40
51
  type RawVariableExpression,
41
52
  PrimitiveType,
42
- stub_RawLambda,
43
53
  stub_RawVariableExpression,
44
54
  Type,
55
+ RawExecutionResult,
56
+ extractExecutionResultValues,
57
+ TDSExecutionResult,
45
58
  } from '@finos/legend-graph';
46
59
  import {
60
+ DEFAULT_TAB_SIZE,
47
61
  useApplicationNavigationContext,
48
62
  useApplicationStore,
49
63
  } from '@finos/legend-application';
50
64
  import {
51
65
  dataQualityRelationValidation_addParameter,
52
- dataQualityRelationValidation_addValidation,
53
66
  dataQualityRelationValidation_deleteParameter,
54
- dataQualityRelationValidation_deleteValidation,
55
67
  } from '../graph-manager/DSL_DataQuality_GraphModifierHelper.js';
56
68
  import { flowResult } from 'mobx';
57
- import {
58
- type RelationValidationDragSource,
59
- DataQualityRelationValidationEditor,
60
- RELATION_VALIDATION_DND_TYPE,
61
- } from './DataQualityRelationValidationEditor.js';
62
- import { DataQualityRelationValidation } from '../graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js';
63
69
  import { DataQualityRelationTrialRuns } from './DataQualityRelationTrialRuns.js';
64
70
  import {
65
71
  type FunctionParameterDragSource,
@@ -67,40 +73,25 @@ import {
67
73
  FUNCTION_PARAMETER_DND_TYPE,
68
74
  } from './DataQualityValidationParametersEditor.js';
69
75
  import { useDrop } from 'react-dnd';
76
+ import { DataQualityRelationValidationsEditor } from './DataQualityRelationValidationsEditor.js';
77
+ import { CodeEditor } from '@finos/legend-lego/code-editor';
78
+ import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
79
+ import { DataQualityRelationGridResult } from './DataQualityRelationGridResult.js';
70
80
 
71
81
  const RelationDefinitionEditor = observer(
72
82
  (props: {
73
- dataQualityRelationValidationState: DataQualityRelationValidationConfigurationState;
83
+ dataQualityRelationValidationConfigurationState: DataQualityRelationValidationConfigurationState;
74
84
  }) => {
75
- const { dataQualityRelationValidationState } = props;
85
+ const { dataQualityRelationValidationConfigurationState } = props;
76
86
  const { relationFunctionDefinitionEditorState, resultState } =
77
- dataQualityRelationValidationState;
87
+ dataQualityRelationValidationConfigurationState;
78
88
  const validationElement =
79
- dataQualityRelationValidationState.validationElement;
89
+ dataQualityRelationValidationConfigurationState.validationElement;
90
+ const lambdaExecutionResult =
91
+ dataQualityRelationValidationConfigurationState.executionResult;
80
92
 
81
- const isReadOnly = dataQualityRelationValidationState.isReadOnly;
82
-
83
- const addRelationValidation = (): void => {
84
- const relationValidation = new DataQualityRelationValidation(
85
- '',
86
- stub_RawLambda(),
87
- );
88
- dataQualityRelationValidation_addValidation(
89
- validationElement,
90
- relationValidation,
91
- );
92
- dataQualityRelationValidationState.addValidationState(relationValidation);
93
- };
94
-
95
- const deleteRelationValidation =
96
- (validation: DataQualityRelationValidation): (() => void) =>
97
- (): void => {
98
- dataQualityRelationValidation_deleteValidation(
99
- validationElement,
100
- validation,
101
- );
102
- dataQualityRelationValidationState.deleteValidationState(validation);
103
- };
93
+ const isReadOnly =
94
+ dataQualityRelationValidationConfigurationState.isReadOnly;
104
95
 
105
96
  const addParameter = (): void => {
106
97
  dataQualityRelationValidation_addParameter(
@@ -147,12 +138,55 @@ const RelationDefinitionEditor = observer(
147
138
  [handleDropParameter],
148
139
  );
149
140
 
141
+ const renderFuncResult = (): React.ReactNode => {
142
+ if (lambdaExecutionResult instanceof TDSExecutionResult) {
143
+ return (
144
+ <DataQualityRelationGridResult
145
+ executionResult={lambdaExecutionResult}
146
+ relationValidationConfigurationState={
147
+ dataQualityRelationValidationConfigurationState
148
+ }
149
+ />
150
+ );
151
+ }
152
+ if (lambdaExecutionResult instanceof RawExecutionResult) {
153
+ const val =
154
+ lambdaExecutionResult.value === null
155
+ ? 'null'
156
+ : lambdaExecutionResult.value.toString();
157
+ return (
158
+ <CodeEditor
159
+ language={CODE_EDITOR_LANGUAGE.TEXT}
160
+ inputValue={val}
161
+ isReadOnly={true}
162
+ />
163
+ );
164
+ } else if (lambdaExecutionResult !== undefined) {
165
+ const json =
166
+ returnUndefOnError(() =>
167
+ JSON.stringify(
168
+ extractExecutionResultValues(lambdaExecutionResult),
169
+ null,
170
+ DEFAULT_TAB_SIZE,
171
+ ),
172
+ ) ?? JSON.stringify(lambdaExecutionResult);
173
+ return (
174
+ <CodeEditor
175
+ language={CODE_EDITOR_LANGUAGE.JSON}
176
+ inputValue={json}
177
+ isReadOnly={true}
178
+ />
179
+ );
180
+ }
181
+ return <BlankPanelContent>Lambda Did Not Run</BlankPanelContent>;
182
+ };
183
+
150
184
  return (
151
185
  <>
152
186
  <PanelLoadingIndicator
153
187
  isLoading={
154
188
  resultState.isGeneratingPlan ||
155
- dataQualityRelationValidationState.isRunningFunc
189
+ dataQualityRelationValidationConfigurationState.isRunningValidation
156
190
  }
157
191
  />
158
192
  <div className="relation-validation-config-editor__definition">
@@ -231,43 +265,16 @@ const RelationDefinitionEditor = observer(
231
265
  />
232
266
  </div>
233
267
  </div>
234
- <div className="relation-validation-config-editor__definition__item">
268
+ <div className="relation-validation-config-editor__item">
235
269
  <div className="relation-validation-config-editor__definition__item__header">
236
270
  <div className="relation-validation-config-editor__definition__item__header__title">
237
- VALIDATIONS
271
+ RESULT
238
272
  </div>
239
- <button
240
- className="relation-validation-config-editor__definition__item__header__add-btn btn--dark"
241
- disabled={isReadOnly}
242
- onClick={addRelationValidation}
243
- tabIndex={-1}
244
- title="Add Relation Validation"
245
- >
246
- <PlusIcon />
247
- </button>
248
273
  </div>
249
- <div className="relation-config-validations">
250
- <DragPreviewLayer
251
- labelGetter={(item: RelationValidationDragSource): string =>
252
- item.validation.name === ''
253
- ? '(unknown)'
254
- : item.validation.name
255
- }
256
- types={[RELATION_VALIDATION_DND_TYPE]}
257
- />
258
- {validationElement.validations.map((relationValidation) => (
259
- <DataQualityRelationValidationEditor
260
- key={relationValidation._UUID}
261
- validation={relationValidation}
262
- relationValidationConfigurationState={
263
- dataQualityRelationValidationState
264
- }
265
- deleteValidation={deleteRelationValidation(
266
- relationValidation,
267
- )}
268
- isReadOnly={isReadOnly}
269
- />
270
- ))}
274
+ <div className="relation-validation-config-editor__definition__item__content">
275
+ <div className="relation-validation-config-editor__definition__result-viewer">
276
+ {renderFuncResult()}
277
+ </div>
271
278
  </div>
272
279
  </div>
273
280
  </div>
@@ -293,6 +300,34 @@ export const DataQualityRelationValidationConfigurationEditor = observer(() => {
293
300
  (): void =>
294
301
  dataQualityRelationValidationConfigurationState.setSelectedTab(tab);
295
302
 
303
+ const executionIsRunning =
304
+ dataQualityRelationValidationConfigurationState.isRunningValidation ||
305
+ dataQualityRelationValidationConfigurationState.isGeneratingPlan;
306
+
307
+ const cancelValidation = applicationStore.guardUnhandledError(() =>
308
+ flowResult(
309
+ dataQualityRelationValidationConfigurationState.cancelValidationRun(),
310
+ ),
311
+ );
312
+
313
+ const runValidation = applicationStore.guardUnhandledError(() =>
314
+ flowResult(
315
+ dataQualityRelationValidationConfigurationState.handleRunValidation(),
316
+ ),
317
+ );
318
+
319
+ const generatePlan = applicationStore.guardUnhandledError(() =>
320
+ flowResult(
321
+ dataQualityRelationValidationConfigurationState.generatePlan(false),
322
+ ),
323
+ );
324
+
325
+ const debugPlanGeneration = applicationStore.guardUnhandledError(() =>
326
+ flowResult(
327
+ dataQualityRelationValidationConfigurationState.generatePlan(true),
328
+ ),
329
+ );
330
+
296
331
  useEffect(() => {
297
332
  flowResult(
298
333
  dataQualityRelationValidationConfigurationState.relationFunctionDefinitionEditorState.convertLambdaObjectToGrammarString(
@@ -339,12 +374,82 @@ export const DataQualityRelationValidationConfigurationEditor = observer(() => {
339
374
  ),
340
375
  )}
341
376
  </div>
377
+ <div className="panel__header__actions">
378
+ {selectedTab ===
379
+ DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.DEFINITION && (
380
+ <>
381
+ <div className="btn__dropdown-combo btn__dropdown-combo--primary">
382
+ {dataQualityRelationValidationConfigurationState.isRunningValidation ? (
383
+ <button
384
+ className="btn__dropdown-combo__canceler"
385
+ onClick={cancelValidation}
386
+ tabIndex={-1}
387
+ >
388
+ <div className="btn--dark btn--caution btn__dropdown-combo__canceler__label">
389
+ <PauseCircleIcon className="btn__dropdown-combo__canceler__label__icon" />
390
+ <div className="btn__dropdown-combo__canceler__label__title">
391
+ Stop
392
+ </div>
393
+ </div>
394
+ </button>
395
+ ) : (
396
+ <>
397
+ <button
398
+ className="btn__dropdown-combo__label"
399
+ onClick={runValidation}
400
+ title="Run Function"
401
+ disabled={executionIsRunning}
402
+ tabIndex={-1}
403
+ >
404
+ <PlayIcon className="btn__dropdown-combo__label__icon" />
405
+ <div className="btn__dropdown-combo__label__title">
406
+ Run
407
+ </div>
408
+ </button>
409
+ <ControlledDropdownMenu
410
+ className="btn__dropdown-combo__dropdown-btn"
411
+ disabled={executionIsRunning}
412
+ content={
413
+ <MenuContent>
414
+ <MenuContentItem
415
+ className="btn__dropdown-combo__option"
416
+ onClick={generatePlan}
417
+ >
418
+ Generate Plan
419
+ </MenuContentItem>
420
+ <MenuContentItem
421
+ className="btn__dropdown-combo__option"
422
+ onClick={debugPlanGeneration}
423
+ >
424
+ Debug
425
+ </MenuContentItem>
426
+ </MenuContent>
427
+ }
428
+ menuProps={{
429
+ anchorOrigin: {
430
+ vertical: 'bottom',
431
+ horizontal: 'right',
432
+ },
433
+ transformOrigin: {
434
+ vertical: 'top',
435
+ horizontal: 'right',
436
+ },
437
+ }}
438
+ >
439
+ <CaretDownIcon />
440
+ </ControlledDropdownMenu>
441
+ </>
442
+ )}
443
+ </div>
444
+ </>
445
+ )}
446
+ </div>
342
447
  </div>
343
448
  <PanelContent>
344
449
  {selectedTab ===
345
450
  DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.DEFINITION && (
346
451
  <RelationDefinitionEditor
347
- dataQualityRelationValidationState={
452
+ dataQualityRelationValidationConfigurationState={
348
453
  dataQualityRelationValidationConfigurationState
349
454
  }
350
455
  />
@@ -357,8 +462,37 @@ export const DataQualityRelationValidationConfigurationEditor = observer(() => {
357
462
  }
358
463
  />
359
464
  )}
465
+ {selectedTab ===
466
+ DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.VALIDATIONS && (
467
+ <DataQualityRelationValidationsEditor
468
+ dataQualityRelationValidationConfigurationState={
469
+ dataQualityRelationValidationConfigurationState
470
+ }
471
+ />
472
+ )}
360
473
  </PanelContent>
361
474
  </Panel>
475
+ <ExecutionPlanViewer
476
+ executionPlanState={
477
+ dataQualityRelationValidationConfigurationState.executionPlanState
478
+ }
479
+ />
480
+ {dataQualityRelationValidationConfigurationState.parametersState
481
+ .parameterValuesEditorState.showModal && (
482
+ <LambdaParameterValuesEditor
483
+ graph={
484
+ dataQualityRelationValidationConfigurationState.editorStore
485
+ .graphManagerState.graph
486
+ }
487
+ observerContext={
488
+ dataQualityRelationValidationConfigurationState.editorStore
489
+ .changeDetectionState.observerContext
490
+ }
491
+ lambdaParametersState={
492
+ dataQualityRelationValidationConfigurationState.parametersState
493
+ }
494
+ />
495
+ )}
362
496
  </div>
363
497
  );
364
498
  });
@@ -28,7 +28,6 @@ import {
28
28
  useDragPreviewLayer,
29
29
  } from '@finos/legend-art';
30
30
  import { flowResult } from 'mobx';
31
- import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '@finos/legend-application-studio';
32
31
  import { PrimitiveType } from '@finos/legend-graph';
33
32
  import {
34
33
  ApplicationNavigationContextData,
@@ -47,6 +46,7 @@ import {
47
46
  } from '../graph-manager/DSL_DataQuality_GraphModifierHelper.js';
48
47
  import { DataQualityValidationDetailPanel } from './DataQualityValidationDetailPanel.js';
49
48
  import { useDrag, useDrop } from 'react-dnd';
49
+ import { DSL_DATA_QUALITY_LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../__lib__/studio/DSL_DataQuality_LegendStudioApplicationNavigationContext.js';
50
50
 
51
51
  export type RelationValidationDragSource = {
52
52
  validation: DataQualityRelationValidation;
@@ -72,7 +72,9 @@ export const DataQualityRelationValidationEditor = observer(
72
72
  const applicationStore = useApplicationStore();
73
73
  const hasParserError =
74
74
  relationValidationConfigurationState.validationStates.some(
75
- (state) => state.parserError,
75
+ (state) =>
76
+ Boolean(state.parserError) ||
77
+ Boolean(state.rowMapFunctionLambdaEditorState?.parserError),
76
78
  );
77
79
  const validationState =
78
80
  relationValidationConfigurationState.getValidationState(validation);
@@ -137,12 +139,15 @@ export const DataQualityRelationValidationEditor = observer(
137
139
  useDragPreviewLayer(dragPreviewConnector);
138
140
 
139
141
  // Actions
140
- const onLambdaEditorFocus = (): void =>
142
+ const onLambdaEditorFocus = (isAssertion: boolean): void =>
141
143
  applicationStore.navigationContextService.push(
142
144
  ApplicationNavigationContextData.createTransient(
143
- LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.CLASS_CONTRAINT_LAMBDA_EDITOR,
145
+ isAssertion
146
+ ? DSL_DATA_QUALITY_LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.VALIDATION_ASSERTION_EDITOR
147
+ : DSL_DATA_QUALITY_LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.VALIDATION_ROW_MAP_EDITOR,
144
148
  ),
145
149
  );
150
+
146
151
  const remove = applicationStore.guardUnhandledError(async () => {
147
152
  await flowResult(
148
153
  validationState.convertLambdaObjectToGrammarString({ pretty: false }),
@@ -154,10 +159,15 @@ export const DataQualityRelationValidationEditor = observer(
154
159
  relationValidationConfigurationState.setSelectedTab(
155
160
  DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.TRIAL_RUN,
156
161
  );
157
- relationValidationConfigurationState.resultState.setValidationToRun(
158
- validation,
159
- );
160
- relationValidationConfigurationState.resultState.handleRunValidation();
162
+ if (
163
+ !relationValidationConfigurationState.resultState.isRunningValidation
164
+ ) {
165
+ relationValidationConfigurationState.resetResultState();
166
+ relationValidationConfigurationState.resultState.setValidationToRun(
167
+ validation,
168
+ );
169
+ relationValidationConfigurationState.resultState.handleRunValidation();
170
+ }
161
171
  };
162
172
 
163
173
  const onValidationTypeChange = (val: SelectOption): void => {
@@ -182,7 +192,11 @@ export const DataQualityRelationValidationEditor = observer(
182
192
  >
183
193
  <div
184
194
  className={clsx('relation-validation', {
185
- backdrop__element: validationState.parserError,
195
+ backdrop__element:
196
+ Boolean(validationState.parserError) ||
197
+ Boolean(
198
+ validationState.rowMapFunctionLambdaEditorState?.parserError,
199
+ ),
186
200
  })}
187
201
  >
188
202
  <div className="relation-validation__content">
@@ -225,6 +239,7 @@ export const DataQualityRelationValidationEditor = observer(
225
239
  onClick={runQuery}
226
240
  tabIndex={-1}
227
241
  title="Run Validation"
242
+ disabled={hasParserError}
228
243
  >
229
244
  <RocketIcon />
230
245
  </button>
@@ -238,36 +253,47 @@ export const DataQualityRelationValidationEditor = observer(
238
253
  </button>
239
254
  </div>
240
255
  {validationState.rowMapFunctionLambdaEditorState && (
241
- <div className="uml-element-editor__row-map">
242
- <div className="uml-element-editor__row-map__label">
256
+ <div className="data-quality-uml-element-editor__lambda">
257
+ <div className="data-quality-uml-element-editor__lambda__label">
243
258
  Row Map Function
244
259
  </div>
260
+ <div className="data-quality-uml-element-editor__lambda__value">
261
+ <InlineLambdaEditor
262
+ disabled={
263
+ relationValidationConfigurationState.isConvertingValidationLambdaObjects ||
264
+ isReadOnly
265
+ }
266
+ lambdaEditorState={
267
+ validationState.rowMapFunctionLambdaEditorState
268
+ }
269
+ forceBackdrop={hasParserError}
270
+ expectedType={PrimitiveType.BOOLEAN}
271
+ onEditorFocus={() => onLambdaEditorFocus(false)}
272
+ disablePopUp={true}
273
+ className="relation-validation__lambda"
274
+ />
275
+ </div>
276
+ </div>
277
+ )}
278
+ <div className="data-quality-uml-element-editor__lambda">
279
+ <div className="data-quality-uml-element-editor__lambda__label">
280
+ Assertion
281
+ </div>
282
+ <div className="data-quality-uml-element-editor__lambda__value">
245
283
  <InlineLambdaEditor
246
284
  disabled={
247
285
  relationValidationConfigurationState.isConvertingValidationLambdaObjects ||
248
286
  isReadOnly
249
287
  }
250
- lambdaEditorState={
251
- validationState.rowMapFunctionLambdaEditorState
252
- }
288
+ lambdaEditorState={validationState}
253
289
  forceBackdrop={hasParserError}
254
290
  expectedType={PrimitiveType.BOOLEAN}
255
- onEditorFocus={onLambdaEditorFocus}
291
+ onEditorFocus={() => onLambdaEditorFocus(true)}
256
292
  disablePopUp={true}
293
+ className="relation-validation__lambda"
257
294
  />
258
295
  </div>
259
- )}
260
- <InlineLambdaEditor
261
- disabled={
262
- relationValidationConfigurationState.isConvertingValidationLambdaObjects ||
263
- isReadOnly
264
- }
265
- lambdaEditorState={validationState}
266
- forceBackdrop={hasParserError}
267
- expectedType={PrimitiveType.BOOLEAN}
268
- onEditorFocus={onLambdaEditorFocus}
269
- disablePopUp={true}
270
- />
296
+ </div>
271
297
  </div>
272
298
  {validationState.isValidationDialogOpen && (
273
299
  <DataQualityValidationDetailPanel