do not navigate away from diagram editor page if there are changes w/ burnettk
This commit is contained in:
parent
26de48193c
commit
7b78ff42da
|
@ -57,6 +57,7 @@
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
"react-jsonschema-form": "^1.8.1",
|
"react-jsonschema-form": "^1.8.1",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
|
"react-router": "^6.3.0",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
"react-jsonschema-form": "^1.8.1",
|
"react-jsonschema-form": "^1.8.1",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
|
"react-router": "^6.3.0",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"serve": "^14.0.0",
|
"serve": "^14.0.0",
|
||||||
|
|
|
@ -84,6 +84,7 @@ type OwnProps = {
|
||||||
onJsonFilesRequested?: (..._args: any[]) => any;
|
onJsonFilesRequested?: (..._args: any[]) => any;
|
||||||
onDmnFilesRequested?: (..._args: any[]) => any;
|
onDmnFilesRequested?: (..._args: any[]) => any;
|
||||||
onSearchProcessModels?: (..._args: any[]) => any;
|
onSearchProcessModels?: (..._args: any[]) => any;
|
||||||
|
onElementsChanged?: (..._args: any[]) => any;
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,6 +110,7 @@ export default function ReactDiagramEditor({
|
||||||
onJsonFilesRequested,
|
onJsonFilesRequested,
|
||||||
onDmnFilesRequested,
|
onDmnFilesRequested,
|
||||||
onSearchProcessModels,
|
onSearchProcessModels,
|
||||||
|
onElementsChanged,
|
||||||
url,
|
url,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const [diagramXMLString, setDiagramXMLString] = useState('');
|
const [diagramXMLString, setDiagramXMLString] = useState('');
|
||||||
|
@ -291,6 +293,11 @@ export default function ReactDiagramEditor({
|
||||||
diagramModeler.on('element.click', (element: any) => {
|
diagramModeler.on('element.click', (element: any) => {
|
||||||
handleElementClick(element);
|
handleElementClick(element);
|
||||||
});
|
});
|
||||||
|
diagramModeler.on('elements.changed', (event: any) => {
|
||||||
|
if (onElementsChanged) {
|
||||||
|
onElementsChanged(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
diagramModeler.on('spiff.service_tasks.requested', (event: any) => {
|
diagramModeler.on('spiff.service_tasks.requested', (event: any) => {
|
||||||
handleServiceTasksRequested(event);
|
handleServiceTasksRequested(event);
|
||||||
|
@ -330,6 +337,7 @@ export default function ReactDiagramEditor({
|
||||||
onJsonFilesRequested,
|
onJsonFilesRequested,
|
||||||
onDmnFilesRequested,
|
onDmnFilesRequested,
|
||||||
onSearchProcessModels,
|
onSearchProcessModels,
|
||||||
|
onElementsChanged,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* 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 null;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -35,11 +35,13 @@ import {
|
||||||
} from '../interfaces';
|
} from '../interfaces';
|
||||||
import ProcessSearch from '../components/ProcessSearch';
|
import ProcessSearch from '../components/ProcessSearch';
|
||||||
import { Notification } from '../components/Notification';
|
import { Notification } from '../components/Notification';
|
||||||
|
import { usePrompt } from '../hooks/UsePrompt';
|
||||||
|
|
||||||
export default function ProcessModelEditDiagram() {
|
export default function ProcessModelEditDiagram() {
|
||||||
const [showFileNameEditor, setShowFileNameEditor] = useState(false);
|
const [showFileNameEditor, setShowFileNameEditor] = useState(false);
|
||||||
const handleShowFileNameEditor = () => setShowFileNameEditor(true);
|
const handleShowFileNameEditor = () => setShowFileNameEditor(true);
|
||||||
const [processModel, setProcessModel] = useState<ProcessModel | null>(null);
|
const [processModel, setProcessModel] = useState<ProcessModel | null>(null);
|
||||||
|
const [diagramHasChanges, setDiagramHasChanges] = useState<boolean>(false);
|
||||||
|
|
||||||
const [scriptText, setScriptText] = useState<string>('');
|
const [scriptText, setScriptText] = useState<string>('');
|
||||||
const [scriptType, setScriptType] = useState<string>('');
|
const [scriptType, setScriptType] = useState<string>('');
|
||||||
|
@ -112,6 +114,8 @@ export default function ProcessModelEditDiagram() {
|
||||||
|
|
||||||
const processModelPath = `process-models/${modifiedProcessModelId}`;
|
const processModelPath = `process-models/${modifiedProcessModelId}`;
|
||||||
|
|
||||||
|
usePrompt('Changes you made may not be saved.', diagramHasChanges);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Grab all available process models in case we need to search for them.
|
// Grab all available process models in case we need to search for them.
|
||||||
// Taken from the Process Group List
|
// Taken from the Process Group List
|
||||||
|
@ -206,6 +210,11 @@ export default function ProcessModelEditDiagram() {
|
||||||
// after saving the file, make sure we null out newFileName
|
// after saving the file, make sure we null out newFileName
|
||||||
// so it does not get used over the params
|
// so it does not get used over the params
|
||||||
setNewFileName('');
|
setNewFileName('');
|
||||||
|
setDiagramHasChanges(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onElementsChanged = () => {
|
||||||
|
setDiagramHasChanges(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteFile = (fileName = params.file_name) => {
|
const onDeleteFile = (fileName = params.file_name) => {
|
||||||
|
@ -922,6 +931,7 @@ export default function ProcessModelEditDiagram() {
|
||||||
onLaunchDmnEditor={onLaunchDmnEditor}
|
onLaunchDmnEditor={onLaunchDmnEditor}
|
||||||
onDmnFilesRequested={onDmnFilesRequested}
|
onDmnFilesRequested={onDmnFilesRequested}
|
||||||
onSearchProcessModels={onSearchProcessModels}
|
onSearchProcessModels={onSearchProcessModels}
|
||||||
|
onElementsChanged={onElementsChanged}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue