UNPKG

@finos/legend-application-studio

Version:
133 lines 17.1 kB
import { jsx as _jsx, jsxs as _jsxs } 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 { BlankPanelPlaceholder, ContextMenu, MenuContent, MenuContentItem, PURE_FunctionIcon, PanelContent, PanelFormTextField, PlusIcon, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, TimesIcon, clsx, Panel, PanelHeader, PanelHeaderActions, PanelHeaderActionItem, PlayIcon, PanelTabs, } from '@finos/legend-art'; import { forwardRef, useEffect, useState } from 'react'; import { serviceValidation_setASsertionId, serviceValidation_setDescription, } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js'; import { InlineLambdaEditor } from '@finos/legend-query-builder'; import { flowResult } from 'mobx'; import { useApplicationStore } from '@finos/legend-application'; const ServicePostValidationAssertionEditor = observer((props) => { const { assertionState } = props; const servicePostValidationState = assertionState.postValidationState.servicePostValidationState; const serviceEditorState = servicePostValidationState.serviceEditorState; const postValState = assertionState.postValidationState; const hasParserError = postValState.hasParserError; const isReadOnly = serviceEditorState.isReadOnly; const assertion = assertionState.assertion; const errorMessage = assertion.id === '' ? `assertion ID can't be empty` : assertion.id.includes(' ') ? `assertion ID can't include spaced` : undefined; return (_jsxs("div", { className: "service-post-validation-editor__parameters", children: [_jsxs("div", { className: "service-post-validation-editor__header", children: [_jsxs("div", { className: "service-post-validation-editor__header__label", children: [_jsx(PURE_FunctionIcon, {}), _jsx("div", { className: "service-post-validation-editor__header__label__text", children: "Assertion" })] }), _jsx("div", { className: "service-post-validation-editor__header__label__actions", children: _jsx("div", { className: "service-post-validation-editor__header__label__action", children: _jsx("button", { className: "service-post-validation-editor__remove-btn btn--dark btn--caution", title: "Delete Assertion", disabled: isReadOnly, onClick: () => assertionState.postValidationState.deleteAssertion(assertion), tabIndex: -1, children: _jsx(TimesIcon, {}) }) }) })] }), _jsx(PanelFormTextField, { name: "ID", value: assertion.id, update: (value) => serviceValidation_setASsertionId(assertion, value ?? ''), errorMessage: errorMessage }), _jsx("div", { className: clsx('service-post-validation-editor__lambda-editor__container', { backdrop__element: hasParserError }), children: _jsx(InlineLambdaEditor, { className: "service-post-validation-editor__lambda-editor", disabled: isReadOnly || postValState.isRunningLambdaConversion, lambdaEditorState: assertionState, forceBackdrop: hasParserError }) })] })); }); const ServicePostValidationParameterEditor = observer((props) => { const { paramState } = props; const serviceEditorState = paramState.postValidationState.servicePostValidationState .serviceEditorState; const postValState = paramState.postValidationState; const hasParserError = postValState.hasParserError; const isReadOnly = serviceEditorState.isReadOnly; return (_jsxs("div", { children: [_jsxs("div", { className: "service-post-validation-editor__header", children: [_jsxs("div", { className: "service-post-validation-editor__header__label", children: [_jsx(PURE_FunctionIcon, {}), _jsx("div", { className: "service-post-validation-editor__header__label__text", children: "Parameter" })] }), _jsx("div", { className: "service-post-validation-editor__header__label__actions", children: _jsx("div", { className: "service-post-validation-editor__header__label__action", children: _jsx("button", { className: "service-post-validation-editor__remove-btn btn--dark btn--caution", title: "Delete Assertion", disabled: isReadOnly, onClick: () => paramState.postValidationState.deleteParam(paramState), tabIndex: -1, children: _jsx(TimesIcon, {}) }) }) })] }), _jsx("div", { className: clsx('service-post-validation-editor__lambda-editor__container', { backdrop__element: hasParserError }), children: _jsx(InlineLambdaEditor, { className: "service-post-validation-editor__lambda-editor", disabled: isReadOnly || postValState.isRunningLambdaConversion, lambdaEditorState: paramState, forceBackdrop: hasParserError }) })] })); }); const ServicePostValidationEditor = observer((props) => { const { postValidationState } = props; const serviceEditorState = postValidationState.servicePostValidationState.serviceEditorState; const editorStore = serviceEditorState.editorStore; const applicationStore = editorStore.applicationStore; const isReadOnly = serviceEditorState.isReadOnly; const validation = postValidationState.validation; const addParameter = () => { flowResult(postValidationState.addParameter()).catch(applicationStore.alertUnhandledError); }; const addAssertion = () => { flowResult(postValidationState.addAssertion()).catch(applicationStore.alertUnhandledError); }; useEffect(() => { flowResult(postValidationState.convertAssertionsLambdas()).catch(applicationStore.alertUnhandledError); flowResult(postValidationState.convertParameterLambdas()).catch(applicationStore.alertUnhandledError); }, [applicationStore, postValidationState]); return (_jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 150, minSize: 28, children: _jsxs("div", { className: "service-test-data-editor panel", children: [_jsx("div", { className: "service-test-suite-editor__header", children: _jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "General" }) }) }), _jsx("div", { className: "service-test-data-editor__data", children: _jsx(PanelFormTextField, { name: "Description", prompt: "post validation description", value: validation.description, update: (value) => serviceValidation_setDescription(validation, value ?? '') }) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { minSize: 56, children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 200, minSize: 28, children: _jsxs("div", { className: "service-test-data-editor panel", children: [_jsxs("div", { className: "service-test-suite-editor__header", children: [_jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "Parameters" }) }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "panel__header__action", tabIndex: -1, onClick: addParameter, title: "Add Parameter", children: _jsx(PlusIcon, {}) }) })] }), _jsxs("div", { className: "service-test-data-editor__data", children: [postValidationState.parametersState.map((aState) => (_jsx(ServicePostValidationParameterEditor, { paramState: aState }, aState.uuid))), !validation.parameters.length && (_jsx(BlankPanelPlaceholder, { text: "Add Parameter", onClick: addParameter, disabled: isReadOnly, clickActionType: "add", tooltipText: "Click to add parameter" }))] })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { minSize: 56, children: _jsxs("div", { className: "service-test-data-editor panel", children: [_jsxs("div", { className: "service-test-suite-editor__header", children: [_jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "Assertions" }) }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "panel__header__action", tabIndex: -1, onClick: addAssertion, title: "Add Assertion", children: _jsx(PlusIcon, {}) }) })] }), _jsxs("div", { className: "service-test-data-editor__data", children: [postValidationState.assertionStates.map((aState) => (_jsx(ServicePostValidationAssertionEditor, { assertionState: aState }, aState.uuid))), !validation.assertions.length && (_jsx(BlankPanelPlaceholder, { text: "Add Assertion", onClick: addAssertion, disabled: isReadOnly, clickActionType: "add", tooltipText: "Click to add assertion" }))] })] }) })] }) })] })); }); const PostValidationContextMenu = observer(forwardRef(function TestContainerContextMenu(props, ref) { const { add, _delete } = props; return (_jsxs(MenuContent, { ref: ref, children: [_jsx(MenuContentItem, { onClick: _delete, children: "Delete" }), _jsx(MenuContentItem, { onClick: add, children: "Add Post Validation" })] })); })); export const PostValidationItem = observer((props) => { const { postValidation, validationState, idx } = props; const serviceEditorState = validationState.serviceEditorState; const applicationStore = useApplicationStore(); const isReadOnly = serviceEditorState.isReadOnly; const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false); const isActive = validationState.selectedPostValidationState?.validation === postValidation; const openVal = () => validationState.changeValidation(postValidation); const add = () => validationState.addValidation(); const _delete = () => validationState.deleteValidation(postValidation); const onContextMenuOpen = () => setIsSelectedFromContextMenu(true); const onContextMenuClose = () => setIsSelectedFromContextMenu(false); const runVal = () => { flowResult(validationState.runVal()).catch(applicationStore.alertUnhandledError); }; return (_jsxs(ContextMenu, { className: clsx('testable-test-explorer__item', { 'testable-test-explorer__item--selected-from-context-menu': !isActive && isSelectedFromContextMenu, }, { 'testable-test-explorer__item--active': isActive }), disabled: isReadOnly, content: _jsx(PostValidationContextMenu, { add: add, _delete: _delete }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: [_jsx("button", { className: clsx('testable-test-explorer__item__label'), onClick: openVal, tabIndex: -1, children: _jsx("div", { className: "testable-test-explorer__item__label__text", children: `validation ${idx + 1}` }) }), _jsx("div", { className: "mapping-test-explorer__item__actions", children: _jsx("button", { className: "mapping-test-explorer__item__action mapping-test-explorer__run-test-btn", onClick: runVal, disabled: validationState.runningPostValidationAction.isInProgress, tabIndex: -1, title: `Validate ${idx + 1}`, children: _jsx(PlayIcon, {}) }) })] })); }); const ServicePostValidationResultViewer = observer((props) => { const { result } = props; const summaryType = result.violations.result.rows.length === 0 ? 'success' : 'fail'; return (_jsxs("div", { className: `testable-test-assertion-result__summary--${summaryType}`, children: [_jsxs("div", { className: "testable-test-assertion-result__summary-main", children: ["Assertion Result Summary (", summaryType, ")"] }), _jsxs("div", { className: "testable-test-assertion-result__summary-info", children: ["Id: ", result.id] }), _jsxs("div", { className: "testable-test-assertion-result__summary-info", children: ["Message: ", result.message] }), _jsxs("div", { className: "testable-test-assertion-result__summary-info", children: ["Violations: ", result.violations.result.rows.length] }), result.violations.result.rows.map((row) => (_jsx("div", { className: `testable-test-assertion-result__summary testable-test-assertion-result__summary--${summaryType}`, children: row.values.map((value, valueIndex) => (_jsxs("div", { className: "testable-test-assertion-result__summary-info", children: [result.violations.result.columns[valueIndex], ": ", value] }, `${result.violations.result.columns[valueIndex]}-${value}`))) }, result.id)))] })); }); const ServicePostValidationResultsViewer = observer((props) => { const { isInProgress, results } = props; return (_jsx("div", { className: "testable-test-assertion-result__summary", children: results ? results.map((result) => (_jsx(ServicePostValidationResultViewer, { result: result }, result.id))) : isInProgress ? 'Post validation(s) running...' : 'Run post validation(s) to see results' })); }); // TOD: Currently editor is a very basic editor. Can improve with the following: // 1. generate parameters using the query parameters (verify that those parameter values are used for execution) // most likely the parameter values should be consistent with other parameter value shapes such as service tests // 2. wire up engine api calls to generate validation as well as run the validations export const ServicePostValidationsEditor = observer((props) => { const { validationState } = props; const serviceEditorState = validationState.serviceEditorState; const service = serviceEditorState.service; const isReadOnly = serviceEditorState.isReadOnly; let POST_VALIDATION_TAB; (function (POST_VALIDATION_TAB) { POST_VALIDATION_TAB["SETUP"] = "SETUP"; POST_VALIDATION_TAB["ASSERTIONS"] = "ASSERTIONS"; })(POST_VALIDATION_TAB || (POST_VALIDATION_TAB = {})); const [selectedTab, setSelectedTab] = useState(POST_VALIDATION_TAB.SETUP); const addPostValidation = () => validationState.addValidation(); useEffect(() => { validationState.init(); }, [validationState]); useEffect(() => { if (validationState.runningPostValidationAction.isInProgress) { setSelectedTab(POST_VALIDATION_TAB.ASSERTIONS); } }, [ validationState.runningPostValidationAction.isInProgress, POST_VALIDATION_TAB.ASSERTIONS, ]); return (_jsxs("div", { className: "service-post-validation-editor", children: [_jsx(PanelHeader, { title: "Post validations" }), _jsx("div", { className: "service-test-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsxs(ResizablePanel, { minSize: 100, size: 300, children: [_jsxs(PanelHeader, { children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__label", children: "Post Validations" }) }), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { onClick: addPostValidation, title: "Add Post Validations", children: _jsx(PlusIcon, {}) }) })] }), _jsxs(PanelContent, { children: [service.postValidations.map((postValidation, _idx) => (_jsx(PostValidationItem, { postValidation: postValidation, validationState: validationState, idx: _idx }, postValidation.hashCode))), !service.postValidations.length && (_jsx(BlankPanelPlaceholder, { text: "Add Post Validation", onClick: addPostValidation, disabled: isReadOnly, clickActionType: "add", tooltipText: "Click to add post validation" }))] })] }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: _jsxs(Panel, { className: "service-test-editor", children: [_jsx(PanelTabs, { tabs: Object.keys(POST_VALIDATION_TAB), selectedTab: selectedTab, changeTab: (tab) => () => setSelectedTab(POST_VALIDATION_TAB[tab]), tabClassName: "panel__header__tab" }), selectedTab === POST_VALIDATION_TAB.SETUP ? (_jsxs(PanelContent, { className: "service-test-editor__content", children: [validationState.selectedPostValidationState && (_jsx(ServicePostValidationEditor, { postValidationState: validationState.selectedPostValidationState })), !service.postValidations.length && (_jsx(BlankPanelPlaceholder, { text: "Add Post Validation", onClick: addPostValidation, disabled: isReadOnly, clickActionType: "add", tooltipText: "Click to add post validation" }))] })) : null, selectedTab === POST_VALIDATION_TAB.ASSERTIONS ? (_jsx(PanelContent, { children: _jsx(ServicePostValidationResultsViewer, { isInProgress: validationState.runningPostValidationAction.isInProgress, results: validationState.postValidationAssertionResults }) })) : null] }) })] }) })] })); }); //# sourceMappingURL=ServicePostValidationEditor.js.map