@finos/legend-extension-dsl-data-quality
Version:
Legend extension for Data Quality
118 lines • 11.9 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 { useApplicationStore } from '@finos/legend-application';
import { flowResult } from 'mobx';
import { buildFilterConditionExpression, ExecutionPlanViewer, } from '@finos/legend-query-builder';
import { MILESTONING_STEREOTYPE, buildRawLambdaFromLambdaFunction, CORE_PURE_PATH, FunctionType, GenericType, GenericTypeExplicitReference, LambdaFunction, Multiplicity, PackageableElementExplicitReference, VariableExpression, } from '@finos/legend-graph';
import { guaranteeNonNullable, isNonNullable, prettyDuration, } from '@finos/legend-shared';
import { useRef, useState } from 'react';
import { DATA_QUALITY_VALIDATION_TEST_ID } from './constants/DataQualityConstants.js';
import { BlankPanelContent, CubesLoadingIndicator, CubesLoadingIndicatorIcon, MenuContent, MenuContentItem, PanelContent, ExclamationTriangleIcon, DebugIcon, CaretDownIcon, MenuContentItemIcon, MenuContentItemLabel, PauseCircleIcon, PlayIcon, ReportIcon, ControlledDropdownMenu, } from '@finos/legend-art';
import { DataQualityResultValues } from './DataQualityResultValues.js';
import { dataQualityClassValidation_setFilter } from '../graph-manager/DSL_DataQuality_GraphModifierHelper.js';
import { DataQualityDateSelectionPanel } from './DataQualityDateSelectionPanel.js';
export const DataQualityResultPanel = observer((props) => {
const { dataQualityState } = props;
const applicationStore = useApplicationStore();
const resultState = dataQualityState.resultState;
const executionResult = resultState.executionResult;
const buildFilterExpression = (queryBuilderState) => {
const { filterState } = queryBuilderState;
const filterConditionExpressions = filterState.rootIds
.map((e) => guaranteeNonNullable(filterState.nodes.get(e)))
.map((e) => buildFilterConditionExpression(filterState, e))
.filter(isNonNullable);
if (!filterConditionExpressions.length) {
dataQualityClassValidation_setFilter(dataQualityState.constraintsConfigurationElement, undefined);
return;
}
const genericType = new GenericType(guaranteeNonNullable(queryBuilderState.class));
const genericTypeReference = GenericTypeExplicitReference.create(genericType);
const functionType = new FunctionType(PackageableElementExplicitReference.create(queryBuilderState.graphManagerState.graph.getType(CORE_PURE_PATH.ANY)), Multiplicity.ONE);
functionType.parameters.push(new VariableExpression(filterState.lambdaParameterName, Multiplicity.ONE, genericTypeReference));
const lambdaFunction = new LambdaFunction(functionType);
lambdaFunction.expressionSequence = filterConditionExpressions;
dataQualityClassValidation_setFilter(dataQualityState.constraintsConfigurationElement, buildRawLambdaFromLambdaFunction(lambdaFunction, queryBuilderState.graphManagerState));
};
const runQuery = () => {
resultState.pressedRunQuery.inProgress();
flowResult(resultState.runQuery()).catch(applicationStore.alertUnhandledError);
resultState.pressedRunQuery.complete();
};
const cancelQuery = applicationStore.guardUnhandledError(() => flowResult(resultState.cancelQuery()));
const generatePlan = applicationStore.guardUnhandledError(() => {
buildFilterExpression(dataQualityState.dataQualityQueryBuilderState);
return flowResult(resultState.generatePlan(false));
});
const debugPlanGeneration = applicationStore.guardUnhandledError(() => flowResult(resultState.generatePlan(true)));
const allowSettingPreviewLimit = dataQualityState.isQuerySupported;
const isRunQueryDisabled = resultState.isGeneratingPlan ||
resultState.pressedRunQuery.isInProgress ||
dataQualityState.dataQualityQueryBuilderState.filterState
.allValidationIssues.length !== 0;
const getResultSetDescription = (_executionResult) => {
const queryDuration = resultState.executionDuration
? prettyDuration(resultState.executionDuration, {
ms: true,
})
: undefined;
if (!queryDuration) {
return undefined;
}
return `validation ran in ${queryDuration}`;
};
const resultDescription = executionResult
? getResultSetDescription(executionResult)
: undefined;
const [previewLimitValue, setPreviewLimitValue] = useState(resultState.previewLimit);
const changePreviewLimit = (event) => {
setPreviewLimitValue(parseInt(event.target.value, 10));
};
const inputRef = useRef(null);
const getPreviewLimit = () => {
if (isNaN(previewLimitValue) || previewLimitValue === 0) {
setPreviewLimitValue(1);
dataQualityState.resultState.setPreviewLimit(1);
}
else {
dataQualityState.resultState.setPreviewLimit(previewLimitValue);
}
};
const onKeyDown = (event) => {
if (event.code === 'Enter') {
getPreviewLimit();
inputRef.current?.focus();
}
else if (event.code === 'Escape') {
inputRef.current?.select();
}
};
const isLoading = resultState.isRunningQuery || resultState.isGeneratingPlan;
const currentClassMilestoningStrategy = dataQualityState.currentClassMilestoningStrategy;
const showProcessingDate = currentClassMilestoningStrategy ===
MILESTONING_STEREOTYPE.PROCESSING_TEMPORAL ||
currentClassMilestoningStrategy === MILESTONING_STEREOTYPE.BITEMPORAL;
const showBusinessDate = currentClassMilestoningStrategy ===
MILESTONING_STEREOTYPE.BUSINESS_TEMPORAL ||
currentClassMilestoningStrategy === MILESTONING_STEREOTYPE.BITEMPORAL;
return (_jsxs("div", { "data-testid": DATA_QUALITY_VALIDATION_TEST_ID.DATA_QUALITY_VALIDATION_RESULT_PANEL, className: "panel data-quality-validation__result", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "results" }), resultState.pressedRunQuery.isInProgress && (_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 ?? '' }), executionResult && resultState.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" })] }))] }), _jsxs("div", { className: "panel__header__actions data-quality-validation__result__header__actions", children: [showProcessingDate && (_jsxs("div", { className: "trial-runs-result-modifier-prompt__group", children: [_jsx("div", { className: "trial-runs-result-modifier-prompt__group__label", children: "Processing Date" }), _jsx("button", { className: "trial-runs-result-modifier-prompt__header__label editable-value", onClick: () => dataQualityState.setShowDateSelection(true), children: _jsx("div", { className: "trial-runs-result-modifier-prompt__header__label__title", children: dataQualityState.processingDate }) })] })), showBusinessDate && (_jsxs("div", { className: "trial-runs-result-modifier-prompt__group", children: [_jsx("div", { className: "trial-runs-result-modifier-prompt__group__label", children: "Business Date" }), _jsx("button", { className: "trial-runs-result-modifier-prompt__header__label editable-value", onClick: () => dataQualityState.setShowDateSelection(true), children: _jsx("div", { className: "trial-runs-result-modifier-prompt__header__label__title", children: dataQualityState.businessDate }) })] })), allowSettingPreviewLimit && (_jsxs("div", { className: "data-quality-validation__result__limit", children: [_jsx("div", { className: "data-quality-validation__result__limit__label", children: "preview row limit" }), _jsx("input", { ref: inputRef, className: "input--dark data-quality-validation__result__limit__input", spellCheck: false, type: "number", value: previewLimitValue, onChange: changePreviewLimit, onBlur: getPreviewLimit, onKeyDown: onKeyDown })] })), _jsx("div", { className: "data-quality-validation__result__execute-btn btn__dropdown-combo btn__dropdown-combo--primary", children: resultState.isRunningQuery ? (_jsx("button", { className: "btn__dropdown-combo__canceler data-quality-validation__result__execute-btn__btn", onClick: cancelQuery, tabIndex: -1, children: _jsxs("div", { className: "btn--dark btn--caution btn__dropdown-combo__canceler__label data-quality-validation__result__execute-btn__btn", children: [_jsx(PauseCircleIcon, {}), "Stop"] }) })) : (_jsxs(_Fragment, { children: [_jsxs("button", { className: "btn__dropdown-combo__label data-quality-validation__result__execute-btn__validation data-quality-validation__result__execute-btn__btn data-quality-validation__result__execute-btn__btn--green", onClick: runQuery, tabIndex: -1, disabled: isRunQueryDisabled, children: [_jsx(PlayIcon, {}), "Run Validation"] }), _jsx(ControlledDropdownMenu, { className: "btn__dropdown-combo__dropdown-btn data-quality-validation__result__execute-btn__btn data-quality-validation__result__execute-btn__btn--green", disabled: isRunQueryDisabled, content: _jsxs(MenuContent, { children: [_jsxs(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: generatePlan, disabled: isRunQueryDisabled, children: [_jsx(MenuContentItemIcon, { children: _jsx(ReportIcon, {}) }), _jsx(MenuContentItemLabel, { children: "Generate Plan" })] }), _jsxs(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: debugPlanGeneration, disabled: isRunQueryDisabled, children: [_jsx(MenuContentItemIcon, { children: _jsx(DebugIcon, {}) }), _jsx(MenuContentItemLabel, { children: "Debug" })] })] }), menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
}, children: _jsx(CaretDownIcon, {}) })] })) })] })] }), _jsxs(PanelContent, { className: "data-quality-validation__result__content", children: [_jsx(CubesLoadingIndicator, { isLoading: isLoading, children: _jsx(CubesLoadingIndicatorIcon, {}) }), !executionResult && !isLoading && (_jsx(BlankPanelContent, { children: "Click on run validation to see the constraints validation results" })), executionResult && !isLoading && (_jsx("div", { className: "data-quality-validation__result__values", children: _jsx(DataQualityResultValues, { executionResult: executionResult }) }))] }), _jsx(ExecutionPlanViewer, { executionPlanState: resultState.executionPlanState }), _jsx(DataQualityDateSelectionPanel, { dataQualityState: dataQualityState })] }));
});
//# sourceMappingURL=DataQualityResultPanel.js.map