UNPKG

@finos/legend-extension-dsl-data-quality

Version:
172 lines 13.3 kB
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 { useDrop } from 'react-dnd'; import { useCallback } from 'react'; import { getClassPropertyIcon } from '@finos/legend-lego/graph-editor'; import { DataQualityGraphFetchTreeNodeData, isConstraintsClassesTreeEmpty, removeNodeRecursively, } from './utils/DataQualityGraphFetchTreeUtil.js'; import { BlankPanelPlaceholder, CheckSquareIcon, ChevronDownIcon, ChevronRightIcon, clsx, PanelDropZone, PURE_UnknownElementTypeIcon, SquareIcon, TimesIcon, TreeView, ExclamationTriangleIcon, MinusSquareIcon, } from '@finos/legend-art'; import { dataQualityClassValidation_setDataQualityGraphFetchTree } from '../graph-manager/DSL_DataQuality_GraphModifierHelper.js'; import { Class, Enumeration, PropertyGraphFetchTree, RootGraphFetchTree, } from '@finos/legend-graph'; import { DATA_QUALITY_VALIDATION_TEST_ID } from './constants/DataQualityConstants.js'; import { flowResult } from 'mobx'; import { DataQualityStructuralValidationsPanel } from './DataQualityStructuralValidationsPanel.js'; import { QUERY_BUILDER_EXPLORER_TREE_DND_TYPE, } from '@finos/legend-query-builder'; export const getQueryBuilderExplorerTreeNodeSortRank = (node) => { if (node.type instanceof Class) { return 1; } else if (node.type instanceof Enumeration) { return 2; } else { return 3; } }; export const DataQualityConstraintsTreeNodeContainer = observer((props) => { const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props; const { dataQualityState, isReadOnly, removeNode } = innerProps; const { dataQualityGraphFetchTreeState } = dataQualityState; let property, type, subType; if (node.tree instanceof PropertyGraphFetchTree) { property = node.tree.property.value; type = property.genericType.value.rawType; subType = node.tree.subType?.value; } else if (node.tree instanceof RootGraphFetchTree) { type = node.tree.class.value; } const isExpandable = Boolean(node.childrenIds.length); const nodeExpandIcon = isExpandable ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : null; const nodeTypeIcon = type ? (getClassPropertyIcon(type)) : (_jsx(PURE_UnknownElementTypeIcon, {})); const showClassConstraintsSelectionCheckBox = !node.isReadOnly && node.type instanceof Class && node.constraints.length !== 0; const noClassConstraintsSelected = node.type instanceof Class && node.constraints.length > 0 && node.constraints.every((constraint) => !constraint.isSelected); const allClassConstraintsSelected = node.type instanceof Class && node.constraints.length > 0 && node.constraints.every((constraint) => constraint.isSelected); const toggleExpandNode = () => onNodeSelect?.(node); const deleteNode = () => removeNode?.(node); const toggleChecked = (constraint) => { dataQualityGraphFetchTreeState.updateNode(node, [constraint.constraint], !constraint.isSelected); constraint.setIsSelected(!constraint.isSelected); }; const checkBoxIcon = () => { if (noClassConstraintsSelected) { return _jsx(SquareIcon, {}); } if (allClassConstraintsSelected) { return _jsx(CheckSquareIcon, {}); } return _jsx(MinusSquareIcon, {}); }; const toggleClassConstraintsSelection = () => { const desiredConstraints = []; let addConstraint = true; if (!allClassConstraintsSelected) { node.constraints.forEach((constraint) => { desiredConstraints.push(constraint.constraint); constraint.setIsSelected(true); }); } else { addConstraint = false; node.constraints.forEach((constraint) => { desiredConstraints.push(constraint.constraint); constraint.setIsSelected(false); }); } dataQualityGraphFetchTreeState.updateNode(node, desiredConstraints, addConstraint); }; return (_jsxs("div", { className: "constraints-selection-node", children: [_jsxs("div", { className: "tree-view__node__container data-quality-validation-graph-fetch-tree__node__container", style: { paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 2)}rem`, display: 'flex', }, children: [_jsxs("div", { className: "data-quality-validation-graph-fetch-tree__node__content", children: [_jsxs("div", { className: "data-quality-validation-graph-fetch-tree__node__icon", children: [showClassConstraintsSelectionCheckBox && (_jsx("div", { onClick: toggleClassConstraintsSelection, children: _jsx("button", { className: clsx('panel__content__form__section__toggler__btn', 'data-quality-validation-graph-fetch-tree__constraint__checkbox', { 'panel__content__form__section__toggler__btn--toggled': !noClassConstraintsSelected, }), children: checkBoxIcon() }) })), nodeExpandIcon && (_jsx("div", { className: "data-quality-validation-graph-fetch-tree__expand-icon", onClick: toggleExpandNode, children: nodeExpandIcon })), _jsx("div", { className: "data-quality-validation-graph-fetch-tree__type-icon", onClick: toggleExpandNode, children: nodeTypeIcon })] }), _jsxs("div", { className: "tree-view__node__label data-quality-validation-graph-fetch-tree__node__label", onClick: toggleExpandNode, children: [node.label, subType && (_jsx("div", { className: "data-quality-validation-graph-fetch-tree__node__sub-type", children: _jsx("div", { className: "data-quality-validation-graph-fetch-tree__node__sub-type__label", children: subType.name }) })), _jsx("div", { className: "data-quality-validation-graph-fetch-tree__node__type", children: _jsx("div", { className: "data-quality-validation-graph-fetch-tree__node__type__label", children: type ? type.name : '' }) })] })] }), !node.isReadOnly ? (_jsx("div", { className: "data-quality-validation-graph-fetch-tree__node__actions", children: _jsx("button", { className: "data-quality-validation-graph-fetch-tree__node__action", title: "Remove", tabIndex: -1, onClick: deleteNode, disabled: isReadOnly, children: _jsx(TimesIcon, {}) }) })) : (_jsx("div", {}))] }), node.constraints.length ? (_jsx("div", { style: { paddingLeft: `${(level + 2) * (stepPaddingInRem ?? 2)}rem`, display: 'flex', flexDirection: 'column', }, children: node.constraints.map((constraint) => (_jsxs("div", { className: "data-quality-validation-graph-fetch-tree__node__label data-quality-validation-graph-fetch-tree__node__constraint", onClick: () => { toggleChecked(constraint); }, children: [_jsx("button", { className: clsx('panel__content__form__section__toggler__btn', 'data-quality-validation-graph-fetch-tree__constraint__checkbox', { 'panel__content__form__section__toggler__btn--toggled': constraint.isSelected, }), children: constraint.isSelected ? _jsx(CheckSquareIcon, {}) : _jsx(SquareIcon, {}) }), _jsx("div", { className: "data-quality-validation-graph-fetch-tree__constraint__name", children: constraint.constraint.name }), _jsx("div", { className: "data-quality-validation-graph-fetch-tree__constraint__value", children: constraint.lambdaString })] }, constraint.lambdaId))) })) : (_jsx(_Fragment, {}))] })); }); export const ConstraintsSelectionExplorer = observer((props) => { const { constraintsClasses, dataQualityState, updateTreeData } = props; const { applicationStore } = dataQualityState; const getChildNodes = (node) => node.childrenIds .map((id) => constraintsClasses.nodes.get(id)) .filter((_node) => _node instanceof DataQualityGraphFetchTreeNodeData) .sort((a, b) => a.label.localeCompare(b.label)) .sort((a, b) => getQueryBuilderExplorerTreeNodeSortRank(b) - getQueryBuilderExplorerTreeNodeSortRank(a)); const removeNode = (node) => { removeNodeRecursively(constraintsClasses, node); updateTreeData({ ...constraintsClasses }); dataQualityClassValidation_setDataQualityGraphFetchTree(dataQualityState.constraintsConfigurationElement, constraintsClasses.tree); }; const showStructuralValidations = () => { dataQualityState.setShowStructuralValidations(true); flowResult(dataQualityState.fetchStructuralValidations()).catch(applicationStore.alertUnhandledError); }; const disableSyncToDQ = Boolean(!dataQualityState.dataQualityGraphFetchTreeState.treeData); return (_jsxs("div", { className: "data-quality-validation-graph-fetch-constraints-selection__config-group__content", children: [_jsxs("div", { className: "data-quality-validation-graph-fetch-constraints-selection__structural-attributes", children: [_jsx("div", { children: dataQualityState.areNestedConstraintsSelected && (_jsxs("div", { className: "data-quality-validation-graph-fetch-constraints-selection__validation", children: [_jsx("div", { className: "data-quality-validation-graph-fetch-constraints-selection__validation__icon", children: _jsx(ExclamationTriangleIcon, {}) }), _jsx("div", { className: "data-quality-validation-graph-fetch-constraints-selection__validation__msg", children: "Nested constraints execution is not yet supported" })] })) }), _jsx("button", { className: "btn--dark structure-validations-btn", onClick: showStructuralValidations, disabled: Boolean(disableSyncToDQ), tabIndex: -1, title: "Show Structural Attributes to be validated during run", children: "Show Structural Attributes" })] }), _jsx("div", { className: "data-quality-validation-graph-fetch-constraints-selection__config-group__item", children: _jsx(TreeView, { components: { TreeNodeContainer: DataQualityConstraintsTreeNodeContainer, }, className: "data-quality-validation-graph-fetch-tree__container__tree", treeData: constraintsClasses, getChildNodes: getChildNodes, innerProps: { dataQualityState, isReadOnly: false, removeNode, } }) }), _jsx(DataQualityStructuralValidationsPanel, { dataQualityState: dataQualityState })] })); }); export const DataQualityConstraintsSelection = observer((props) => { const { dataQualityState } = props; const constraintsConfiguration = dataQualityState.constraintsConfigurationElement; const dataQualityGraphFetchTreeState = dataQualityState.dataQualityGraphFetchTreeState; const treeData = dataQualityGraphFetchTreeState.treeData; const updateTreeData = (data) => { dataQualityGraphFetchTreeState.setGraphFetchTree(data); }; const handleDrop = useCallback((item) => { dataQualityGraphFetchTreeState.addProperty(item.node, { refreshTreeData: true, }); if (dataQualityGraphFetchTreeState.treeData) { dataQualityClassValidation_setDataQualityGraphFetchTree(constraintsConfiguration, dataQualityGraphFetchTreeState.treeData.tree); } }, [dataQualityGraphFetchTreeState, constraintsConfiguration]); const [{ isDragOver }, dropConnector] = useDrop(() => ({ accept: [ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.CLASS_PROPERTY, QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY, ], drop: (item, monitor) => { if (!monitor.didDrop()) { handleDrop(item); } // prevent drop event propagation to accomondate for nested DnD }, collect: (monitor) => ({ isDragOver: monitor.isOver({ shallow: true }), }), }), [handleDrop]); return (_jsx("div", { "data-testid": DATA_QUALITY_VALIDATION_TEST_ID.DATA_QUALITY_VALIDATION_TREE, className: "constraints-selection-tab", children: _jsxs(PanelDropZone, { isDragOver: isDragOver, dropTargetConnector: dropConnector, contentClassName: "data-quality-validation-graph-fetch-panel", children: [(!treeData || isConstraintsClassesTreeEmpty(treeData)) && (_jsx(BlankPanelPlaceholder, { text: "Add a scope for constraints", tooltipText: "Drag and drop properties here" })), treeData && !isConstraintsClassesTreeEmpty(treeData) && (_jsx(ConstraintsSelectionExplorer, { constraintsClasses: treeData, dataQualityState: dataQualityState, updateTreeData: updateTreeData }))] }) })); }); //# sourceMappingURL=DataQualityConstraintsSelection.js.map