Feature/upgrade react router dom (#1050)
* updated react-router-dom to match react-router version w/ burnettk * disable save button on process model edit diagram page unless a change has been made w/ burnettk * remove web components from form data on extensions page to avoid potential errors w/ burnettk * updates based on coderabbit w/ burnettk * fixed cypress issues --------- Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
9b8cb58e99
commit
73df645408
|
@ -36,7 +36,7 @@ const updateDmnText = (oldText, newText, elementId = 'wonderful_process') => {
|
|||
// wait for a little bit for the xml to get set before saving
|
||||
// FIXME: gray out save button or add spinner while xml is loading
|
||||
cy.wait(500);
|
||||
cy.contains('Save').click();
|
||||
cy.getBySel('process-model-file-save-button').click();
|
||||
};
|
||||
|
||||
const updateBpmnPythonScript = (pythonScript, elementId = 'process_script') => {
|
||||
|
@ -47,7 +47,7 @@ const updateBpmnPythonScript = (pythonScript, elementId = 'process_script') => {
|
|||
|
||||
// wait for a little bit for the xml to get set before saving
|
||||
cy.wait(500);
|
||||
cy.contains('Save').click();
|
||||
cy.getBySel('process-model-file-save-button').click();
|
||||
};
|
||||
|
||||
// NOTE: anytime the status dropdown box is clicked on, click off of it
|
||||
|
|
|
@ -82,7 +82,8 @@ describe('process-models', () => {
|
|||
cy.get('#bio-properties-panel-name').clear();
|
||||
cy.get('#bio-properties-panel-name').type('Start Event Name');
|
||||
cy.wait(500);
|
||||
cy.contains('Save').click();
|
||||
cy.getBySel('process-model-file-changed');
|
||||
cy.getBySel('process-model-file-save-button').click();
|
||||
cy.contains('Start Event Name');
|
||||
cy.get(fileNameInputSelector).type(bpmnFileName);
|
||||
cy.contains(saveChangesButtonText).click();
|
||||
|
@ -101,7 +102,7 @@ describe('process-models', () => {
|
|||
cy.get('#bio-properties-panel-id').clear();
|
||||
cy.get('#bio-properties-panel-id').type(decisionAcceptanceTestId);
|
||||
cy.contains('General').click();
|
||||
cy.contains('Save').click();
|
||||
cy.getBySel('process-model-file-save-button').click();
|
||||
cy.get(fileNameInputSelector).type(dmnFileName);
|
||||
cy.contains(saveChangesButtonText).click();
|
||||
cy.contains(`Process Model File: ${dmnFileName}`);
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
"react-icons": "^5.0.1",
|
||||
"react-jsonschema-form": "^1.8.1",
|
||||
"react-router": "^6.22.0",
|
||||
"react-router-dom": "6.3.0",
|
||||
"react-router-dom": "^6.22.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"serve": "^14.0.0",
|
||||
"timepicker": "^1.13.18",
|
||||
|
@ -15604,14 +15604,6 @@
|
|||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
"integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.6"
|
||||
}
|
||||
},
|
||||
"node_modules/hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
|
@ -26244,29 +26236,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz",
|
||||
"integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==",
|
||||
"version": "6.22.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
|
||||
"integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
|
||||
"dependencies": {
|
||||
"history": "^5.2.0",
|
||||
"react-router": "6.3.0"
|
||||
"@remix-run/router": "1.15.0",
|
||||
"react-router": "6.22.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom/node_modules/react-router": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz",
|
||||
"integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==",
|
||||
"dependencies": {
|
||||
"history": "^5.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-scripts": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||
|
@ -45705,14 +45689,6 @@
|
|||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
"integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.7.6"
|
||||
}
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
|
@ -53463,22 +53439,12 @@
|
|||
}
|
||||
},
|
||||
"react-router-dom": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz",
|
||||
"integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==",
|
||||
"version": "6.22.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
|
||||
"integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
|
||||
"requires": {
|
||||
"history": "^5.2.0",
|
||||
"react-router": "6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-router": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz",
|
||||
"integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==",
|
||||
"requires": {
|
||||
"history": "^5.2.0"
|
||||
}
|
||||
}
|
||||
"@remix-run/router": "1.15.0",
|
||||
"react-router": "6.22.0"
|
||||
}
|
||||
},
|
||||
"react-scripts": {
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"react-icons": "^5.0.1",
|
||||
"react-jsonschema-form": "^1.8.1",
|
||||
"react-router": "^6.22.0",
|
||||
"react-router-dom": "6.3.0",
|
||||
"react-router-dom": "^6.22.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"serve": "^14.0.0",
|
||||
"timepicker": "^1.13.18",
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { defineAbility } from '@casl/ability';
|
||||
import React from 'react';
|
||||
|
||||
|
@ -10,14 +9,11 @@ export default function App() {
|
|||
const ability = defineAbility(() => {});
|
||||
return (
|
||||
<div className="cds--white">
|
||||
{/* @ts-ignore */}
|
||||
<AbilityContext.Provider value={ability}>
|
||||
<APIErrorProvider>
|
||||
<BrowserRouter>
|
||||
<AbilityContext.Provider value={ability}>
|
||||
<ContainerForExtensions />
|
||||
</BrowserRouter>
|
||||
</APIErrorProvider>
|
||||
</AbilityContext.Provider>
|
||||
</APIErrorProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Content } from '@carbon/react';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
|
||||
|
@ -100,33 +100,32 @@ export default function ContainerForExtensions() {
|
|||
]);
|
||||
|
||||
const routeComponents = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<BaseRoutes extensionUxElements={extensionUxElements} />}
|
||||
/>
|
||||
<Route path="/editor/*" element={<EditorRoutes />} />
|
||||
<Route path="/extensions/:page_identifier" element={<Extension />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
</Routes>
|
||||
);
|
||||
return [
|
||||
{
|
||||
path: '*',
|
||||
element: <BaseRoutes extensionUxElements={extensionUxElements} />,
|
||||
},
|
||||
{ path: 'editor/*', element: <EditorRoutes /> },
|
||||
{ path: 'extensions/:page_identifier', element: <Extension /> },
|
||||
{ path: 'login', element: <Login /> },
|
||||
];
|
||||
};
|
||||
|
||||
const backendIsDownPage = () => {
|
||||
return <BackendIsDown />;
|
||||
return [<BackendIsDown />];
|
||||
};
|
||||
|
||||
const innerComponents = () => {
|
||||
if (backendIsUp === null) {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
if (backendIsUp) {
|
||||
return routeComponents();
|
||||
return <Outlet />;
|
||||
}
|
||||
return backendIsDownPage();
|
||||
};
|
||||
|
||||
const layout = () => {
|
||||
return (
|
||||
<>
|
||||
<NavigationBar extensionUxElements={extensionUxElements} />;
|
||||
|
@ -138,4 +137,14 @@ export default function ContainerForExtensions() {
|
|||
</Content>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '*',
|
||||
Component: layout,
|
||||
children: routeComponents(),
|
||||
},
|
||||
]);
|
||||
return <RouterProvider router={router} />;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import MDEditor from '@uiw/react-md-editor';
|
||||
import FormattingService from '../services/FormattingService';
|
||||
|
||||
export default function MarkdownRenderer(props: any) {
|
||||
const { source } = props;
|
||||
const newMarkdown = FormattingService.checkForSpiffFormats(source);
|
||||
let wrapperClassName = '';
|
||||
const propsToUse = props;
|
||||
if ('wrapperClassName' in propsToUse) {
|
||||
|
@ -10,7 +13,7 @@ export default function MarkdownRenderer(props: any) {
|
|||
return (
|
||||
<div data-color-mode="light" className={wrapperClassName}>
|
||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||
<MDEditor.Markdown {...propsToUse} />
|
||||
<MDEditor.Markdown {...{ ...propsToUse, ...{ source: newMarkdown } }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from '@carbon/icons-react';
|
||||
// @ts-ignore
|
||||
import { Button } from '@carbon/react';
|
||||
import { ObjectWithStringKeysAndValues } from '../interfaces';
|
||||
|
||||
type OwnProps = {
|
||||
title: string;
|
||||
|
@ -17,6 +18,7 @@ type OwnProps = {
|
|||
allowTogglingFullMessage?: boolean;
|
||||
timeout?: number;
|
||||
withBottomMargin?: boolean;
|
||||
'data-qa'?: string;
|
||||
};
|
||||
|
||||
export function Notification({
|
||||
|
@ -28,6 +30,7 @@ export function Notification({
|
|||
allowTogglingFullMessage = false,
|
||||
timeout,
|
||||
withBottomMargin = true,
|
||||
'data-qa': dataQa,
|
||||
}: OwnProps) {
|
||||
const [showMessage, setShowMessage] = useState<boolean>(
|
||||
!allowTogglingFullMessage
|
||||
|
@ -48,8 +51,15 @@ export function Notification({
|
|||
classes = `${classes} with-bottom-margin`;
|
||||
}
|
||||
|
||||
const additionalProps: ObjectWithStringKeysAndValues = {};
|
||||
if (dataQa) {
|
||||
additionalProps['data-qa'] = dataQa;
|
||||
}
|
||||
|
||||
return (
|
||||
<div role="status" className={classes}>
|
||||
// we control the props added to the variable so we know it's fine
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
<div role="status" className={classes} {...additionalProps}>
|
||||
<div className="cds--inline-notification__details">
|
||||
<div className="cds--inline-notification__text-wrapper">
|
||||
{iconComponent}
|
||||
|
|
|
@ -91,6 +91,7 @@ type OwnProps = {
|
|||
url?: string;
|
||||
callers?: ProcessReference[];
|
||||
activeUserElement?: React.ReactElement;
|
||||
disableSaveButton?: boolean;
|
||||
};
|
||||
|
||||
const FitViewport = 'fit-viewport';
|
||||
|
@ -121,6 +122,7 @@ export default function ReactDiagramEditor({
|
|||
url,
|
||||
callers,
|
||||
activeUserElement,
|
||||
disableSaveButton,
|
||||
}: OwnProps) {
|
||||
const [diagramXMLString, setDiagramXMLString] = useState('');
|
||||
const [diagramModelerState, setDiagramModelerState] = useState(null);
|
||||
|
@ -708,7 +710,13 @@ export default function ReactDiagramEditor({
|
|||
a={targetUris.processModelFileShowPath}
|
||||
ability={ability}
|
||||
>
|
||||
<Button onClick={handleSave}>Save</Button>
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={disableSaveButton}
|
||||
data-qa="process-model-file-save-button"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Can>
|
||||
<Can
|
||||
I="DELETE"
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* See below for more details.
|
||||
*/
|
||||
|
||||
import { FunctionComponent } from 'react';
|
||||
|
||||
// Current version of the extension uischema.
|
||||
export type ExtensionUiSchemaVersion = '0.1' | '0.2';
|
||||
|
||||
|
@ -210,4 +212,8 @@ export interface ExtensionApiResponse {
|
|||
// The markdown string rendered from the process model.
|
||||
rendered_results_markdown?: string;
|
||||
}
|
||||
|
||||
export type SupportedComponentList = {
|
||||
[key in keyof typeof UiSchemaPageComponentList]: FunctionComponent<any>;
|
||||
};
|
||||
/** ************************************* */
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
* These hooks re-implement the now removed useBlocker and usePrompt hooks in 'react-router-dom'.
|
||||
* Thanks for the idea @piecyk https://github.com/remix-run/react-router/issues/8139#issuecomment-953816315
|
||||
* Source: https://github.com/remix-run/react-router/commit/256cad70d3fd4500b1abcfea66f3ee622fb90874#diff-b60f1a2d4276b2a605c05e19816634111de2e8a4186fe9dd7de8e344b65ed4d3L344-L381
|
||||
*/
|
||||
|
||||
import { useCallback, useContext, useEffect } from 'react';
|
||||
import { UNSAFE_NavigationContext as NavigationContext } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* Blocks all navigation attempts. This is useful for preventing the page from
|
||||
* changing until some condition is met, like saving form data.
|
||||
*
|
||||
* @param blocker
|
||||
* @param when
|
||||
* @see https://reactrouter.com/api/useBlocker
|
||||
*/
|
||||
export function useBlocker(blocker: any, when: any = true) {
|
||||
const { navigator } = useContext(NavigationContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (!when) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const unblock = (navigator as any).block((tx: any) => {
|
||||
const autoUnblockingTx = {
|
||||
...tx,
|
||||
retry() {
|
||||
// Automatically unblock the transition so it can play all the way
|
||||
// through before retrying it. TODO: Figure out how to re-enable
|
||||
// this block if the transition is cancelled for some reason.
|
||||
unblock();
|
||||
tx.retry();
|
||||
},
|
||||
};
|
||||
|
||||
blocker(autoUnblockingTx);
|
||||
});
|
||||
|
||||
return unblock;
|
||||
}, [navigator, blocker, when]);
|
||||
}
|
||||
/**
|
||||
* Prompts the user with an Alert before they leave the current screen.
|
||||
*
|
||||
* @param message
|
||||
* @param when
|
||||
*/
|
||||
export function usePrompt(message: any, when: any = true) {
|
||||
const blocker = useCallback(
|
||||
(tx: any) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (window.confirm(message)) {
|
||||
tx.retry();
|
||||
}
|
||||
},
|
||||
[message]
|
||||
);
|
||||
|
||||
useBlocker(blocker, when);
|
||||
}
|
|
@ -148,9 +148,6 @@ export interface ProcessReference {
|
|||
}
|
||||
|
||||
export type ObjectWithStringKeysAndValues = { [key: string]: string };
|
||||
export type ObjectWithStringKeysAndFunctionValues = {
|
||||
[key: string]: Function;
|
||||
};
|
||||
|
||||
export interface FilterOperator {
|
||||
id: string;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Routes, Route, useLocation } from 'react-router-dom';
|
||||
import { useLocation, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import ProcessModelEditDiagram from './ProcessModelEditDiagram';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
import LoginHandler from '../components/LoginHandler';
|
||||
import ProcessModelEditDiagram from './ProcessModelEditDiagram';
|
||||
|
||||
export default function EditorRoutes() {
|
||||
const location = useLocation();
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { createElement, useCallback, useEffect, useState } from 'react';
|
||||
import { useParams, useSearchParams } from 'react-router-dom';
|
||||
import { Editor } from '@monaco-editor/react';
|
||||
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||
import {
|
||||
ObjectWithStringKeysAndFunctionValues,
|
||||
ProcessFile,
|
||||
ProcessModel,
|
||||
} from '../interfaces';
|
||||
import { ProcessFile, ProcessModel } from '../interfaces';
|
||||
import HttpService from '../services/HttpService';
|
||||
import useAPIError from '../hooks/UseApiError';
|
||||
import { recursivelyChangeNullAndUndefined, makeid } from '../helpers';
|
||||
|
@ -16,6 +12,7 @@ import {
|
|||
ExtensionApiResponse,
|
||||
ExtensionPostBody,
|
||||
ExtensionUiSchema,
|
||||
SupportedComponentList,
|
||||
UiSchemaPageComponent,
|
||||
UiSchemaPageDefinition,
|
||||
} from '../extension_ui_schema_interfaces';
|
||||
|
@ -65,7 +62,7 @@ export default function Extension({
|
|||
|
||||
const { addError, removeError } = useAPIError();
|
||||
|
||||
const supportedComponents: ObjectWithStringKeysAndFunctionValues = {
|
||||
const supportedComponents: SupportedComponentList = {
|
||||
CreateNewInstance,
|
||||
CustomForm,
|
||||
MarkdownRenderer,
|
||||
|
@ -98,7 +95,6 @@ export default function Extension({
|
|||
);
|
||||
const processLoadResult = useCallback(
|
||||
(result: ExtensionApiResponse, pageDefinition: UiSchemaPageDefinition) => {
|
||||
setFormData(result.task_data);
|
||||
if (pageDefinition.navigate_to_on_load) {
|
||||
const optionString = interpolateNavigationString(
|
||||
pageDefinition.navigate_to_on_load,
|
||||
|
@ -114,6 +110,8 @@ export default function Extension({
|
|||
);
|
||||
setMarkdownToRenderOnLoad(newMarkdown);
|
||||
}
|
||||
|
||||
const taskDataCopy = { ...result.task_data };
|
||||
if (
|
||||
pageDefinition.on_load &&
|
||||
pageDefinition.on_load.ui_schema_page_components_variable
|
||||
|
@ -123,7 +121,18 @@ export default function Extension({
|
|||
pageDefinition.on_load.ui_schema_page_components_variable
|
||||
]
|
||||
);
|
||||
|
||||
// we were getting any AJV8Validator error when we had this data in the task data
|
||||
// when we attempted to submit a form using this task data.
|
||||
// The error was:
|
||||
// Uncaught RangeError: Maximum call stack size exceeded
|
||||
//
|
||||
// Removing the ui schema page components dictionary seems to resolve it.
|
||||
delete taskDataCopy[
|
||||
pageDefinition.on_load.ui_schema_page_components_variable
|
||||
];
|
||||
}
|
||||
setFormData(taskDataCopy);
|
||||
setReadyForComponentsToDisplay(true);
|
||||
},
|
||||
[interpolateNavigationString]
|
||||
|
@ -303,7 +312,7 @@ export default function Extension({
|
|||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
const renderComponentArguments = (component: UiSchemaPageComponent) => {
|
||||
const argumentsForComponent: any = component.arguments;
|
||||
if (processModel) {
|
||||
if (processModel && argumentsForComponent) {
|
||||
Object.keys(argumentsForComponent).forEach((argName: string) => {
|
||||
const argValue = argumentsForComponent[argName];
|
||||
if (
|
||||
|
@ -368,7 +377,10 @@ export default function Extension({
|
|||
if (supportedComponents[componentName]) {
|
||||
const argumentsForComponent = renderComponentArguments(component);
|
||||
componentsToDisplay.push(
|
||||
supportedComponents[componentName](argumentsForComponent)
|
||||
createElement(
|
||||
supportedComponents[componentName],
|
||||
argumentsForComponent
|
||||
)
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
|
|
|
@ -47,7 +47,6 @@ import {
|
|||
} from '../interfaces';
|
||||
import ProcessSearch from '../components/ProcessSearch';
|
||||
import { Notification } from '../components/Notification';
|
||||
import { usePrompt } from '../hooks/UsePrompt';
|
||||
import ActiveUsers from '../components/ActiveUsers';
|
||||
import { useFocusedTabStatus } from '../hooks/useFocusedTabStatus';
|
||||
|
||||
|
@ -137,8 +136,6 @@ export default function ProcessModelEditDiagram() {
|
|||
|
||||
const [callers, setCallers] = useState<ProcessReference[]>([]);
|
||||
|
||||
usePrompt('Changes you made may not be saved.', diagramHasChanges);
|
||||
|
||||
const getProcessesCallback = useCallback((onProcessesFetched?: Function) => {
|
||||
const processResults = (result: any) => {
|
||||
const selectionArray = result.map((item: any) => {
|
||||
|
@ -1054,7 +1051,7 @@ export default function ProcessModelEditDiagram() {
|
|||
path = generatePath(
|
||||
'/editor/process-models/:process_model_id/files/:file_name',
|
||||
{
|
||||
process_model_id: params.process_model_id,
|
||||
process_model_id: params.process_model_id || null,
|
||||
file_name: file.name,
|
||||
}
|
||||
);
|
||||
|
@ -1063,7 +1060,7 @@ export default function ProcessModelEditDiagram() {
|
|||
path = generatePath(
|
||||
'/editor/process-models/:process_model_id/files?file_type=dmn',
|
||||
{
|
||||
process_model_id: params.process_model_id,
|
||||
process_model_id: params.process_model_id || null,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1121,6 +1118,7 @@ export default function ProcessModelEditDiagram() {
|
|||
onElementsChanged={onElementsChanged}
|
||||
callers={callers}
|
||||
activeUserElement={<ActiveUsers />}
|
||||
disableSaveButton={!diagramHasChanges}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -1131,6 +1129,8 @@ export default function ProcessModelEditDiagram() {
|
|||
<Notification
|
||||
title="File Saved: "
|
||||
onClose={() => setDisplaySaveFileMessage(false)}
|
||||
hideCloseButton
|
||||
timeout={3000}
|
||||
>
|
||||
Changes to the file were saved.
|
||||
</Notification>
|
||||
|
@ -1139,6 +1139,34 @@ export default function ProcessModelEditDiagram() {
|
|||
return null;
|
||||
};
|
||||
|
||||
const unsavedChangesMessage = () => {
|
||||
if (diagramHasChanges) {
|
||||
return (
|
||||
<Notification
|
||||
title="Unsaved changes."
|
||||
type="error"
|
||||
hideCloseButton
|
||||
data-qa="process-model-file-changed"
|
||||
>
|
||||
Please save to avoid losing your work.
|
||||
</Notification>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const pageModals = () => {
|
||||
return (
|
||||
<>
|
||||
{newFileNameBox()}
|
||||
{scriptEditorAndTests()}
|
||||
{markdownEditor()}
|
||||
{jsonSchemaEditor()}
|
||||
{processModelSelector()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// if a file name is not given then this is a new model and the ReactDiagramEditor component will handle it
|
||||
if ((bpmnXmlForDiagramRendering || !params.file_name) && processModel) {
|
||||
const processModelFileName = processModelFile ? processModelFile.name : '';
|
||||
|
@ -1159,13 +1187,13 @@ export default function ProcessModelEditDiagram() {
|
|||
Process Model File{processModelFile ? ': ' : ''}
|
||||
{processModelFileName}
|
||||
</h1>
|
||||
|
||||
{pageModals()}
|
||||
|
||||
{unsavedChangesMessage()}
|
||||
{saveFileMessage()}
|
||||
|
||||
{appropriateEditor()}
|
||||
{newFileNameBox()}
|
||||
{scriptEditorAndTests()}
|
||||
{markdownEditor()}
|
||||
{jsonSchemaEditor()}
|
||||
{processModelSelector()}
|
||||
<div id="diagram-container" />
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue