@finos/legend-extension-dsl-data-quality
Version:
Legend extension for Data Quality
174 lines • 19.2 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { observer } from 'mobx-react-lite';
import { CORE_DND_TYPE, useEditorStore, } from '@finos/legend-application-studio';
import { DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB, DataQualityRelationValidationConfigurationState, } from './states/DataQualityRelationValidationConfigurationState.js';
import React, { useCallback, useEffect, useRef } from 'react';
import { BlankPanelContent, CaretDownIcon, clsx, ControlledDropdownMenu, CsvIcon, DragPreviewLayer, ExclamationTriangleIcon, MenuContent, MenuContentItem, MenuContentItemIcon, MenuContentItemLabel, Panel, PanelContent, PanelLoadingIndicator, PauseCircleIcon, PlayIcon, PlusIcon, } from '@finos/legend-art';
import { prettyCONSTName, prettyDuration, returnUndefOnError, } from '@finos/legend-shared';
import { ExecutionPlanViewer, LambdaEditor, LambdaParameterValuesEditor, } from '@finos/legend-query-builder';
import { PrimitiveType, stub_RawVariableExpression, Type, RawExecutionResult, extractExecutionResultValues, TDSExecutionResult, } from '@finos/legend-graph';
import { ActionAlertActionType, ActionAlertType, DEFAULT_TAB_SIZE, useApplicationNavigationContext, useApplicationStore, } from '@finos/legend-application';
import { dataQualityRelationValidation_addParameter, dataQualityRelationValidation_deleteParameter, } from '../graph-manager/DSL_DataQuality_GraphModifierHelper.js';
import { flowResult } from 'mobx';
import { DataQualityRelationTrialRuns } from './DataQualityRelationTrialRuns.js';
import { DataQualityValidationParametersEditor, FUNCTION_PARAMETER_DND_TYPE, } from './DataQualityValidationParametersEditor.js';
import { useDrop } from 'react-dnd';
import { DataQualityRelationValidationsEditor } from './DataQualityRelationValidationsEditor.js';
import { CodeEditor } from '@finos/legend-lego/code-editor';
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
import { DataQualityRelationGridResult } from './DataQualityRelationGridResult.js';
import { DATA_QUALITY_VALIDATION_TEST_ID, USER_ATTESTATION_MESSAGE, } from './constants/DataQualityConstants.js';
const RelationDefinitionEditor = observer((props) => {
const { dataQualityRelationValidationConfigurationState } = props;
const { relationFunctionDefinitionEditorState, resultState } = dataQualityRelationValidationConfigurationState;
const { editorStore: { applicationStore }, } = dataQualityRelationValidationConfigurationState;
const validationElement = dataQualityRelationValidationConfigurationState.validationElement;
const lambdaExecutionResult = dataQualityRelationValidationConfigurationState.executionResult;
const isReadOnly = dataQualityRelationValidationConfigurationState.isReadOnly;
const isExportDisabled = dataQualityRelationValidationConfigurationState.isRunningValidation ||
dataQualityRelationValidationConfigurationState.isGeneratingPlan;
const exportValidationResults = async (format) => {
dataQualityRelationValidationConfigurationState.handleExport(format);
};
const getResultSetDescription = (_executionResult) => {
const queryDuration = dataQualityRelationValidationConfigurationState.executionDuration
? prettyDuration(dataQualityRelationValidationConfigurationState.executionDuration, {
ms: true,
})
: undefined;
if (!queryDuration) {
return undefined;
}
return `lambda ran in ${queryDuration}`;
};
const resultDescription = !dataQualityRelationValidationConfigurationState.isRunningValidation &&
lambdaExecutionResult
? getResultSetDescription(lambdaExecutionResult)
: undefined;
const confirmExport = (format) => {
applicationStore.alertService.setActionAlertInfo({
message: USER_ATTESTATION_MESSAGE,
type: ActionAlertType.CAUTION,
actions: [
{
label: 'Accept',
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
handler: applicationStore.guardUnhandledError(() => exportValidationResults(format)),
},
{
label: 'Decline',
type: ActionAlertActionType.PROCEED,
default: true,
},
],
});
};
const addParameter = () => {
dataQualityRelationValidation_addParameter(validationElement.query.parameters, stub_RawVariableExpression(PrimitiveType.STRING));
};
const deleteParameter = (val) => () => {
dataQualityRelationValidation_deleteParameter(validationElement.query.parameters, val);
};
const handleDropParameter = useCallback((item) => {
if (!isReadOnly && item.data.packageableElement instanceof Type) {
dataQualityRelationValidation_addParameter(validationElement.query.parameters, stub_RawVariableExpression(item.data.packageableElement));
}
}, [validationElement, isReadOnly]);
const [{ isParameterDragOver }, dropConnector] = useDrop(() => ({
accept: [
CORE_DND_TYPE.PROJECT_EXPLORER_CLASS,
CORE_DND_TYPE.PROJECT_EXPLORER_ENUMERATION,
],
drop: (item) => handleDropParameter(item),
collect: (monitor) => ({
isParameterDragOver: monitor.isOver({ shallow: true }),
}),
}), [handleDropParameter]);
const ref = useRef(null);
dropConnector(ref);
const renderFuncResult = () => {
if (lambdaExecutionResult instanceof TDSExecutionResult) {
return (_jsx(DataQualityRelationGridResult, { executionResult: lambdaExecutionResult, relationValidationConfigurationState: dataQualityRelationValidationConfigurationState }));
}
if (lambdaExecutionResult instanceof RawExecutionResult) {
const val = lambdaExecutionResult.value === null
? 'null'
: lambdaExecutionResult.value.toString();
return (_jsx(CodeEditor, { language: CODE_EDITOR_LANGUAGE.TEXT, inputValue: val, isReadOnly: true }));
}
else if (lambdaExecutionResult !== undefined) {
const json = returnUndefOnError(() => JSON.stringify(extractExecutionResultValues(lambdaExecutionResult), null, DEFAULT_TAB_SIZE)) ?? JSON.stringify(lambdaExecutionResult);
return (_jsx(CodeEditor, { language: CODE_EDITOR_LANGUAGE.JSON, inputValue: json, isReadOnly: true }));
}
return _jsx(BlankPanelContent, { children: "Lambda Did Not Run" });
};
return (_jsxs(_Fragment, { children: [_jsx(PanelLoadingIndicator, { isLoading: resultState.isGeneratingPlan ||
dataQualityRelationValidationConfigurationState.isRunningValidation }), _jsxs("div", { className: "relation-validation-config-editor__definition", children: [_jsxs("div", { className: "relation-validation-config-editor__definition__item", children: [_jsxs("div", { className: "relation-validation-config-editor__definition__item__header", children: [_jsx("div", { className: "relation-validation-config-editor__definition__item__header__title", children: "PARAMETERS" }), _jsx("button", { className: "relation-validation-config-editor__definition__item__header__add-btn btn--dark", disabled: isReadOnly, onClick: addParameter, tabIndex: -1, title: "Add Parameter", children: _jsx(PlusIcon, {}) })] }), _jsx(DragPreviewLayer, { labelGetter: (item) => item.parameter.name === '' ? '(unknown)' : item.parameter.name, types: [FUNCTION_PARAMETER_DND_TYPE] }), _jsxs("div", { ref: ref, className: clsx('relation-validation-config-editor__definition__item__content', {
'panel__content__lists--dnd-over': isParameterDragOver && !isReadOnly,
}), children: [validationElement.query.parameters.map((param) => (_jsx(DataQualityValidationParametersEditor, { parameter: param, _validationConfig: validationElement, deleteParameter: deleteParameter(param), isReadOnly: isReadOnly }, param._UUID))), validationElement.query.parameters.length === 0 && (_jsx("div", { className: "relation-validation-config-editor__definition__item__content--empty", children: "No parameters" }))] })] }), _jsxs("div", { className: "relation-validation-config-editor__definition__item", children: [_jsx("div", { className: "relation-validation-config-editor__definition__item__header", children: _jsx("div", { className: "relation-validation-config-editor__definition__item__header__title", children: "LAMBDA" }) }), _jsx("div", { className: clsx('relation-validation-config-editor__definition__item__content', {
backdrop__element: Boolean(relationFunctionDefinitionEditorState.parserError),
}), children: _jsx(LambdaEditor, { className: "relation-validation-config-editor__definition__lambda-editor lambda-editor--dark", disabled: relationFunctionDefinitionEditorState.isConvertingFunctionBodyToString ||
false, lambdaEditorState: relationFunctionDefinitionEditorState, forceBackdrop: false, autoFocus: true }) })] }), _jsxs("div", { className: "relation-validation-config-editor__item", children: [_jsxs("div", { className: "relation-validation-config-editor__definition__item__header", children: [_jsxs("div", { className: "relation-validation-config-editor__definition__item__header-group", children: [_jsx("div", { className: "relation-validation-config-editor__definition__item__header__title", children: "RESULT" }), dataQualityRelationValidationConfigurationState.isRunningValidation && (_jsx("div", { className: "panel__header__title__label__status", children: "Running Validation..." })), _jsx("div", { "data-testid": DATA_QUALITY_VALIDATION_TEST_ID.DATA_QUALITY_VALIDATION_RESULT_ANALYTICS, className: "data-quality-validation__result__analytics", children: resultDescription ?? '' }), lambdaExecutionResult &&
dataQualityRelationValidationConfigurationState.checkForStaleResults && (_jsxs("div", { className: "data-quality-validation__result__stale-status", children: [_jsx("div", { className: "data-quality-validation__result__stale-status__icon", children: _jsx(ExclamationTriangleIcon, {}) }), _jsx("div", { className: "data-quality-validation__result__stale-status__label", children: "Preview data might be stale" })] }))] }), _jsx(ControlledDropdownMenu, { className: "data-quality-validation__result__export__dropdown", title: "Export", disabled: isExportDisabled, content: _jsx(MenuContent, { children: Object.values(resultState.exportDataFormatOptions).map((format) => (_jsxs(MenuContentItem, { onClick: () => confirmExport(format), children: [_jsx(MenuContentItemIcon, { children: _jsx(CsvIcon, {}) }), _jsx(MenuContentItemLabel, { children: format })] }, format))) }), menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, children: _jsxs("div", { className: "relation-validation-config-editor__definition__item__header__action", children: [_jsx("div", { className: "data-quality-validation__result__export__dropdown__label", children: "Export" }), _jsx("div", { className: "data-quality-validation__result__export__dropdown__trigger", children: _jsx(CaretDownIcon, {}) })] }) })] }), _jsx("div", { className: "relation-validation-config-editor__definition__item__content", children: _jsx("div", { className: "relation-validation-config-editor__definition__result-viewer", children: renderFuncResult() }) })] })] })] }));
});
export const DataQualityRelationValidationConfigurationEditor = observer(() => {
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const dataQualityRelationValidationConfigurationState = editorStore.tabManagerState.getCurrentEditorState(DataQualityRelationValidationConfigurationState);
const dataQualityRelationValidationElement = dataQualityRelationValidationConfigurationState.validationElement;
const selectedTab = dataQualityRelationValidationConfigurationState.selectedTab;
const changeTab = (tab) => () => dataQualityRelationValidationConfigurationState.setSelectedTab(tab);
const executionIsRunning = dataQualityRelationValidationConfigurationState.isRunningValidation ||
dataQualityRelationValidationConfigurationState.isGeneratingPlan;
const cancelValidation = applicationStore.guardUnhandledError(() => flowResult(dataQualityRelationValidationConfigurationState.cancelValidationRun()));
const runValidation = applicationStore.guardUnhandledError(() => flowResult(dataQualityRelationValidationConfigurationState.handleRunValidation()));
const generatePlan = applicationStore.guardUnhandledError(() => flowResult(dataQualityRelationValidationConfigurationState.generatePlan(false)));
const debugPlanGeneration = applicationStore.guardUnhandledError(() => flowResult(dataQualityRelationValidationConfigurationState.generatePlan(true)));
useEffect(() => {
flowResult(dataQualityRelationValidationConfigurationState.relationFunctionDefinitionEditorState.convertLambdaObjectToGrammarString({
pretty: true,
firstLoad: true,
})).catch(applicationStore.alertUnhandledError);
flowResult(dataQualityRelationValidationConfigurationState.convertValidationLambdaObjects()).catch(applicationStore.alertUnhandledError);
}, [applicationStore, dataQualityRelationValidationConfigurationState]);
useApplicationNavigationContext('studio.editor.dq-relation-editor');
return (_jsxs("div", { className: "relation-validation-config-editor uml-editor uml-editor--dark", children: [_jsxs(Panel, { children: [_jsx("div", { className: "panel__header", children: _jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "dataQualityRelationValidation" }), _jsx("div", { className: "panel__header__title__content", children: dataQualityRelationValidationElement.name })] }) }), _jsxs("div", { className: "panel__header relation-validation-config-editor__tabs__header", children: [_jsx("div", { className: "relation-validation-config-editor__tabs", children: Object.values(DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB).map((tab) => (_jsx("div", { onClick: changeTab(tab), className: clsx('relation-validation-config-editor__tab', {
'relation-validation-config-editor__tab--active': tab === selectedTab,
}), children: prettyCONSTName(tab) }, tab))) }), _jsx("div", { className: "panel__header__actions", children: selectedTab ===
DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.DEFINITION && (_jsx(_Fragment, { children: _jsx("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary", children: dataQualityRelationValidationConfigurationState.isRunningValidation ? (_jsx("button", { className: "btn__dropdown-combo__canceler", onClick: cancelValidation, tabIndex: -1, children: _jsxs("div", { className: "btn--dark btn--caution btn__dropdown-combo__canceler__label", children: [_jsx(PauseCircleIcon, { className: "btn__dropdown-combo__canceler__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__canceler__label__title", children: "Stop" })] }) })) : (_jsxs(_Fragment, { children: [_jsxs("button", { className: "btn__dropdown-combo__label", onClick: runValidation, title: "Run Function", disabled: executionIsRunning, tabIndex: -1, children: [_jsx(PlayIcon, { className: "btn__dropdown-combo__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Run" })] }), _jsx(ControlledDropdownMenu, { className: "btn__dropdown-combo__dropdown-btn", disabled: executionIsRunning, content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: generatePlan, children: "Generate Plan" }), _jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: debugPlanGeneration, children: "Debug" })] }), menuProps: {
anchorOrigin: {
vertical: 'bottom',
horizontal: 'right',
},
transformOrigin: {
vertical: 'top',
horizontal: 'right',
},
}, children: _jsx(CaretDownIcon, {}) })] })) }) })) })] }), _jsxs(PanelContent, { children: [selectedTab ===
DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.DEFINITION && (_jsx(RelationDefinitionEditor, { dataQualityRelationValidationConfigurationState: dataQualityRelationValidationConfigurationState })), selectedTab ===
DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.TRIAL_RUN && (_jsx(DataQualityRelationTrialRuns, { dataQualityRelationValidationConfigurationState: dataQualityRelationValidationConfigurationState })), selectedTab ===
DATA_QUALITY_RELATION_VALIDATION_EDITOR_TAB.VALIDATIONS && (_jsx(DataQualityRelationValidationsEditor, { dataQualityRelationValidationConfigurationState: dataQualityRelationValidationConfigurationState }))] })] }), _jsx(ExecutionPlanViewer, { executionPlanState: dataQualityRelationValidationConfigurationState.executionPlanState }), dataQualityRelationValidationConfigurationState.parametersState
.parameterValuesEditorState.showModal && (_jsx(LambdaParameterValuesEditor, { graph: dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graph, observerContext: dataQualityRelationValidationConfigurationState.editorStore
.changeDetectionState.observerContext, lambdaParametersState: dataQualityRelationValidationConfigurationState.parametersState }))] }));
});
//# sourceMappingURL=DataQualityRelationValidationConfigurationEditor.js.map