diff --git a/package-lock.json b/package-lock.json
index dc0c3c5..1792581 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
+ "axios": "^0.27.2",
"bpmn-js": "^9.1.0",
"bpmn-js-properties-panel": "^1.1.1",
"react": "^18.1.0",
@@ -4691,6 +4692,28 @@
"node": ">=12"
}
},
+ "node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/axios/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -19921,6 +19944,27 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz",
"integrity": "sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA=="
},
+ "axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "requires": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ },
+ "dependencies": {
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
+ }
+ },
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
diff --git a/package.json b/package.json
index f7d6a99..9a5ab7a 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
+ "axios": "^0.27.2",
"bpmn-js": "^9.1.0",
"bpmn-js-properties-panel": "^1.1.1",
"react": "^18.1.0",
diff --git a/src/App.js b/src/App.js
index 7cb686e..fe426bc 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,12 +1,19 @@
// import logo from './logo.svg';
-import './App.css';
-import BpmnModeler from 'bpmn-js';
-import {
- BpmnPropertiesPanelModule,
- BpmnPropertiesProviderModule,
-} from 'bpmn-js-properties-panel';
+// import './App.css';
+// import BpmnModeler from 'bpmn-js';
+// import {
+// BpmnPropertiesPanelModule,
+// BpmnPropertiesProviderModule,
+// } from 'bpmn-js-properties-panel';
+//
+import React, { useEffect, useState } from "react";
+import Modeler from "bpmn-js/lib/Modeler";
+import "bpmn-js/dist/assets/diagram-js.css";
+import "bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
+import axios from "axios";
+import ReactEditor from "./react_editor"
-function App(props) {
+function App() {
// return (
//
//
@@ -25,6 +32,146 @@ function App(props) {
//
//
// );
+
+ // from spiff backend
+ // const bpmnModeler = new BpmnModeler({
+ // container: '#canvas',
+ // propertiesPanel: {
+ // parent: '#properties'
+ // },
+ // additionalModules: [
+ // BpmnPropertiesPanelModule,
+ // BpmnPropertiesProviderModule
+ // ]
+ // });
+ //
+ // async function exportDiagram() {
+ // try {
+ // var data = await bpmnModeler.saveXML({ format: true });
+ // //POST request with body equal on data in JSON format
+ // fetch("/admin/process-models/{{ process_model.id }}/save/{{ file_name }}", {
+ // method: "POST",
+ // headers: {
+ // "Content-Type": "text/xml",
+ // },
+ // body: data.xml,
+ // })
+ // .then((response) => response.json())
+ // //Then with the data from the response in JSON...
+ // .then((data) => {
+ // console.log("Success:", data);
+ // })
+ // //Then with the error genereted...
+ // .catch((error) => {
+ // console.error("Error:", error);
+ // });
+ //
+ // alert("Diagram exported. Check the developer tools!");
+ // } catch (err) {
+ // console.error("could not save BPMN 2.0 diagram", err);
+ // }
+ // }
+ //
+ // #<{(|*
+ // * Open diagram in our modeler instance.
+ // *
+ // * @param {String} bpmnXML diagram to display
+ // |)}>#
+ // async function openDiagram(bpmnXML) {
+ // // import diagram
+ // try {
+ // await bpmnModeler.importXML(bpmnXML);
+ //
+ // // access modeler components
+ // var canvas = bpmnModeler.get("canvas");
+ // var overlays = bpmnModeler.get("overlays");
+ //
+ // // zoom to fit full viewport
+ // canvas.zoom("fit-viewport");
+ //
+ // // attach an overlay to a node
+ // overlays.add("SCAN_OK", "note", {
+ // position: {
+ // bottom: 0,
+ // right: 0,
+ // },
+ // html: 'Mixed up the labels?
',
+ // });
+ //
+ // // add marker
+ // canvas.addMarker("SCAN_OK", "needs-discussion");
+ // } catch (err) {
+ // console.error("could not import BPMN 2.0 diagram", err);
+ // }
+ // }
+ //
+ // // trying to use the python variable bpmn_xml directly causes the xml to have escape sequences
+ // // and using the meta tag seems to help with that
+ // // var bpmn_xml = $("#bpmn_xml").data();
+ // openDiagram({process.env.PUBLIC_URL + '/sample.bpmn'});
+ //
+ // // wire save button
+ // $("#save-button").click(exportDiagram);
+
+
+ // const [diagram, diagramSet] = useState("");
+ // const container = document.getElementById("container");
+ //
+ // useEffect(() => {
+ // if (diagram.length === 0) {
+ // axios
+ // .get(
+ // "https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/master/colors/resources/pizza-collaboration.bpmn"
+ // )
+ // .then((r) => {
+ // diagramSet(r.data);
+ // })
+ // .catch((e) => {
+ // console.log(e);
+ // });
+ // }
+ // }, [diagram]);
+ //
+ // if (diagram.length > 0) {
+ // const modeler = new Modeler({
+ // container,
+ // keyboard: {
+ // bindTo: document
+ // }
+ // });
+ // modeler
+ // .importXML(diagram)
+ // .then(({ warnings }) => {
+ // if (warnings.length) {
+ // console.log("Warnings", warnings);
+ // }
+ //
+ // const canvas = modeler.get("modeling");
+ // canvas.setColor("CalmCustomerTask", {
+ // stroke: "green",
+ // fill: "yellow"
+ // });
+ // })
+ // .catch((err) => {
+ // console.log("error", err);
+ // });
+ // }
+ //
+ // return (
+ //
+ // );
+
+
function onShown() {
console.log('diagram shown');
}
@@ -37,95 +184,14 @@ function App(props) {
console.log('failed to show diagram');
}
- // return (
- //
- // );
- //
-
- const bpmnModeler = new BpmnModeler({
- container: '#canvas',
- propertiesPanel: {
- parent: '#properties'
- },
- additionalModules: [
- BpmnPropertiesPanelModule,
- BpmnPropertiesProviderModule
- ]
- });
-
- async function exportDiagram() {
- try {
- var data = await bpmnModeler.saveXML({ format: true });
- //POST request with body equal on data in JSON format
- fetch("/admin/process-models/{{ process_model.id }}/save/{{ file_name }}", {
- method: "POST",
- headers: {
- "Content-Type": "text/xml",
- },
- body: data.xml,
- })
- .then((response) => response.json())
- //Then with the data from the response in JSON...
- .then((data) => {
- console.log("Success:", data);
- })
- //Then with the error genereted...
- .catch((error) => {
- console.error("Error:", error);
- });
-
- alert("Diagram exported. Check the developer tools!");
- } catch (err) {
- console.error("could not save BPMN 2.0 diagram", err);
- }
- }
-
- /**
- * Open diagram in our modeler instance.
- *
- * @param {String} bpmnXML diagram to display
- */
- async function openDiagram(bpmnXML) {
- // import diagram
- try {
- await bpmnModeler.importXML(bpmnXML);
-
- // access modeler components
- var canvas = bpmnModeler.get("canvas");
- var overlays = bpmnModeler.get("overlays");
-
- // zoom to fit full viewport
- canvas.zoom("fit-viewport");
-
- // attach an overlay to a node
- overlays.add("SCAN_OK", "note", {
- position: {
- bottom: 0,
- right: 0,
- },
- html: 'Mixed up the labels?
',
- });
-
- // add marker
- canvas.addMarker("SCAN_OK", "needs-discussion");
- } catch (err) {
- console.error("could not import BPMN 2.0 diagram", err);
- }
- }
-
- // trying to use the python variable bpmn_xml directly causes the xml to have escape sequences
- // and using the meta tag seems to help with that
- // var bpmn_xml = $("#bpmn_xml").data();
- openDiagram({process.env.PUBLIC_URL + '/sample.bpmn'});
-
- // wire save button
- $("#save-button").click(exportDiagram);
-
+ return (
+
+ );
}
export default App;
diff --git a/src/bpmn-js-properties-panel.css b/src/bpmn-js-properties-panel.css
new file mode 100644
index 0000000..e2866ce
--- /dev/null
+++ b/src/bpmn-js-properties-panel.css
@@ -0,0 +1,101 @@
+* {
+ box-sizing: border-box;
+}
+body,
+html {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 12px;
+ height: 100%;
+ max-height: 100%;
+ padding: 0;
+ margin: 0;
+}
+#js-properties-panel {
+ width: 400px;
+}
+a:link {
+ text-decoration: none;
+}
+.content {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ display: flex;
+}
+.content > .message {
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ display: table;
+ font-size: 16px;
+ color: #111;
+}
+.content > .message .note {
+ vertical-align: middle;
+ text-align: center;
+ display: table-cell;
+}
+.content > .message.error .details {
+ max-width: 500px;
+ font-size: 12px;
+ margin: 20px auto;
+ text-align: left;
+ color: #BD2828;
+}
+.content > .message.error pre {
+ border: solid 1px #BD2828;
+ background: #fefafa;
+ padding: 10px;
+ color: #BD2828;
+}
+.content:not(.with-error) .error,
+.content.with-error .intro,
+.content.with-diagram .intro {
+ display: none;
+}
+.content .canvas {
+ width: 100%;
+}
+.content .canvas,
+.content .properties-panel-parent {
+ display: none;
+}
+.content.with-diagram .canvas,
+.content.with-diagram .properties-panel-parent {
+ display: block;
+}
+.buttons {
+ position: fixed;
+ bottom: 20px;
+ left: 20px;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+.buttons > li {
+ display: inline-block;
+ margin-right: 10px;
+}
+.buttons > li > a {
+ background: #DDD;
+ border: solid 1px #666;
+ display: inline-block;
+ padding: 5px;
+}
+.buttons a {
+ opacity: 0.3;
+}
+.buttons a.active {
+ opacity: 1;
+}
+.properties-panel-parent {
+ border-left: 1px solid #ccc;
+ overflow: auto;
+}
+.properties-panel-parent:empty {
+ display: none;
+}
+.properties-panel-parent > .djs-properties-panel {
+ padding-bottom: 70px;
+ min-height: 100%;
+}
diff --git a/src/react_editor.js b/src/react_editor.js
new file mode 100644
index 0000000..4c1e1bc
--- /dev/null
+++ b/src/react_editor.js
@@ -0,0 +1,143 @@
+import BpmnModeler from 'bpmn-js/lib/Modeler';
+import {
+ BpmnPropertiesPanelModule,
+ BpmnPropertiesProviderModule,
+} from 'bpmn-js-properties-panel';
+import React from "react";
+
+import "bpmn-js-properties-panel/dist/assets/properties-panel.css"
+import './bpmn-js-properties-panel.css';
+
+export default class ReactEditor extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = { };
+
+ this.containerRef = React.createRef();
+ }
+
+ componentDidMount() {
+
+ const {
+ url,
+ diagramXML
+ } = this.props;
+
+ const container = this.containerRef.current;
+
+ this.bpmnViewer = new BpmnModeler({
+ container: container,
+ keyboard: {
+ bindTo: document
+ },
+ propertiesPanel: {
+ parent: '#js-properties-panel'
+ },
+ additionalModules: [
+ BpmnPropertiesPanelModule,
+ BpmnPropertiesProviderModule
+ ]
+ });
+
+ this.bpmnViewer.on('import.done', (event) => {
+ const {
+ error,
+ warnings
+ } = event;
+
+ if (error) {
+ return this.handleError(error);
+ }
+
+ this.bpmnViewer.get('canvas').zoom('fit-viewport');
+
+ return this.handleShown(warnings);
+ });
+
+ if (url) {
+ return this.fetchDiagram(url);
+ }
+
+ if (diagramXML) {
+ return this.displayDiagram(diagramXML);
+ }
+ }
+
+ componentWillUnmount() {
+ this.bpmnViewer.destroy();
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ const {
+ props,
+ state
+ } = this;
+
+ if (props.url !== prevProps.url) {
+ return this.fetchDiagram(props.url);
+ }
+
+ const currentXML = props.diagramXML || state.diagramXML;
+
+ const previousXML = prevProps.diagramXML || prevState.diagramXML;
+
+ if (currentXML && currentXML !== previousXML) {
+ return this.displayDiagram(currentXML);
+ }
+ }
+
+ displayDiagram(diagramXML) {
+ this.bpmnViewer.importXML(diagramXML);
+ }
+
+ fetchDiagram(url) {
+
+ this.handleLoading();
+
+ fetch(url)
+ .then(response => response.text())
+ .then(text => this.setState({ diagramXML: text }))
+ .catch(err => this.handleError(err));
+ }
+
+ handleLoading() {
+ const { onLoading } = this.props;
+
+ if (onLoading) {
+ onLoading();
+ }
+ }
+
+ handleError(err) {
+ const { onError } = this.props;
+
+ if (onError) {
+ onError(err);
+ }
+ }
+
+ handleShown(warnings) {
+ const { onShown } = this.props;
+
+ if (onShown) {
+ onShown(warnings);
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}