@finos/legend-application-studio
Version:
Legend Studio application core
133 lines • 17.1 kB
JavaScript
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