@finos/legend-extension-dsl-data-quality 2.1.34 → 2.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.d.ts.map +1 -1
- package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.js +45 -13
- package/lib/components/DSL_DataQuality_LegendStudioApplicationPlugin.js.map +1 -1
- package/lib/components/DataQualityCustomSelector.d.ts +16 -1
- package/lib/components/DataQualityCustomSelector.d.ts.map +1 -1
- package/lib/components/DataQualityCustomSelector.js +29 -4
- package/lib/components/DataQualityCustomSelector.js.map +1 -1
- package/lib/components/DataQualityRelationComparisonEditor.d.ts +19 -0
- package/lib/components/DataQualityRelationComparisonEditor.d.ts.map +1 -0
- package/lib/components/DataQualityRelationComparisonEditor.js +239 -0
- package/lib/components/DataQualityRelationComparisonEditor.js.map +1 -0
- package/lib/components/DataQualityRelationGridResult.d.ts +3 -0
- package/lib/components/DataQualityRelationGridResult.d.ts.map +1 -1
- package/lib/components/DataQualityRelationGridResult.js +1 -1
- package/lib/components/DataQualityRelationGridResult.js.map +1 -1
- package/lib/components/DataQualityRelationLambdaGUIDataTypeHandlers.d.ts +0 -10
- package/lib/components/DataQualityRelationLambdaGUIDataTypeHandlers.d.ts.map +1 -1
- package/lib/components/DataQualityRelationLambdaGUIDataTypeHandlers.js +11 -24
- package/lib/components/DataQualityRelationLambdaGUIDataTypeHandlers.js.map +1 -1
- package/lib/components/DataQualityRelationLambdaGUIValidationEditor.d.ts.map +1 -1
- package/lib/components/DataQualityRelationLambdaGUIValidationEditor.js +6 -4
- package/lib/components/DataQualityRelationLambdaGUIValidationEditor.js.map +1 -1
- package/lib/components/states/DataQualityRelationComparisonConfigurationState.d.ts +111 -0
- package/lib/components/states/DataQualityRelationComparisonConfigurationState.d.ts.map +1 -0
- package/lib/components/states/DataQualityRelationComparisonConfigurationState.js +495 -0
- package/lib/components/states/DataQualityRelationComparisonConfigurationState.js.map +1 -0
- package/lib/data-quality-custom-selector.css +2 -2
- package/lib/data-quality-custom-selector.css.map +1 -1
- package/lib/graph/metamodel/DSL_DataQuality_HashUtils.d.ts +3 -1
- package/lib/graph/metamodel/DSL_DataQuality_HashUtils.d.ts.map +1 -1
- package/lib/graph/metamodel/DSL_DataQuality_HashUtils.js +2 -0
- package/lib/graph/metamodel/DSL_DataQuality_HashUtils.js.map +1 -1
- package/lib/graph/metamodel/DSL_DataQuality_PureGraphPlugin.d.ts.map +1 -1
- package/lib/graph/metamodel/DSL_DataQuality_PureGraphPlugin.js +2 -1
- package/lib/graph/metamodel/DSL_DataQuality_PureGraphPlugin.js.map +1 -1
- package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.d.ts +35 -0
- package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.d.ts.map +1 -1
- package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js +37 -0
- package/lib/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_GraphManagerHelper.d.ts +2 -1
- package/lib/graph-manager/DSL_DataQuality_GraphManagerHelper.d.ts.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_GraphManagerHelper.js +2 -1
- package/lib/graph-manager/DSL_DataQuality_GraphManagerHelper.js.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.d.ts +7 -1
- package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.d.ts.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.js +18 -0
- package/lib/graph-manager/DSL_DataQuality_GraphModifierHelper.js.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_PureGraphManagerPlugin.d.ts.map +1 -1
- package/lib/graph-manager/DSL_DataQuality_PureGraphManagerPlugin.js +5 -2
- package/lib/graph-manager/DSL_DataQuality_PureGraphManagerPlugin.js.map +1 -1
- package/lib/graph-manager/action/changeDetection/DSL_DataQuality_ObserverHelper.d.ts +3 -1
- package/lib/graph-manager/action/changeDetection/DSL_DataQuality_ObserverHelper.d.ts.map +1 -1
- package/lib/graph-manager/action/changeDetection/DSL_DataQuality_ObserverHelper.js +28 -1
- package/lib/graph-manager/action/changeDetection/DSL_DataQuality_ObserverHelper.js.map +1 -1
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureGraphManagerExtension.d.ts +4 -1
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureGraphManagerExtension.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureGraphManagerExtension.js.map +1 -1
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureProtocolProcessorPlugin.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureProtocolProcessorPlugin.js +33 -5
- package/lib/graph-manager/protocol/pure/DSL_DataQuality_PureProtocolProcessorPlugin.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.d.ts +26 -2
- package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.js +107 -3
- package/lib/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.d.ts +19 -0
- package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.js +37 -0
- package/lib/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationBuilderHelper.d.ts +2 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationBuilderHelper.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationBuilderHelper.js +26 -3
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationBuilderHelper.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationTransformer.d.ts +3 -2
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationTransformer.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationTransformer.js +29 -2
- package/lib/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationTransformer.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.d.ts +4 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.js +37 -2
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/package.json +7 -7
- package/src/components/DSL_DataQuality_LegendStudioApplicationPlugin.tsx +64 -12
- package/src/components/DataQualityCustomSelector.tsx +111 -6
- package/src/components/DataQualityRelationComparisonEditor.tsx +795 -0
- package/src/components/DataQualityRelationGridResult.tsx +1 -1
- package/src/components/DataQualityRelationLambdaGUIDataTypeHandlers.tsx +9 -87
- package/src/components/DataQualityRelationLambdaGUIValidationEditor.tsx +16 -6
- package/src/components/states/DataQualityRelationComparisonConfigurationState.ts +747 -0
- package/src/graph/metamodel/DSL_DataQuality_HashUtils.ts +2 -0
- package/src/graph/metamodel/DSL_DataQuality_PureGraphPlugin.ts +2 -0
- package/src/graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.ts +66 -0
- package/src/graph-manager/DSL_DataQuality_GraphManagerHelper.ts +13 -0
- package/src/graph-manager/DSL_DataQuality_GraphModifierHelper.ts +57 -0
- package/src/graph-manager/DSL_DataQuality_PureGraphManagerPlugin.ts +8 -0
- package/src/graph-manager/action/changeDetection/DSL_DataQuality_ObserverHelper.ts +42 -0
- package/src/graph-manager/protocol/pure/DSL_DataQuality_PureGraphManagerExtension.ts +16 -0
- package/src/graph-manager/protocol/pure/DSL_DataQuality_PureProtocolProcessorPlugin.ts +65 -0
- package/src/graph-manager/protocol/pure/v1/V1_DSL_Data_Quality_PureGraphManagerExtension.ts +171 -1
- package/src/graph-manager/protocol/pure/v1/V1_DataQualityValidationConfiguration.ts +49 -0
- package/src/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationBuilderHelper.ts +39 -0
- package/src/graph-manager/protocol/pure/v1/transformation/V1_DSL_DataQuality_ValueSpecificationTransformer.ts +50 -0
- package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_DSL_DataQuality_ProtocolHelper.ts +71 -0
- package/style/_data-quality-relation-comparison-editor.scss +361 -0
- package/style/data-quality-custom-selector.scss +23 -0
- package/style/index.scss +74 -0
- package/tsconfig.json +2 -0
|
@@ -0,0 +1,795 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-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 { observer } from 'mobx-react-lite';
|
|
18
|
+
import React, { useEffect, useMemo } from 'react';
|
|
19
|
+
import {
|
|
20
|
+
BlankPanelContent,
|
|
21
|
+
CaretDownIcon,
|
|
22
|
+
clsx,
|
|
23
|
+
ControlledDropdownMenu,
|
|
24
|
+
CustomSelectorInput,
|
|
25
|
+
Dialog,
|
|
26
|
+
ExclamationTriangleIcon,
|
|
27
|
+
MenuContent,
|
|
28
|
+
MenuContentItem,
|
|
29
|
+
Modal,
|
|
30
|
+
ModalBody,
|
|
31
|
+
ModalFooter,
|
|
32
|
+
ModalFooterButton,
|
|
33
|
+
ModalFooterStatus,
|
|
34
|
+
ModalHeader,
|
|
35
|
+
Panel,
|
|
36
|
+
PanelContent,
|
|
37
|
+
PanelFormBooleanField,
|
|
38
|
+
PanelFormSection,
|
|
39
|
+
PanelLoadingIndicator,
|
|
40
|
+
PauseCircleIcon,
|
|
41
|
+
PlayIcon,
|
|
42
|
+
RefreshIcon,
|
|
43
|
+
ResizablePanel,
|
|
44
|
+
ResizablePanelGroup,
|
|
45
|
+
ResizablePanelSplitter,
|
|
46
|
+
ResizablePanelSplitterLine,
|
|
47
|
+
} from '@finos/legend-art';
|
|
48
|
+
import { MD5HashStrategy } from '../graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js';
|
|
49
|
+
import {
|
|
50
|
+
DataQualityRelationComparisonConfigurationState,
|
|
51
|
+
DEFAULT_LIMIT,
|
|
52
|
+
RECONCILIATION_EXECUTION_TYPE,
|
|
53
|
+
} from './states/DataQualityRelationComparisonConfigurationState.js';
|
|
54
|
+
import { useEditorStore } from '@finos/legend-application-studio';
|
|
55
|
+
import {
|
|
56
|
+
DEFAULT_TAB_SIZE,
|
|
57
|
+
useApplicationStore,
|
|
58
|
+
} from '@finos/legend-application';
|
|
59
|
+
import {
|
|
60
|
+
BasicValueSpecificationEditor,
|
|
61
|
+
LambdaEditor,
|
|
62
|
+
LambdaParameterValuesEditor,
|
|
63
|
+
type LambdaParameterState,
|
|
64
|
+
getTDSColumnCustomizations,
|
|
65
|
+
getFilterTDSColumnCustomizations,
|
|
66
|
+
} from '@finos/legend-query-builder';
|
|
67
|
+
import { flowResult } from 'mobx';
|
|
68
|
+
import { DataQualityMultiCustomSelector } from './DataQualityCustomSelector.js';
|
|
69
|
+
import {
|
|
70
|
+
type ExecutionResult,
|
|
71
|
+
type ObserverContext,
|
|
72
|
+
PrimitiveType,
|
|
73
|
+
type PureModel,
|
|
74
|
+
TDSExecutionResult,
|
|
75
|
+
RawExecutionResult,
|
|
76
|
+
type ValueSpecification,
|
|
77
|
+
extractExecutionResultValues,
|
|
78
|
+
} from '@finos/legend-graph';
|
|
79
|
+
import {
|
|
80
|
+
guaranteeType,
|
|
81
|
+
prettyDuration,
|
|
82
|
+
prettyCONSTName,
|
|
83
|
+
returnUndefOnError,
|
|
84
|
+
} from '@finos/legend-shared';
|
|
85
|
+
import { CodeEditor } from '@finos/legend-lego/code-editor';
|
|
86
|
+
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
|
|
87
|
+
import {
|
|
88
|
+
DataQualityResultCellRenderer,
|
|
89
|
+
getRowDataFromExecutionResult,
|
|
90
|
+
} from './DataQualityRelationGridResult.js';
|
|
91
|
+
import {
|
|
92
|
+
type DataGridColumnDefinition,
|
|
93
|
+
DataGrid,
|
|
94
|
+
} from '@finos/legend-lego/data-grid';
|
|
95
|
+
|
|
96
|
+
const ComparisonParameterSection = observer(
|
|
97
|
+
(props: {
|
|
98
|
+
title: string;
|
|
99
|
+
graph: PureModel;
|
|
100
|
+
observerContext: ObserverContext;
|
|
101
|
+
parameterStates: LambdaParameterState[];
|
|
102
|
+
}) => {
|
|
103
|
+
const { title, graph, observerContext, parameterStates } = props;
|
|
104
|
+
|
|
105
|
+
if (!parameterStates.length) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<div className="data-quality-relation-comparison-editor__parameters-modal__section">
|
|
111
|
+
<div className="data-quality-relation-comparison-editor__parameters-modal__section__title">
|
|
112
|
+
{title}
|
|
113
|
+
</div>
|
|
114
|
+
<div className="data-quality-relation-comparison-editor__parameters-modal__section__body">
|
|
115
|
+
{parameterStates.map((paramState) => {
|
|
116
|
+
const variableType =
|
|
117
|
+
paramState.variableType ?? PrimitiveType.STRING;
|
|
118
|
+
return (
|
|
119
|
+
<div
|
|
120
|
+
key={paramState.uuid}
|
|
121
|
+
className="panel__content__form__section"
|
|
122
|
+
>
|
|
123
|
+
<div className="lambda-parameter-values__value__label">
|
|
124
|
+
<div className="lambda-parameter-values__value__label__name">
|
|
125
|
+
{paramState.parameter.name}
|
|
126
|
+
</div>
|
|
127
|
+
<div className="lambda-parameter-values__value__label__type">
|
|
128
|
+
{variableType.name}
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
{paramState.value && (
|
|
132
|
+
<BasicValueSpecificationEditor
|
|
133
|
+
valueSpecification={paramState.value}
|
|
134
|
+
setValueSpecification={(val: ValueSpecification): void => {
|
|
135
|
+
paramState.setValue(val);
|
|
136
|
+
}}
|
|
137
|
+
graph={graph}
|
|
138
|
+
observerContext={observerContext}
|
|
139
|
+
typeCheckOption={{
|
|
140
|
+
expectedType: variableType,
|
|
141
|
+
match: variableType === PrimitiveType.DATETIME,
|
|
142
|
+
}}
|
|
143
|
+
className="query-builder__parameters__value__editor"
|
|
144
|
+
resetValue={(): void => undefined}
|
|
145
|
+
/>
|
|
146
|
+
)}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
})}
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const DataQualityRelationComparisonParametersEditor = observer(
|
|
157
|
+
(props: { state: DataQualityRelationComparisonConfigurationState }) => {
|
|
158
|
+
const { state } = props;
|
|
159
|
+
const applicationStore = useApplicationStore();
|
|
160
|
+
const [isSubmitAction, setIsSubmitAction] = React.useState(false);
|
|
161
|
+
const [isClosingAction, setIsClosingAction] = React.useState(false);
|
|
162
|
+
const valuesEditorState = state.comparisonParametersEditorState;
|
|
163
|
+
const submitAction = valuesEditorState.submitAction;
|
|
164
|
+
|
|
165
|
+
const close = (): void => {
|
|
166
|
+
setIsClosingAction(true);
|
|
167
|
+
valuesEditorState.close();
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const submit = applicationStore.guardUnhandledError(async () => {
|
|
171
|
+
if (submitAction) {
|
|
172
|
+
setIsSubmitAction(true);
|
|
173
|
+
close();
|
|
174
|
+
await submitAction.handler();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Dialog
|
|
180
|
+
open={Boolean(valuesEditorState.showModal)}
|
|
181
|
+
onClose={close}
|
|
182
|
+
classes={{
|
|
183
|
+
root: 'editor-modal__root-container',
|
|
184
|
+
container: 'editor-modal__container',
|
|
185
|
+
paper: 'editor-modal__content',
|
|
186
|
+
}}
|
|
187
|
+
>
|
|
188
|
+
<Modal
|
|
189
|
+
darkMode={
|
|
190
|
+
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
|
191
|
+
}
|
|
192
|
+
className="editor-modal lambda-parameter-values__modal data-quality-relation-comparison-editor__parameters-modal"
|
|
193
|
+
>
|
|
194
|
+
<ModalHeader title="Set Comparison Parameter Values" />
|
|
195
|
+
<ModalBody className="lambda-parameter-values__modal__body data-quality-relation-comparison-editor__parameters-modal__body">
|
|
196
|
+
<div className="data-quality-relation-comparison-editor__parameters-modal__description">
|
|
197
|
+
Source and target parameters are submitted independently for the
|
|
198
|
+
reconciliation run.
|
|
199
|
+
</div>
|
|
200
|
+
<div className="data-quality-relation-comparison-editor__parameters-modal__sections">
|
|
201
|
+
<ComparisonParameterSection
|
|
202
|
+
title="Source Query"
|
|
203
|
+
graph={state.editorStore.graphManagerState.graph}
|
|
204
|
+
observerContext={
|
|
205
|
+
state.editorStore.changeDetectionState.observerContext
|
|
206
|
+
}
|
|
207
|
+
parameterStates={state.sourceParametersState.parameterStates}
|
|
208
|
+
/>
|
|
209
|
+
<ComparisonParameterSection
|
|
210
|
+
title="Target Query"
|
|
211
|
+
graph={state.editorStore.graphManagerState.graph}
|
|
212
|
+
observerContext={
|
|
213
|
+
state.editorStore.changeDetectionState.observerContext
|
|
214
|
+
}
|
|
215
|
+
parameterStates={state.targetParametersState.parameterStates}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
</ModalBody>
|
|
219
|
+
<ModalFooter>
|
|
220
|
+
{isClosingAction && (
|
|
221
|
+
<ModalFooterStatus>Closing...</ModalFooterStatus>
|
|
222
|
+
)}
|
|
223
|
+
{submitAction && (
|
|
224
|
+
<ModalFooterButton
|
|
225
|
+
inProgressText={
|
|
226
|
+
isSubmitAction ? `${submitAction.label}...` : undefined
|
|
227
|
+
}
|
|
228
|
+
onClick={submit}
|
|
229
|
+
text={prettyCONSTName(submitAction.label)}
|
|
230
|
+
/>
|
|
231
|
+
)}
|
|
232
|
+
<ModalFooterButton
|
|
233
|
+
inProgressText={isClosingAction ? 'Closing...' : undefined}
|
|
234
|
+
onClick={close}
|
|
235
|
+
text="Close"
|
|
236
|
+
type="secondary"
|
|
237
|
+
/>
|
|
238
|
+
</ModalFooter>
|
|
239
|
+
</Modal>
|
|
240
|
+
</Dialog>
|
|
241
|
+
);
|
|
242
|
+
},
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
export const DataQualityRelationComparisonEditor = observer(() => {
|
|
246
|
+
const editorStore = useEditorStore();
|
|
247
|
+
const applicationStore = useApplicationStore();
|
|
248
|
+
const state = editorStore.tabManagerState.getCurrentEditorState(
|
|
249
|
+
DataQualityRelationComparisonConfigurationState,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const comparison = state.element;
|
|
253
|
+
const md5Strategy = guaranteeType(comparison.strategy, MD5HashStrategy);
|
|
254
|
+
|
|
255
|
+
const sourceColumnOptions = state.sourceColumnOptions;
|
|
256
|
+
const targetColumnOptions = state.targetColumnOptions;
|
|
257
|
+
const combinedColumnOptions = state.combinedColumnOptions;
|
|
258
|
+
|
|
259
|
+
const isRunning = state.isRunning;
|
|
260
|
+
const executionResult = state.executionResult;
|
|
261
|
+
const isFetchingColumns = state.fetchColumnsState.isInProgress;
|
|
262
|
+
const hasColumnFetchError = state.hasColumnFetchError;
|
|
263
|
+
const columnFetchError = state.columnFetchError;
|
|
264
|
+
const hasNoOverlappingColumns = state.hasNoOverlappingColumns;
|
|
265
|
+
const columnsDisabled = hasColumnFetchError || isFetchingColumns;
|
|
266
|
+
|
|
267
|
+
// Execution handlers
|
|
268
|
+
const cancelRun = applicationStore.guardUnhandledError(() =>
|
|
269
|
+
flowResult(state.cancelRun()),
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
const runReconciliation = applicationStore.guardUnhandledError(() =>
|
|
273
|
+
flowResult(state.handleRun(RECONCILIATION_EXECUTION_TYPE.RECONCILIATION)),
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const runSourceQuery = applicationStore.guardUnhandledError(() =>
|
|
277
|
+
flowResult(state.handleRun(RECONCILIATION_EXECUTION_TYPE.SOURCE_QUERY)),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const runTargetQuery = applicationStore.guardUnhandledError(() =>
|
|
281
|
+
flowResult(state.handleRun(RECONCILIATION_EXECUTION_TYPE.TARGET_QUERY)),
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const retryFetchColumns = applicationStore.guardUnhandledError(() =>
|
|
285
|
+
flowResult(state.retryFetchColumns()),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const getResultSetDescription = (
|
|
289
|
+
_executionResult: ExecutionResult,
|
|
290
|
+
): string | undefined => {
|
|
291
|
+
const queryDuration = state.executionDuration
|
|
292
|
+
? prettyDuration(state.executionDuration)
|
|
293
|
+
: undefined;
|
|
294
|
+
if (!queryDuration) {
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
const executionName =
|
|
298
|
+
state.lastExecutionType === RECONCILIATION_EXECUTION_TYPE.RECONCILIATION
|
|
299
|
+
? 'Data Comparison'
|
|
300
|
+
: state.lastExecutionType === RECONCILIATION_EXECUTION_TYPE.SOURCE_QUERY
|
|
301
|
+
? 'Source Query'
|
|
302
|
+
: 'Target Query';
|
|
303
|
+
return `${executionName} ran in ${queryDuration}`;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const resultDescription =
|
|
307
|
+
!isRunning && executionResult
|
|
308
|
+
? getResultSetDescription(executionResult)
|
|
309
|
+
: undefined;
|
|
310
|
+
|
|
311
|
+
const darkMode =
|
|
312
|
+
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled;
|
|
313
|
+
const [limitValue, setLimitValue] = React.useState(state.limit);
|
|
314
|
+
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
315
|
+
|
|
316
|
+
const changeLimit: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
317
|
+
setLimitValue(parseInt(event.target.value, 10));
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const getLimit = (): void => {
|
|
321
|
+
if (isNaN(limitValue) || limitValue === 0) {
|
|
322
|
+
setLimitValue(1000);
|
|
323
|
+
state.setLimit(1000);
|
|
324
|
+
} else {
|
|
325
|
+
state.setLimit(limitValue);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const onLimitKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (
|
|
330
|
+
event,
|
|
331
|
+
) => {
|
|
332
|
+
if (event.code === 'Enter') {
|
|
333
|
+
getLimit();
|
|
334
|
+
inputRef.current?.focus();
|
|
335
|
+
} else if (event.code === 'Escape') {
|
|
336
|
+
setLimitValue(state.limit);
|
|
337
|
+
inputRef.current?.select();
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
setLimitValue(state.limit);
|
|
343
|
+
}, [state.limit]);
|
|
344
|
+
|
|
345
|
+
const renderResult = (): React.ReactNode => {
|
|
346
|
+
if (executionResult instanceof TDSExecutionResult) {
|
|
347
|
+
const colDefs = executionResult.result.columns.map(
|
|
348
|
+
(colName) =>
|
|
349
|
+
({
|
|
350
|
+
minWidth: 50,
|
|
351
|
+
sortable: true,
|
|
352
|
+
resizable: true,
|
|
353
|
+
field: colName,
|
|
354
|
+
flex: 1,
|
|
355
|
+
...getTDSColumnCustomizations(executionResult, colName),
|
|
356
|
+
...getFilterTDSColumnCustomizations(executionResult, colName),
|
|
357
|
+
cellRenderer: DataQualityResultCellRenderer,
|
|
358
|
+
}) as DataGridColumnDefinition,
|
|
359
|
+
);
|
|
360
|
+
return (
|
|
361
|
+
<div className="data-quality-validation__result__values__table">
|
|
362
|
+
<div
|
|
363
|
+
className={clsx('data-quality-validation__result__tds-grid', {
|
|
364
|
+
'ag-theme-balham': !darkMode,
|
|
365
|
+
'ag-theme-balham-dark': darkMode,
|
|
366
|
+
})}
|
|
367
|
+
>
|
|
368
|
+
<DataGrid
|
|
369
|
+
rowData={getRowDataFromExecutionResult(executionResult)}
|
|
370
|
+
gridOptions={{
|
|
371
|
+
suppressScrollOnNewData: true,
|
|
372
|
+
getRowId: (data) => `${data.data.rowNumber}`,
|
|
373
|
+
rowSelection: {
|
|
374
|
+
mode: 'multiRow',
|
|
375
|
+
checkboxes: false,
|
|
376
|
+
headerCheckbox: false,
|
|
377
|
+
},
|
|
378
|
+
}}
|
|
379
|
+
onRowDataUpdated={(params) => {
|
|
380
|
+
params.api.refreshCells({ force: true });
|
|
381
|
+
}}
|
|
382
|
+
suppressFieldDotNotation={true}
|
|
383
|
+
suppressContextMenu={false}
|
|
384
|
+
columnDefs={colDefs}
|
|
385
|
+
/>
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
if (executionResult instanceof RawExecutionResult) {
|
|
391
|
+
const val =
|
|
392
|
+
executionResult.value === null
|
|
393
|
+
? 'null'
|
|
394
|
+
: executionResult.value.toString();
|
|
395
|
+
return (
|
|
396
|
+
<CodeEditor
|
|
397
|
+
language={CODE_EDITOR_LANGUAGE.TEXT}
|
|
398
|
+
inputValue={val}
|
|
399
|
+
isReadOnly={true}
|
|
400
|
+
/>
|
|
401
|
+
);
|
|
402
|
+
} else if (executionResult !== undefined) {
|
|
403
|
+
const json =
|
|
404
|
+
returnUndefOnError(() =>
|
|
405
|
+
JSON.stringify(
|
|
406
|
+
extractExecutionResultValues(executionResult),
|
|
407
|
+
null,
|
|
408
|
+
DEFAULT_TAB_SIZE,
|
|
409
|
+
),
|
|
410
|
+
) ?? JSON.stringify(executionResult);
|
|
411
|
+
return (
|
|
412
|
+
<CodeEditor
|
|
413
|
+
language={CODE_EDITOR_LANGUAGE.JSON}
|
|
414
|
+
inputValue={json}
|
|
415
|
+
isReadOnly={true}
|
|
416
|
+
/>
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
return <BlankPanelContent>No Data to Display</BlankPanelContent>;
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
useEffect(() => {
|
|
423
|
+
flowResult(
|
|
424
|
+
state.sourceLambdaEditorState.convertLambdaObjectToGrammarString({
|
|
425
|
+
pretty: true,
|
|
426
|
+
firstLoad: true,
|
|
427
|
+
}),
|
|
428
|
+
).catch(applicationStore.alertUnhandledError);
|
|
429
|
+
flowResult(
|
|
430
|
+
state.targetLambdaEditorState.convertLambdaObjectToGrammarString({
|
|
431
|
+
pretty: true,
|
|
432
|
+
firstLoad: true,
|
|
433
|
+
}),
|
|
434
|
+
).catch(applicationStore.alertUnhandledError);
|
|
435
|
+
}, [
|
|
436
|
+
applicationStore,
|
|
437
|
+
state.sourceLambdaEditorState,
|
|
438
|
+
state.targetLambdaEditorState,
|
|
439
|
+
]);
|
|
440
|
+
|
|
441
|
+
const sourceHashColumnValue = md5Strategy.sourceHashColumn
|
|
442
|
+
? {
|
|
443
|
+
value: md5Strategy.sourceHashColumn,
|
|
444
|
+
label: md5Strategy.sourceHashColumn,
|
|
445
|
+
}
|
|
446
|
+
: undefined;
|
|
447
|
+
|
|
448
|
+
const targetHashColumnValue = md5Strategy.targetHashColumn
|
|
449
|
+
? {
|
|
450
|
+
value: md5Strategy.targetHashColumn,
|
|
451
|
+
label: md5Strategy.targetHashColumn,
|
|
452
|
+
}
|
|
453
|
+
: undefined;
|
|
454
|
+
|
|
455
|
+
const selectedKeyOptions = useMemo(() => {
|
|
456
|
+
const selectedKeys = new Set(comparison.keys);
|
|
457
|
+
return combinedColumnOptions.filter(({ value }) => selectedKeys.has(value));
|
|
458
|
+
}, [combinedColumnOptions, comparison.keys]);
|
|
459
|
+
|
|
460
|
+
const selectedColumnsToCompareOptions = useMemo(() => {
|
|
461
|
+
const selectedColumns = new Set(comparison.columnsToCompare);
|
|
462
|
+
return combinedColumnOptions.filter(({ value }) =>
|
|
463
|
+
selectedColumns.has(value),
|
|
464
|
+
);
|
|
465
|
+
}, [combinedColumnOptions, comparison.columnsToCompare]);
|
|
466
|
+
|
|
467
|
+
return (
|
|
468
|
+
<div className="data-quality-relation-comparison-editor">
|
|
469
|
+
<Panel>
|
|
470
|
+
<PanelLoadingIndicator isLoading={isRunning} />
|
|
471
|
+
<div className="panel__header">
|
|
472
|
+
<div className="panel__header__title">
|
|
473
|
+
<div className="panel__header__title__label">
|
|
474
|
+
dataQualityRelationComparison
|
|
475
|
+
</div>
|
|
476
|
+
<div className="panel__header__title__content">
|
|
477
|
+
{comparison.name}
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
</div>
|
|
481
|
+
<div className="data-quality-relation-comparison-editor__actions-bar">
|
|
482
|
+
<div className="data-quality-relation-comparison-editor__actions-bar__limit">
|
|
483
|
+
<div className="data-quality-relation-comparison-editor__actions-bar__limit__label">
|
|
484
|
+
preview row limit
|
|
485
|
+
</div>
|
|
486
|
+
<input
|
|
487
|
+
ref={inputRef}
|
|
488
|
+
className="input--dark data-quality-relation-comparison-editor__actions-bar__limit__input"
|
|
489
|
+
spellCheck={false}
|
|
490
|
+
type="number"
|
|
491
|
+
value={Number.isNaN(limitValue) ? '' : limitValue}
|
|
492
|
+
min={1}
|
|
493
|
+
placeholder={DEFAULT_LIMIT.toString()}
|
|
494
|
+
onChange={changeLimit}
|
|
495
|
+
onBlur={getLimit}
|
|
496
|
+
onKeyDown={onLimitKeyDown}
|
|
497
|
+
/>
|
|
498
|
+
</div>
|
|
499
|
+
<div className="btn__dropdown-combo btn__dropdown-combo--primary">
|
|
500
|
+
{state.isRunning ? (
|
|
501
|
+
<button
|
|
502
|
+
className="btn__dropdown-combo__canceler data-quality-relation-comparison-editor__actions-bar__cancel-btn"
|
|
503
|
+
onClick={cancelRun}
|
|
504
|
+
tabIndex={-1}
|
|
505
|
+
>
|
|
506
|
+
<div className="btn--dark btn--caution btn__dropdown-combo__canceler__label data-quality-relation-comparison-editor__actions-bar__cancel-label">
|
|
507
|
+
<PauseCircleIcon className="btn__dropdown-combo__canceler__label__icon" />
|
|
508
|
+
<div className="btn__dropdown-combo__canceler__label__title">
|
|
509
|
+
Stop
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
</button>
|
|
513
|
+
) : (
|
|
514
|
+
<div className="data-quality-relation-comparison-editor__actions-bar__run-group">
|
|
515
|
+
<button
|
|
516
|
+
className="btn__dropdown-combo__label data-quality-relation-comparison-editor__actions-bar__run-btn"
|
|
517
|
+
onClick={runReconciliation}
|
|
518
|
+
title="Run Data Comparison"
|
|
519
|
+
disabled={isRunning}
|
|
520
|
+
tabIndex={-1}
|
|
521
|
+
>
|
|
522
|
+
<PlayIcon className="btn__dropdown-combo__label__icon" />
|
|
523
|
+
<div className="btn__dropdown-combo__label__title">
|
|
524
|
+
Run Data Comparison
|
|
525
|
+
</div>
|
|
526
|
+
</button>
|
|
527
|
+
<ControlledDropdownMenu
|
|
528
|
+
className="btn__dropdown-combo__dropdown-btn data-quality-relation-comparison-editor__actions-bar__dropdown-btn"
|
|
529
|
+
disabled={isRunning}
|
|
530
|
+
content={
|
|
531
|
+
<MenuContent>
|
|
532
|
+
<MenuContentItem
|
|
533
|
+
className="btn__dropdown-combo__option"
|
|
534
|
+
onClick={runSourceQuery}
|
|
535
|
+
>
|
|
536
|
+
Run Source Query
|
|
537
|
+
</MenuContentItem>
|
|
538
|
+
<MenuContentItem
|
|
539
|
+
className="btn__dropdown-combo__option"
|
|
540
|
+
onClick={runTargetQuery}
|
|
541
|
+
>
|
|
542
|
+
Run Target Query
|
|
543
|
+
</MenuContentItem>
|
|
544
|
+
</MenuContent>
|
|
545
|
+
}
|
|
546
|
+
menuProps={{
|
|
547
|
+
anchorOrigin: {
|
|
548
|
+
vertical: 'bottom',
|
|
549
|
+
horizontal: 'right',
|
|
550
|
+
},
|
|
551
|
+
transformOrigin: {
|
|
552
|
+
vertical: 'top',
|
|
553
|
+
horizontal: 'right',
|
|
554
|
+
},
|
|
555
|
+
}}
|
|
556
|
+
>
|
|
557
|
+
<CaretDownIcon />
|
|
558
|
+
</ControlledDropdownMenu>
|
|
559
|
+
</div>
|
|
560
|
+
)}
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
<PanelContent>
|
|
564
|
+
<div className="data-quality-relation-comparison-editor__queries">
|
|
565
|
+
<ResizablePanelGroup orientation="vertical">
|
|
566
|
+
<ResizablePanel minSize={200}>
|
|
567
|
+
<div className="data-quality-relation-comparison-editor__query-panel">
|
|
568
|
+
<div className="data-quality-relation-comparison-editor__query-panel__header">
|
|
569
|
+
<div className="data-quality-relation-comparison-editor__query-panel__title">
|
|
570
|
+
SOURCE QUERY
|
|
571
|
+
</div>
|
|
572
|
+
</div>
|
|
573
|
+
<div
|
|
574
|
+
className={clsx(
|
|
575
|
+
'data-quality-relation-comparison-editor__query-panel__content',
|
|
576
|
+
{
|
|
577
|
+
backdrop__element: Boolean(
|
|
578
|
+
state.sourceLambdaEditorState.parserError,
|
|
579
|
+
),
|
|
580
|
+
},
|
|
581
|
+
)}
|
|
582
|
+
>
|
|
583
|
+
<LambdaEditor
|
|
584
|
+
className="data-quality-relation-comparison-editor__lambda-editor lambda-editor--dark"
|
|
585
|
+
disabled={
|
|
586
|
+
state.sourceLambdaEditorState
|
|
587
|
+
.isConvertingFunctionBodyToString
|
|
588
|
+
}
|
|
589
|
+
lambdaEditorState={state.sourceLambdaEditorState}
|
|
590
|
+
forceBackdrop={false}
|
|
591
|
+
autoFocus={false}
|
|
592
|
+
/>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
595
|
+
</ResizablePanel>
|
|
596
|
+
<ResizablePanelSplitter>
|
|
597
|
+
<ResizablePanelSplitterLine color="var(--color-dark-grey-250)" />
|
|
598
|
+
</ResizablePanelSplitter>
|
|
599
|
+
<ResizablePanel minSize={200}>
|
|
600
|
+
<div className="data-quality-relation-comparison-editor__query-panel">
|
|
601
|
+
<div className="data-quality-relation-comparison-editor__query-panel__header">
|
|
602
|
+
<div className="data-quality-relation-comparison-editor__query-panel__title">
|
|
603
|
+
TARGET QUERY
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
<div
|
|
607
|
+
className={clsx(
|
|
608
|
+
'data-quality-relation-comparison-editor__query-panel__content',
|
|
609
|
+
{
|
|
610
|
+
backdrop__element: Boolean(
|
|
611
|
+
state.targetLambdaEditorState.parserError,
|
|
612
|
+
),
|
|
613
|
+
},
|
|
614
|
+
)}
|
|
615
|
+
>
|
|
616
|
+
<LambdaEditor
|
|
617
|
+
className="data-quality-relation-comparison-editor__lambda-editor lambda-editor--dark"
|
|
618
|
+
disabled={
|
|
619
|
+
state.targetLambdaEditorState
|
|
620
|
+
.isConvertingFunctionBodyToString
|
|
621
|
+
}
|
|
622
|
+
lambdaEditorState={state.targetLambdaEditorState}
|
|
623
|
+
forceBackdrop={false}
|
|
624
|
+
autoFocus={false}
|
|
625
|
+
/>
|
|
626
|
+
</div>
|
|
627
|
+
</div>
|
|
628
|
+
</ResizablePanel>
|
|
629
|
+
</ResizablePanelGroup>
|
|
630
|
+
</div>
|
|
631
|
+
|
|
632
|
+
<div className="data-quality-relation-comparison-editor__panel__content__form">
|
|
633
|
+
{hasColumnFetchError && (
|
|
634
|
+
<div className="data-quality-relation-comparison-editor__column-fetch-error">
|
|
635
|
+
<ExclamationTriangleIcon className="data-quality-relation-comparison-editor__column-fetch-error__icon" />
|
|
636
|
+
<span className="data-quality-relation-comparison-editor__column-fetch-error__message">
|
|
637
|
+
{columnFetchError}
|
|
638
|
+
</span>
|
|
639
|
+
<button
|
|
640
|
+
className="data-quality-relation-comparison-editor__column-fetch-error__retry-btn btn--dark btn--sm"
|
|
641
|
+
onClick={retryFetchColumns}
|
|
642
|
+
disabled={isFetchingColumns}
|
|
643
|
+
tabIndex={-1}
|
|
644
|
+
>
|
|
645
|
+
<RefreshIcon />
|
|
646
|
+
<span>Retry</span>
|
|
647
|
+
</button>
|
|
648
|
+
</div>
|
|
649
|
+
)}
|
|
650
|
+
{hasNoOverlappingColumns && (
|
|
651
|
+
<div className="data-quality-relation-comparison-editor__column-overlap-warning">
|
|
652
|
+
<ExclamationTriangleIcon className="data-quality-relation-comparison-editor__column-overlap-warning__icon" />
|
|
653
|
+
<span className="data-quality-relation-comparison-editor__column-overlap-warning__message">
|
|
654
|
+
No overlapping columns found between source and target
|
|
655
|
+
queries. The Keys and Columns to Compare selectors require at
|
|
656
|
+
least one common column name across both queries.
|
|
657
|
+
</span>
|
|
658
|
+
</div>
|
|
659
|
+
)}
|
|
660
|
+
<PanelFormSection>
|
|
661
|
+
<div className="panel__content__form__section__header__label">
|
|
662
|
+
Keys
|
|
663
|
+
</div>
|
|
664
|
+
<div className="panel__content__form__section__header__prompt">
|
|
665
|
+
Columns used as join keys between source and target
|
|
666
|
+
</div>
|
|
667
|
+
<DataQualityMultiCustomSelector
|
|
668
|
+
value={selectedKeyOptions}
|
|
669
|
+
onChange={(values) =>
|
|
670
|
+
state.setKeys(values.map((option) => option.value))
|
|
671
|
+
}
|
|
672
|
+
options={combinedColumnOptions}
|
|
673
|
+
placeholder="Select keys..."
|
|
674
|
+
disabled={columnsDisabled}
|
|
675
|
+
darkMode={darkMode}
|
|
676
|
+
/>
|
|
677
|
+
</PanelFormSection>
|
|
678
|
+
|
|
679
|
+
<PanelFormSection>
|
|
680
|
+
<div className="panel__content__form__section__header__label">
|
|
681
|
+
Columns to Compare
|
|
682
|
+
</div>
|
|
683
|
+
<DataQualityMultiCustomSelector
|
|
684
|
+
value={selectedColumnsToCompareOptions}
|
|
685
|
+
onChange={(values) =>
|
|
686
|
+
state.setColumnsToCompare(
|
|
687
|
+
values.map((option) => option.value),
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
options={combinedColumnOptions}
|
|
691
|
+
placeholder="Select columns to compare..."
|
|
692
|
+
disabled={columnsDisabled}
|
|
693
|
+
darkMode={darkMode}
|
|
694
|
+
/>
|
|
695
|
+
</PanelFormSection>
|
|
696
|
+
|
|
697
|
+
<PanelFormSection>
|
|
698
|
+
<div className="panel__content__form__section__header__label">
|
|
699
|
+
Source Hash Column
|
|
700
|
+
</div>
|
|
701
|
+
<div className="panel__content__form__section__header__prompt">
|
|
702
|
+
If a source hash column already exists you can specify it here
|
|
703
|
+
(optional)
|
|
704
|
+
</div>
|
|
705
|
+
<CustomSelectorInput
|
|
706
|
+
value={sourceHashColumnValue ?? null}
|
|
707
|
+
options={sourceColumnOptions}
|
|
708
|
+
onChange={(opt: { value: string; label: string } | null) => {
|
|
709
|
+
state.setSourceHashColumn(opt?.value);
|
|
710
|
+
}}
|
|
711
|
+
placeholder="Select source hash column..."
|
|
712
|
+
isClearable={true}
|
|
713
|
+
darkMode={darkMode}
|
|
714
|
+
disabled={columnsDisabled}
|
|
715
|
+
/>
|
|
716
|
+
</PanelFormSection>
|
|
717
|
+
<PanelFormSection>
|
|
718
|
+
<div className="panel__content__form__section__header__label">
|
|
719
|
+
Target Hash Column
|
|
720
|
+
</div>
|
|
721
|
+
<div className="panel__content__form__section__header__prompt">
|
|
722
|
+
If a target hash column already exists you can specify it here
|
|
723
|
+
(optional)
|
|
724
|
+
</div>
|
|
725
|
+
<CustomSelectorInput
|
|
726
|
+
value={targetHashColumnValue ?? null}
|
|
727
|
+
options={targetColumnOptions}
|
|
728
|
+
onChange={(opt: { value: string; label: string } | null) => {
|
|
729
|
+
state.setTargetHashColumn(opt?.value);
|
|
730
|
+
}}
|
|
731
|
+
placeholder="Select target hash column..."
|
|
732
|
+
isClearable={true}
|
|
733
|
+
darkMode={darkMode}
|
|
734
|
+
disabled={columnsDisabled}
|
|
735
|
+
/>
|
|
736
|
+
</PanelFormSection>
|
|
737
|
+
<PanelFormBooleanField
|
|
738
|
+
name="Aggregated Hash"
|
|
739
|
+
prompt="Compare data at a group level using keys, or compare entire datasets as a whole when no keys are provided."
|
|
740
|
+
value={md5Strategy.aggregatedHash}
|
|
741
|
+
isReadOnly={false}
|
|
742
|
+
update={(value) => state.setAggregatedHash(value)}
|
|
743
|
+
/>
|
|
744
|
+
</div>
|
|
745
|
+
|
|
746
|
+
<div className="data-quality-relation-comparison-editor__result">
|
|
747
|
+
<div className="data-quality-relation-comparison-editor__result__header">
|
|
748
|
+
<div className="data-quality-relation-comparison-editor__result__header-group">
|
|
749
|
+
<div className="data-quality-relation-comparison-editor__result__title">
|
|
750
|
+
RESULT
|
|
751
|
+
</div>
|
|
752
|
+
{isRunning && (
|
|
753
|
+
<div className="data-quality-relation-comparison-editor__result__status">
|
|
754
|
+
{state.currentExecutionType ===
|
|
755
|
+
RECONCILIATION_EXECUTION_TYPE.RECONCILIATION
|
|
756
|
+
? 'Running Data Comparison...'
|
|
757
|
+
: state.currentExecutionType ===
|
|
758
|
+
RECONCILIATION_EXECUTION_TYPE.SOURCE_QUERY
|
|
759
|
+
? 'Running Source Query...'
|
|
760
|
+
: 'Running Target Query...'}
|
|
761
|
+
</div>
|
|
762
|
+
)}
|
|
763
|
+
<div className="data-quality-relation-comparison-editor__result__analytics">
|
|
764
|
+
{resultDescription ?? ''}
|
|
765
|
+
</div>
|
|
766
|
+
</div>
|
|
767
|
+
</div>
|
|
768
|
+
<div className="data-quality-relation-comparison-editor__result__content">
|
|
769
|
+
<div className="data-quality-relation-comparison-editor__result__viewer">
|
|
770
|
+
{renderResult()}
|
|
771
|
+
</div>
|
|
772
|
+
</div>
|
|
773
|
+
</div>
|
|
774
|
+
</PanelContent>
|
|
775
|
+
</Panel>
|
|
776
|
+
{state.sourceParametersState.parameterValuesEditorState.showModal && (
|
|
777
|
+
<LambdaParameterValuesEditor
|
|
778
|
+
graph={editorStore.graphManagerState.graph}
|
|
779
|
+
observerContext={editorStore.changeDetectionState.observerContext}
|
|
780
|
+
lambdaParametersState={state.sourceParametersState}
|
|
781
|
+
/>
|
|
782
|
+
)}
|
|
783
|
+
{state.targetParametersState.parameterValuesEditorState.showModal && (
|
|
784
|
+
<LambdaParameterValuesEditor
|
|
785
|
+
graph={editorStore.graphManagerState.graph}
|
|
786
|
+
observerContext={editorStore.changeDetectionState.observerContext}
|
|
787
|
+
lambdaParametersState={state.targetParametersState}
|
|
788
|
+
/>
|
|
789
|
+
)}
|
|
790
|
+
{state.comparisonParametersEditorState.showModal && (
|
|
791
|
+
<DataQualityRelationComparisonParametersEditor state={state} />
|
|
792
|
+
)}
|
|
793
|
+
</div>
|
|
794
|
+
);
|
|
795
|
+
});
|