From 12c8b899f04033116d89b3c2d2cd558df64a143d Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Tue, 14 Nov 2023 15:14:07 -0500 Subject: [PATCH] Copy and Paste Error (#663) * We were getting copy and paste errors that an id already existed. This fixes that problem by assuring we always call the importXML method on the diagram modeller (and don't bypass it with a call to the fromXML of the protected _moddle. we have to correct for the loop characteristics getting removed in a different way. * run_pyl. * eslint fixes * Cypress caught some errors - I hate it, but it was right, and it caught something critical. --- spiffworkflow-backend/.gitignore | 1 + .../src/components/ReactDiagramEditor.tsx | 113 +++++++++--------- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/spiffworkflow-backend/.gitignore b/spiffworkflow-backend/.gitignore index 0d420dae..ce2cc2de 100644 --- a/spiffworkflow-backend/.gitignore +++ b/spiffworkflow-backend/.gitignore @@ -22,3 +22,4 @@ node_modules /local_wheels/*.whl /some_cache_dir /process.json +/keycloak diff --git a/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx b/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx index 1f4f050f..35e6f1cd 100644 --- a/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx +++ b/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx @@ -15,7 +15,7 @@ import { // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'dmn-... Remove this comment to see the full error message } from 'dmn-js-properties-panel'; -import React, { useRef, useEffect, useState } from 'react'; +import React, { useRef, useEffect, useState, useCallback } from 'react'; // @ts-ignore import { Button, ButtonSet, Modal, UnorderedList, Link } from '@carbon/react'; @@ -145,6 +145,59 @@ export default function ReactDiagramEditor({ const [showingReferences, setShowingReferences] = useState(false); + const zoom = useCallback( + (amount: number) => { + if (diagramModelerState) { + let modeler = diagramModelerState as any; + if (diagramType === 'dmn') { + modeler = (diagramModelerState as any).getActiveViewer(); + } + try { + if (amount === 0) { + const canvas = (modeler as any).get('canvas'); + canvas.zoom(FitViewport, 'auto'); + } else { + modeler.get('zoomScroll').stepZoom(amount); + } + } catch (e) { + console.log( + 'zoom failed, certain modes in DMN do not support zooming.', + e + ); + } + } + }, + [diagramModelerState, diagramType] + ); + + /* This restores unresolved references that camunda removes, I wish we could move this to the bpmn-io extensions */ + // @ts-ignore + const fixUnresolvedReferences = (diagramModelerToUse: any): null => { + // @ts-ignore + diagramModelerToUse.on('import.parse.complete', event => { // eslint-disable-line + // @ts-ignore + if (!event.references) return; + const refs = event.references.filter( + (r: any) => + r.property === 'bpmn:loopDataInputRef' || + r.property === 'bpmn:loopDataOutputRef' + ); + // eslint-disable-next-line no-underscore-dangle + const desc = diagramModelerToUse._moddle.registry.getEffectiveDescriptor( + 'bpmn:ItemAwareElement' + ); + refs.forEach((ref: any) => { + const props = { + id: ref.id, + name: ref.id ? typeof ref.name === 'undefined' : ref.name, + }; + const elem = diagramModelerToUse._moddle.create(desc, props); // eslint-disable-line no-underscore-dangle + elem.$parent = ref.element; + ref.element.set(ref.property, elem); + }); + }); + }; + useEffect(() => { if (diagramModelerState) { return; @@ -473,38 +526,11 @@ export default function ReactDiagramEditor({ if (alreadyImportedXmlRef.current) { return; } - if (diagramType === 'bpmn') { - diagramModelerToUse._moddle // eslint-disable-line no-underscore-dangle - .fromXML(diagramXMLToDisplay) - .then((result: any) => { - const refs = result.references.filter( - (r: any) => - r.property === 'bpmn:loopDataInputRef' || - r.property === 'bpmn:loopDataOutputRef' - ); - const desc = - diagramModelerToUse._moddle.registry.getEffectiveDescriptor( // eslint-disable-line - 'bpmn:ItemAwareElement' - ); - refs.forEach((ref: any) => { - const props = { - id: ref.id, - name: ref.id ? typeof ref.name === 'undefined' : ref.name, - }; - const elem = diagramModelerToUse._moddle.create(desc, props); // eslint-disable-line no-underscore-dangle - elem.$parent = ref.element; - ref.element.set(ref.property, elem); - }); - diagramModelerToUse.importDefinitions(result.rootElement); - console.log( - 'Zooming the viewport for bpmn at the end of displayDiagram' - ); - diagramModelerToUse.get('canvas').zoom(FitViewport, 'auto'); - }); - } else { - diagramModelerToUse.importXML(diagramXMLToDisplay); + diagramModelerToUse.importXML(diagramXMLToDisplay); + zoom(0); + if (diagramType !== 'dmn') { + fixUnresolvedReferences(diagramModelerToUse); } - alreadyImportedXmlRef.current = true; } @@ -571,6 +597,7 @@ export default function ReactDiagramEditor({ performingXmlUpdates, processModelId, url, + zoom, ]); function handleSave() { @@ -727,28 +754,6 @@ export default function ReactDiagramEditor({ return null; }; - const zoom = (amount: number) => { - if (diagramModelerState) { - let modeler = diagramModelerState as any; - if (diagramType === 'dmn') { - modeler = (diagramModelerState as any).getActiveViewer(); - } - try { - if (amount === 0) { - const canvas = (modeler as any).get('canvas'); - canvas.zoom(FitViewport, 'auto'); - } else { - modeler.get('zoomScroll').stepZoom(amount); - } - } catch (e) { - console.log( - 'zoom failed, certain modes in DMN do not support zooming.', - e - ); - } - } - }; - const diagramControlButtons = () => { // align the iconDescription to the bottom so it doesn't cover up the Save button // when mousing through them