diff --git a/components/bpmn-q/modeler-component/editor/ui/ConfirmationModal.js b/components/bpmn-q/modeler-component/editor/ui/ConfirmationModal.js
new file mode 100644
index 00000000..b0cf5651
--- /dev/null
+++ b/components/bpmn-q/modeler-component/editor/ui/ConfirmationModal.js
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2023 Institute of Architecture of Application Systems -
+ * University of Stuttgart
+ *
+ * This program and the accompanying materials are made available under the
+ * terms the Apache Software License 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import React from 'react';
+import Modal from '../ui/modal/Modal';
+
+// polyfill upcoming structural components
+const Title = Modal.Title || (({children}) =>
{children} );
+const Body = Modal.Body || (({children}) => {children}
);
+const Footer = Modal.Footer || (({children}) => {children}
);
+
+/**
+ * Modal component for confirming the discard of changes in the editor.
+ *
+ * @param onClose Function called when the modal is closed.
+ * @param onConfirm Function called when the "Yes" button is clicked to confirm discarding changes.
+ * @returns {JSX.Element} The modal as a React component.
+ * @constructor
+ */
+export default function ConfirmationModal({onClose, onConfirm}) {
+
+ return
+
+ Confirm Discard Changes
+
+
+ There are unsaved changes. Are you sure you want to discard all changes and generate a new diagram?
+
+
+ ;
+}
\ No newline at end of file
diff --git a/components/bpmn-q/modeler-component/editor/ui/NewDiagramButton.js b/components/bpmn-q/modeler-component/editor/ui/NewDiagramButton.js
index 2bff09b4..528a5467 100644
--- a/components/bpmn-q/modeler-component/editor/ui/NewDiagramButton.js
+++ b/components/bpmn-q/modeler-component/editor/ui/NewDiagramButton.js
@@ -1,25 +1,63 @@
-import React from "react";
-import { createNewDiagram } from "../util/IoUtilities";
+import React, { useState, useEffect } from 'react';
+import { createNewDiagram } from '../util/IoUtilities';
+import { getModeler } from '../ModelerHandler';
+import ConfirmationModal from './ConfirmationModal';
-/**
- * React button which creates a new workflow.
- *
- * @param props
- * @returns {JSX.Element}
- * @constructor
- */
export default function NewDiagramButton(props) {
- const { modeler } = props;
+ const { modeler } = props;
+ const [unsavedChanges, setUnsavedChanges] = useState(false);
+ const [showConfirmationModal, setShowConfirmationModal] = useState(false);
- return (
- createNewDiagram(modeler)}
- >
-
- New Diagram
-
-
- );
+ useEffect(() => {
+ if (unsavedChanges) {
+ setShowConfirmationModal(true);
+ } else {
+ createNewDiagram(modeler);
+ }
+ }, [unsavedChanges, modeler]);
+
+ const checkUnsavedChanges = () => {
+ getModeler().saveXML({ format: true }, function (err, xml) {
+ if (!err) {
+ let oldXml = getModeler().oldXml;
+ if (oldXml !== undefined) {
+ oldXml = oldXml.trim();
+ }
+ if (oldXml !== xml.trim() && oldXml !== undefined) {
+ setUnsavedChanges(true);
+ setShowConfirmationModal(true);
+ } else {
+ setShowConfirmationModal(false);
+ createNewDiagram(modeler);
+ }
+ }
+ });
+ };
+
+ const handleConfirmDiscard = () => {
+ createNewDiagram(modeler);
+ setUnsavedChanges(false);
+ setShowConfirmationModal(false);
+ };
+
+ const handleCancelDiscard = () => {
+ setShowConfirmationModal(false);
+ };
+
+ return (
+
+
+
+ New Diagram
+
+
+
+ {showConfirmationModal && (
+
+ )}
+
+ );
}
diff --git a/components/bpmn-q/modeler-component/editor/util/IoUtilities.js b/components/bpmn-q/modeler-component/editor/util/IoUtilities.js
index 7b8b4ecd..a15039ae 100644
--- a/components/bpmn-q/modeler-component/editor/util/IoUtilities.js
+++ b/components/bpmn-q/modeler-component/editor/util/IoUtilities.js
@@ -15,14 +15,14 @@ let FormData = require("form-data");
// workflow with a start event to use as template for new workflows
const NEW_DIAGRAM_XML =
'\n' +
- '\n' +
- ' \n' +
- ' \n' +
+ '\n' +
+ ' \n' +
+ ' \n' +
" \n" +
' \n' +
' \n' +
' \n' +
- ' \n' +
+ ' \n' +
" \n" +
" \n" +
" \n" +
@@ -72,8 +72,9 @@ export async function saveModelerAsLocalFile(
fileFormat === saveFileFormats.ALL
) {
if (openWindow) {
- await openFileDialog(xml, fileName, saveFileFormats.BPMN);
+ await openFileDialog(modeler, xml, fileName, saveFileFormats.BPMN);
} else {
+ modeler.oldXml = xml;
await saveXmlAsLocalFile(xml, fileName);
}
}
@@ -346,7 +347,7 @@ export async function saveWorkflowAsSVG(modeler, fileName, fileFormat) {
fileFormat === saveFileFormats.ALL ||
fileFormat === saveFileFormats.SVG
) {
- openFileDialog(svg, fileName, saveFileFormats.SVG);
+ openFileDialog(modeler, svg, fileName, saveFileFormats.SVG);
}
if (
fileFormat === saveFileFormats.ALL ||
@@ -378,7 +379,7 @@ function downloadPng(pngDataUrl, fileName, fileFormat) {
openFileUrlDialog(pngDataUrl, fileName, fileFormat);
}
-async function openFileDialog(content, fileName, fileFormat) {
+async function openFileDialog(modeler, content, fileName, fileFormat) {
let suggestedName = fileName;
if (suggestedName.includes(".bpmn")) {
suggestedName = fileName.split(".bpmn")[0];
@@ -398,6 +399,9 @@ async function openFileDialog(content, fileName, fileFormat) {
],
});
writeFile(fileHandle, content);
+ if (fileFormat === saveFileFormats.BPMN || fileFormat === saveFileFormats.ALL) {
+ modeler.oldXml = content;
+ }
}
async function openFileUrlDialog(content, fileName, fileFormat) {