diff --git a/.eslintrc.js b/.eslintrc.js
index 04e1db5..3f57d10 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -4,20 +4,27 @@ module.exports = {
es2021: true,
},
extends: [
- "react-app",
- "react-app/jest",
- "plugin:react/recommended",
- "airbnb",
- "plugin:jest/recommended",
- "plugin:prettier/recommended",
+ 'react-app',
+ 'react-app/jest',
+ 'plugin:react/recommended',
+ 'airbnb',
+ 'plugin:jest/recommended',
+ 'plugin:prettier/recommended',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
- ecmaVersion: "latest",
- sourceType: "module",
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ },
+ plugins: ['react'],
+ rules: {
+ 'react/jsx-no-bind': 'off',
+ 'jsx-a11y/no-autofocus': 'off',
+ 'jsx-a11y/label-has-associated-control': 'off',
+ 'no-console': 'off',
+ 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
+ 'react/react-in-jsx-scope': 'off',
},
- plugins: ["react"],
- rules: {},
};
diff --git a/package-lock.json b/package-lock.json
index f7cce92..18976df 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"dmn-js": "^12.1.1",
"dmn-js-properties-panel": "^1.0.0",
"dmn-js-shared": "^12.1.1",
+ "prop-types": "^15.8.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
"react-datepicker": "^4.8.0",
diff --git a/package.json b/package.json
index 89bc471..963de3c 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"dmn-js": "^12.1.1",
"dmn-js-properties-panel": "^1.0.0",
"dmn-js-shared": "^12.1.1",
+ "prop-types": "^15.8.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
"react-datepicker": "^4.8.0",
diff --git a/src/components/ErrorBoundary.js b/src/components/ErrorBoundary.js
index d84a6cf..4dd5014 100644
--- a/src/components/ErrorBoundary.js
+++ b/src/components/ErrorBoundary.js
@@ -1,5 +1,6 @@
-import React from "react";
-//FIXME: this is currently not actually catching any issues. not sure why
+import React from 'react';
+import PropTypes from 'prop-types';
+
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
@@ -8,26 +9,29 @@ class ErrorBoundary extends React.Component {
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
- return { hasError: true };
+ return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
- this.setState({
- error: error,
- errorInfo: errorInfo
- })
// You can also log the error to an error reporting service
- console.log("HELLO: ", error, errorInfo);
+ console.log('HELLO: ', error, errorInfo);
}
render() {
- if (this.state.hasError) {
+ const { hasError } = this.state;
+ const { children } = this.props;
+
+ if (hasError) {
// You can render any custom fallback UI
return
Something went wrong.
;
}
- return this.props.children;
+ return children;
}
}
export default ErrorBoundary;
+
+ErrorBoundary.propTypes = {
+ children: PropTypes.string.isRequired,
+};
diff --git a/src/components/FileInput.js b/src/components/FileInput.js
index 351b6e4..fb7dd63 100644
--- a/src/components/FileInput.js
+++ b/src/components/FileInput.js
@@ -1,23 +1,25 @@
-import React from "react";
-import { BACKEND_BASE_URL } from '../config';
-import { HOT_AUTH_TOKEN } from '../config';
+import React from 'react';
import axios from 'axios';
+import PropTypes from 'prop-types';
+import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config';
export default class FileInput extends React.Component {
- constructor(props) {
- super(props);
+ constructor({ processGroupId, processModelId }) {
+ super({ processGroupId, processModelId });
this.handleSubmit = this.handleSubmit.bind(this);
this.fileInput = React.createRef();
- this.props = props;
+ this.processGroupId = processGroupId;
+ this.processModelId = processModelId;
}
handleSubmit(event) {
- event.preventDefault()
- const url = `${BACKEND_BASE_URL}/process-models/${this.props.processModel.process_group_id}/${this.props.processModel.id}/file`;
+ event.preventDefault();
+ const url = `${BACKEND_BASE_URL}/process-models/${this.processGroupId}/${this.processModelId}/file`;
const formData = new FormData();
formData.append('file', this.fileInput.current.files[0]);
formData.append('fileName', this.fileInput.current.files[0].name);
+ // this might work if we remove the content-type header
// const headers = {
// 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`,
// 'content-type': 'multipart/form-data',
@@ -38,7 +40,7 @@ export default class FileInput extends React.Component {
const config = {
headers: {
'content-type': 'multipart/form-data',
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`,
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
},
};
axios.post(url, formData, config).then((response) => {
@@ -58,3 +60,8 @@ export default class FileInput extends React.Component {
);
}
}
+
+FileInput.propTypes = {
+ processGroupId: PropTypes.string.isRequired,
+ processModelId: PropTypes.string.isRequired,
+};
diff --git a/src/components/PaginationForTable.js b/src/components/PaginationForTable.js
index e8498d8..39cdfa8 100644
--- a/src/components/PaginationForTable.js
+++ b/src/components/PaginationForTable.js
@@ -1,93 +1,162 @@
-import React from "react";
-import { Link } from "react-router-dom";
+import React from 'react';
+import { Link } from 'react-router-dom';
-import { Dropdown, Stack } from 'react-bootstrap'
+import { Dropdown, Stack } from 'react-bootstrap';
+import PropTypes from 'prop-types';
export const DEFAULT_PER_PAGE = 50;
export const DEFAULT_PAGE = 1;
-export default function PaginationForTable(props) {
+export default function PaginationForTable({
+ page,
+ perPage,
+ pagination,
+ tableToDisplay,
+ queryParamString,
+ path,
+}) {
const PER_PAGE_OPTIONS = [2, 10, 50, 100];
- const buildPerPageDropdown = (() => {
- const perPageDropdownRows = PER_PAGE_OPTIONS.map(perPageOption => {
- if (perPageOption === props.perPage) {
- return {perPageOption}
- } else {
- return {perPageOption}
+ const buildPerPageDropdown = () => {
+ const perPageDropdownRows = PER_PAGE_OPTIONS.map((perPageOption) => {
+ if (perPageOption === perPage) {
+ return (
+
+ {perPageOption}
+
+ );
}
+ return (
+
+ {perPageOption}
+
+ );
});
return (
-
- )
- });
+ );
+ };
- const buildPaginationNav = (() => {
- let previousPageTag = "";
- if (props.page === 1) {
+ const buildPaginationNav = () => {
+ let previousPageTag = '';
+ if (page === 1) {
previousPageTag = (
- «
- )
+
+
+ «
+
+
+ );
} else {
previousPageTag = (
- «
+
+ «
+
- )
+ );
}
- let nextPageTag = "";
- if (props.page >= props.pagination.pages) {
+ let nextPageTag = '';
+ if (page >= pagination.pages) {
nextPageTag = (
- »
- )
+
+
+ »
+
+
+ );
} else {
nextPageTag = (
- »
+
+ »
+
- )
+ );
}
- let startingNumber = ((props.page - 1) * props.perPage) + 1
- let endingNumber = ((props.page) * props.perPage)
- if (endingNumber > props.pagination.total) {
- endingNumber = props.pagination.total
+ let startingNumber = (page - 1) * perPage + 1;
+ let endingNumber = page * perPage;
+ if (endingNumber > pagination.total) {
+ endingNumber = pagination.total;
}
- if (startingNumber > props.pagination.total) {
- startingNumber = props.pagination.total
+ if (startingNumber > pagination.total) {
+ startingNumber = pagination.total;
}
return (
- {startingNumber}-{endingNumber} of {props.pagination.total}
+
+ {startingNumber}-{endingNumber} of{' '}
+ {pagination.total}
+
- )
- });
+ );
+ };
- return(
+ return (
- {buildPaginationNav()}
- {props.tableToDisplay}
- {buildPerPageDropdown()}
+ {buildPaginationNav()}
+ {tableToDisplay}
+ {buildPerPageDropdown()}
- )
+ );
}
+
+PaginationForTable.propTypes = {
+ page: PropTypes.number.isRequired,
+ perPage: PropTypes.number.isRequired,
+ pagination: PropTypes.objectOf(PropTypes.number).isRequired,
+ tableToDisplay: PropTypes.string.isRequired,
+ queryParamString: PropTypes.string.isRequired,
+ path: PropTypes.string.isRequired,
+};
diff --git a/src/components/ProcessBreadcrumb.js b/src/components/ProcessBreadcrumb.js
index 67b9d28..b5e7c6b 100644
--- a/src/components/ProcessBreadcrumb.js
+++ b/src/components/ProcessBreadcrumb.js
@@ -1,30 +1,67 @@
-import { Link } from "react-router-dom";
-import Breadcrumb from 'react-bootstrap/Breadcrumb'
+import { Link } from 'react-router-dom';
+import Breadcrumb from 'react-bootstrap/Breadcrumb';
+import PropTypes from 'prop-types';
-export default function ProcessBreadcrumb(props) {
- let processGroupBreadcrumb = ''
- let processModelBreadcrumb = ''
+export default function ProcessBreadcrumb({
+ processModelId,
+ processGroupId,
+ linkProcessModel,
+}) {
+ let processGroupBreadcrumb = '';
+ let processModelBreadcrumb = '';
- if (props.processModelId) {
- if (props.linkProcessModel) {
- processModelBreadcrumb = Process Model: {props.processModelId}
+ if (processModelId) {
+ if (linkProcessModel) {
+ processModelBreadcrumb = (
+
+ Process Model: {processModelId}
+
+ );
} else {
- processModelBreadcrumb = Process Model: {props.processModelId}
+ processModelBreadcrumb = (
+
+ Process Model: {processModelId}
+
+ );
}
- processGroupBreadcrumb =
- Process Group: {props.processGroupId}
-
- } else if (props.processGroupId) {
- processGroupBreadcrumb = Process Group: {props.processGroupId}
+ processGroupBreadcrumb = (
+
+ Process Group: {processGroupId}
+
+ );
+ } else if (processGroupId) {
+ processGroupBreadcrumb = (
+ Process Group: {processGroupId}
+ );
}
return (
-
-
- Home
- {processGroupBreadcrumb}
- {processModelBreadcrumb}
-
+
+
+
+ Home
+
+ {processGroupBreadcrumb}
+ {processModelBreadcrumb}
+
);
}
+
+ProcessBreadcrumb.propTypes = {
+ processModelId: PropTypes.string.isRequired,
+ processGroupId: PropTypes.string.isRequired,
+ linkProcessModel: PropTypes.bool,
+};
+
+ProcessBreadcrumb.defaultProps = {
+ linkProcessModel: false,
+};
diff --git a/src/components/ProcessBreadcrumb.test.js b/src/components/ProcessBreadcrumb.test.js
index f6c1790..45890f3 100644
--- a/src/components/ProcessBreadcrumb.test.js
+++ b/src/components/ProcessBreadcrumb.test.js
@@ -1,30 +1,46 @@
import { render, screen } from '@testing-library/react';
+import { BrowserRouter } from 'react-router-dom';
import ProcessBreadcrumb from './ProcessBreadcrumb';
-import {
- BrowserRouter,
-} from "react-router-dom";
test('renders home link', () => {
- render();
+ render(
+
+
+
+ );
const homeElement = screen.getByText(/Home/);
expect(homeElement).toBeInTheDocument();
});
test('renders process group when given processGroupId', async () => {
- render();
+ render(
+
+
+
+ );
const processGroupElement = screen.getByText(/group-a/);
expect(processGroupElement).toBeInTheDocument();
- const processGroupBreadcrumbs = await screen.findAllByText(/Process Group: group-a/);
+ const processGroupBreadcrumbs = await screen.findAllByText(
+ /Process Group: group-a/
+ );
expect(processGroupBreadcrumbs[0]).toHaveClass('breadcrumb-item active');
});
test('renders process model when given processModelId', async () => {
- render();
+ render(
+
+
+
+ );
const processGroupElement = screen.getByText(/group-b/);
expect(processGroupElement).toBeInTheDocument();
- const processModelBreadcrumbs = await screen.findAllByText(/Process Model: model-c/);
+ const processModelBreadcrumbs = await screen.findAllByText(
+ /Process Model: model-c/
+ );
expect(processModelBreadcrumbs[0]).toHaveClass('breadcrumb-item active');
- const processGroupBreadcrumbs = await screen.findAllByText(/Process Group: group-b/);
+ const processGroupBreadcrumbs = await screen.findAllByText(
+ /Process Group: group-b/
+ );
expect(processGroupBreadcrumbs[0]).toBeInTheDocument();
// expect(processGroupBreadcrumbs[0]).toHaveClass('breadcrumb-item');
});
diff --git a/src/config.js b/src/config.js
index 929017c..2ffaed5 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,23 +1,24 @@
const host = window.location.hostname;
const hostAndPort = `${host}:7000`;
-export const BACKEND_BASE_URL = `http://${hostAndPort}/v1.0`
-export const HOT_AUTH_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOm51bGx9.krsOjlSilPMu_3r7WkkUfKyr-h3HprXr6R4_FXRXz6Y"
+export const BACKEND_BASE_URL = `http://${hostAndPort}/v1.0`;
+export const HOT_AUTH_TOKEN =
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOm51bGx9.krsOjlSilPMu_3r7WkkUfKyr-h3HprXr6R4_FXRXz6Y';
export const STANDARD_HEADERS = {
headers: new Headers({
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`
- })
-}
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
+ }),
+};
export const PROCESS_STATUSES = [
- "all",
- "not_started",
- "user_input_required",
- "waiting",
- "complete",
- "faulted",
- "suspended",
-]
+ 'all',
+ 'not_started',
+ 'user_input_required',
+ 'waiting',
+ 'complete',
+ 'faulted',
+ 'suspended',
+];
-export const DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"
+export const DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss';
diff --git a/src/helpers.js b/src/helpers.js
index a61200c..902ffa7 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -1,20 +1,20 @@
// https://www.30secondsofcode.org/js/s/slugify
-export const slugifyString = ((str) => {
+export const slugifyString = (str) => {
return str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
-});
+};
-export const convertDateToSeconds = ((date, onChangeFunction) => {
+export const convertDateToSeconds = (date, onChangeFunction) => {
if (date === null) {
- return;
+ return undefined;
}
let dateInMilliseconds = date;
- if (typeof(date.getTime) === "function") {
+ if (typeof date.getTime === 'function') {
dateInMilliseconds = date.getTime();
}
const dateInSeconds = Math.floor(dateInMilliseconds / 1000);
@@ -23,4 +23,6 @@ export const convertDateToSeconds = ((date, onChangeFunction) => {
} else {
return dateInSeconds;
}
-});
+
+ return undefined;
+};
diff --git a/src/index.js b/src/index.js
index 1eed046..36c968b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,33 +1,27 @@
import React from 'react';
import * as ReactDOMClient from 'react-dom/client';
-import logo from './logo.svg';
-
+import { Container } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
import reportWebVitals from './reportWebVitals';
-import {
- BrowserRouter,
- Routes,
- Route,
-} from "react-router-dom";
-import ProcessGroups from "./routes/ProcessGroups"
-import ProcessGroupShow from "./routes/ProcessGroupShow"
-import ProcessGroupNew from "./routes/ProcessGroupNew"
-import ProcessGroupEdit from "./routes/ProcessGroupEdit"
-import ProcessModelShow from "./routes/ProcessModelShow"
-import ProcessModelEditDiagram from "./routes/ProcessModelEditDiagram"
-import ProcessInstanceList from "./routes/ProcessInstanceList"
-import ProcessInstanceReport from "./routes/ProcessInstanceReport"
-import ProcessModelNew from "./routes/ProcessModelNew"
-import ProcessModelEdit from "./routes/ProcessModelEdit"
-import ProcessInstanceShow from "./routes/ProcessInstanceShow"
-import ErrorBoundary from "./components/ErrorBoundary"
-
-import { Container } from 'react-bootstrap'
+import ProcessGroups from './routes/ProcessGroups';
+import ProcessGroupShow from './routes/ProcessGroupShow';
+import ProcessGroupNew from './routes/ProcessGroupNew';
+import ProcessGroupEdit from './routes/ProcessGroupEdit';
+import ProcessModelShow from './routes/ProcessModelShow';
+import ProcessModelEditDiagram from './routes/ProcessModelEditDiagram';
+import ProcessInstanceList from './routes/ProcessInstanceList';
+import ProcessInstanceReport from './routes/ProcessInstanceReport';
+import ProcessModelNew from './routes/ProcessModelNew';
+import ProcessModelEdit from './routes/ProcessModelEdit';
+import ProcessInstanceShow from './routes/ProcessInstanceShow';
+import ErrorBoundary from './components/ErrorBoundary';
+import logo from './logo.svg';
const root = ReactDOMClient.createRoot(document.getElementById('root'));
root.render(
@@ -40,18 +34,48 @@ root.render(
} />
} />
- } />
+ }
+ />
} />
- } />
+ }
+ />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
diff --git a/src/react_diagram_editor.js b/src/react_diagram_editor.js
index 96731e8..872f90f 100644
--- a/src/react_diagram_editor.js
+++ b/src/react_diagram_editor.js
@@ -10,34 +10,44 @@ import {
DmnPropertiesProviderModule,
} from 'dmn-js-properties-panel';
-import React, { useRef, useEffect, useState } from "react";
-import { BACKEND_BASE_URL } from './config';
-import { HOT_AUTH_TOKEN } from './config';
+import React, { useRef, useEffect, useState } from 'react';
import spiffworkflowIO from 'bpmn-js-spiffworkflow/app/spiffworkflow/InputOutput';
import spiffworkflowPanel from 'bpmn-js-spiffworkflow/app/spiffworkflow/PropertiesPanel';
import Button from 'react-bootstrap/Button';
+import PropTypes from 'prop-types';
+import { HOT_AUTH_TOKEN, BACKEND_BASE_URL } from './config';
-import "bpmn-js/dist/assets/diagram-js.css";
-import "bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
-import "bpmn-js-properties-panel/dist/assets/properties-panel.css"
+import 'bpmn-js/dist/assets/diagram-js.css';
+import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
+import 'bpmn-js-properties-panel/dist/assets/properties-panel.css';
import './bpmn-js-properties-panel.css';
-import "bpmn-js/dist/assets/bpmn-js.css";
+import 'bpmn-js/dist/assets/bpmn-js.css';
-import "dmn-js/dist/assets/diagram-js.css";
-import "dmn-js/dist/assets/dmn-js-decision-table-controls.css";
-import "dmn-js/dist/assets/dmn-js-decision-table.css";
-import "dmn-js/dist/assets/dmn-js-drd.css";
-import "dmn-js/dist/assets/dmn-js-literal-expression.css";
-import "dmn-js/dist/assets/dmn-js-shared.css";
-import "dmn-js/dist/assets/dmn-font/css/dmn-embedded.css";
-import "dmn-js-properties-panel/dist/assets/properties-panel.css"
+import 'dmn-js/dist/assets/diagram-js.css';
+import 'dmn-js/dist/assets/dmn-js-decision-table-controls.css';
+import 'dmn-js/dist/assets/dmn-js-decision-table.css';
+import 'dmn-js/dist/assets/dmn-js-drd.css';
+import 'dmn-js/dist/assets/dmn-js-literal-expression.css';
+import 'dmn-js/dist/assets/dmn-js-shared.css';
+import 'dmn-js/dist/assets/dmn-font/css/dmn-embedded.css';
+import 'dmn-js-properties-panel/dist/assets/properties-panel.css';
-import "bpmn-js-spiffworkflow/app/css/app.css"
+import 'bpmn-js-spiffworkflow/app/css/app.css';
// https://codesandbox.io/s/quizzical-lake-szfyo?file=/src/App.js was a handy reference
-export default function ReactDiagramEditor(props) {
- const [diagramXML, setDiagramXML] = useState("");
+export default function ReactDiagramEditor({
+ processModelId,
+ processGroupId,
+ saveDiagram,
+ diagramType,
+
+ diagramXML,
+ fileName,
+ onLaunchScriptEditor,
+ url,
+}) {
+ const [diagramXMLString, setDiagramXMLString] = useState('');
const [diagramModelerState, setDiagramModelerState] = useState(null);
const [performingXmlUpdates, setPerformingXmlUpdates] = useState(false);
@@ -48,8 +58,8 @@ export default function ReactDiagramEditor(props) {
return;
}
- document.getElementById("diagram-container").innerHTML = "";
- var temp = document.createElement('template');
+ document.getElementById('diagram-container').innerHTML = '';
+ const temp = document.createElement('template');
temp.innerHTML = `
@@ -57,61 +67,48 @@ export default function ReactDiagramEditor(props) {
style="border:1px solid #000000; height:90vh; width:90vw; margin:auto;">
- `
+ `;
- var frag = temp.content;
- document.getElementById("diagram-container").appendChild(frag);
+ const frag = temp.content;
+ document.getElementById('diagram-container').appendChild(frag);
let diagramModeler = null;
- if (props.diagramType === "bpmn") {
+ if (diagramType === 'bpmn') {
diagramModeler = new BpmnModeler({
- container: "#canvas",
+ container: '#canvas',
keyboard: {
- bindTo: document
+ bindTo: document,
},
propertiesPanel: {
- parent: '#js-properties-panel'
+ parent: '#js-properties-panel',
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
spiffworkflowIO,
- spiffworkflowPanel
+ spiffworkflowPanel,
],
});
- } else if (props.diagramType === "dmn") {
+ } else if (diagramType === 'dmn') {
diagramModeler = new DmnModeler({
- container: "#canvas",
+ container: '#canvas',
keyboard: {
- bindTo: document
+ bindTo: document,
},
drd: {
propertiesPanel: {
- parent: '#js-properties-panel'
+ parent: '#js-properties-panel',
},
additionalModules: [
DmnPropertiesPanelModule,
DmnPropertiesProviderModule,
- ]
- }
+ ],
+ },
});
}
- setDiagramModelerState(diagramModeler);
-
- diagramModeler.on('launch.script.editor', (event) => {
- const {
- error,
- element,
- } = event;
- if (error) {
- console.log(error);
- }
- handleLaunchScriptEditor(element);
- });
function handleLaunchScriptEditor(element) {
- const { onLaunchScriptEditor } = props;
if (onLaunchScriptEditor) {
setPerformingXmlUpdates(true);
const modeling = diagramModeler.get('modeling');
@@ -119,108 +116,150 @@ export default function ReactDiagramEditor(props) {
}
}
- }, [props, diagramModelerState])
+ setDiagramModelerState(diagramModeler);
+
+ diagramModeler.on('launch.script.editor', (event) => {
+ const { error, element } = event;
+ if (error) {
+ console.log(error);
+ }
+ handleLaunchScriptEditor(element);
+ });
+ }, [diagramModelerState, diagramType, onLaunchScriptEditor]);
useEffect(() => {
if (!diagramModelerState) {
- return;
+ return undefined;
}
if (performingXmlUpdates) {
- return;
+ return undefined;
+ }
+
+ function handleError(err) {
+ console.log('ERROR:', err);
}
diagramModelerState.on('import.done', (event) => {
- const {
- error,
- } = event;
+ const { error } = event;
if (error) {
- return handleError(error);
+ handleError(error);
+ return;
}
let modeler = diagramModelerState;
- if (props.diagramType === "dmn") {
+ if (diagramType === 'dmn') {
modeler = diagramModelerState.getActiveViewer();
}
// only get the canvas if the dmn active viewer is actually
// a Modeler and not an Editor which is what it will when we are
// actively editing a decision table
- if (modeler.constructor.name === "Modeler") {
+ if (modeler.constructor.name === 'Modeler') {
modeler.get('canvas').zoom('fit-viewport');
}
});
- var diagramXMLToUse = props.diagramXML || diagramXML
- if (diagramXMLToUse) {
- if (!diagramXML) {
- setDiagramXML(diagramXMLToUse);
- }
- return displayDiagram(diagramModelerState, diagramXMLToUse);
- }
-
- if (!diagramXML) {
- if (props.url) {
- return fetchDiagramFromURL(props.url);
- } else if (props.fileName) {
- return fetchDiagramFromJsonAPI(props.process_group_id, props.process_model_id, props.fileName);
- } else {
- let newDiagramFileName = 'new_bpmn_diagram.bpmn';
- if (props.diagramType === "dmn" ) {
- newDiagramFileName = 'new_dmn_diagram.dmn';
- }
- return fetchDiagramFromURL(process.env.PUBLIC_URL + '/' + newDiagramFileName);
- }
- }
-
- return () => {
- diagramModelerState.destroy();
- }
-
- function fetchDiagramFromURL(url) {
- fetch(url)
- .then(response => response.text())
- .then(text => setDiagramXML(text))
- .catch(err => handleError(err));
- }
-
- function fetchDiagramFromJsonAPI(processGroupId, processModelId, fileName) {
- fetch(`${BACKEND_BASE_URL}/process-models/${processGroupId}/${processModelId}/file/${fileName}`, {
- headers: new Headers({
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`
- })
- })
- .then(response => response.json())
- .then(response_json => setDiagramXML(response_json.file_contents))
- .catch(err => handleError(err));
- }
-
- function handleError(err) {
- const { onError } = props;
- if (onError) {
- onError(err);
- }
- }
-
function displayDiagram(diagramModelerToUse, diagramXMLToDisplay) {
if (alreadyImportedXmlRef.current) {
return;
}
diagramModelerToUse.importXML(diagramXMLToDisplay);
- alreadyImportedXmlRef.current = true
+ alreadyImportedXmlRef.current = true;
}
- }, [props, diagramXML, diagramModelerState, performingXmlUpdates]);
+
+ function fetchDiagramFromURL(urlToUse) {
+ fetch(urlToUse)
+ .then((response) => response.text())
+ .then((text) => setDiagramXMLString(text))
+ .catch((err) => handleError(err));
+ }
+
+ function fetchDiagramFromJsonAPI() {
+ fetch(
+ `${BACKEND_BASE_URL}/process-models/${processGroupId}/${processModelId}/file/${fileName}`,
+ {
+ headers: new Headers({
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
+ }),
+ }
+ )
+ .then((response) => response.json())
+ .then((responseJson) => setDiagramXMLString(responseJson.file_contents))
+ .catch((err) => handleError(err));
+ }
+
+ const diagramXMLToUse = diagramXML || diagramXMLString;
+ if (diagramXMLToUse) {
+ if (!diagramXMLString) {
+ setDiagramXMLString(diagramXMLToUse);
+ }
+ displayDiagram(diagramModelerState, diagramXMLToUse);
+ return undefined;
+ }
+
+ if (!diagramXMLString) {
+ if (url) {
+ fetchDiagramFromURL(url);
+ return undefined;
+ }
+ if (fileName) {
+ fetchDiagramFromJsonAPI();
+ return undefined;
+ }
+ let newDiagramFileName = 'new_bpmn_diagram.bpmn';
+ if (diagramType === 'dmn') {
+ newDiagramFileName = 'new_dmn_diagram.dmn';
+ }
+ fetchDiagramFromURL(`${process.env.PUBLIC_URL}/${newDiagramFileName}`);
+ return undefined;
+ }
+
+ return () => {
+ diagramModelerState.destroy();
+ };
+ }, [
+ diagramModelerState,
+ diagramType,
+ diagramXML,
+ diagramXMLString,
+ fileName,
+ performingXmlUpdates,
+ processGroupId,
+ processModelId,
+ url,
+ ]);
function handleSave() {
- diagramModelerState.saveXML({ format: true })
- .then(xmlObject => {
- props.saveDiagram(xmlObject.xml);
- })
+ diagramModelerState.saveXML({ format: true }).then((xmlObject) => {
+ saveDiagram(xmlObject.xml);
+ });
}
return (
-
+
);
}
+
+ReactDiagramEditor.propTypes = {
+ processModelId: PropTypes.string.isRequired,
+ processGroupId: PropTypes.string.isRequired,
+ saveDiagram: PropTypes.func.isRequired,
+ diagramType: PropTypes.string.isRequired,
+
+ diagramXML: PropTypes.string,
+ fileName: PropTypes.string,
+ onLaunchScriptEditor: PropTypes.func,
+ url: PropTypes.string,
+};
+
+ReactDiagramEditor.defaultProps = {
+ diagramXML: null,
+ fileName: null,
+ onLaunchScriptEditor: null,
+ url: null,
+};
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
index 5253d3a..532f29b 100644
--- a/src/reportWebVitals.js
+++ b/src/reportWebVitals.js
@@ -1,4 +1,4 @@
-const reportWebVitals = onPerfEntry => {
+const reportWebVitals = (onPerfEntry) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
diff --git a/src/routes/ProcessGroupEdit.js b/src/routes/ProcessGroupEdit.js
index 9b22198..2fad50c 100644
--- a/src/routes/ProcessGroupEdit.js
+++ b/src/routes/ProcessGroupEdit.js
@@ -1,19 +1,21 @@
-import React, { useState, useEffect } from "react";
-import { useParams, useNavigate } from "react-router-dom";
-import { BACKEND_BASE_URL } from '../config';
-import { HOT_AUTH_TOKEN, STANDARD_HEADERS } from '../config';
-import ProcessBreadcrumb from '../components/ProcessBreadcrumb'
-import { Button, Stack } from 'react-bootstrap'
+import React, { useState, useEffect } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { Button, Stack } from 'react-bootstrap';
+import { BACKEND_BASE_URL, HOT_AUTH_TOKEN, STANDARD_HEADERS } from '../config';
+import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
export default function ProcessGroupEdit() {
- const [displayName, setDisplayName] = useState("");
+ const [displayName, setDisplayName] = useState('');
const params = useParams();
const navigate = useNavigate();
const [processGroup, setProcessGroup] = useState(null);
useEffect(() => {
- fetch(`${BACKEND_BASE_URL}/process-groups/${params.process_group_id}`, STANDARD_HEADERS)
- .then(res => res.json())
+ fetch(
+ `${BACKEND_BASE_URL}/process-groups/${params.process_group_id}`,
+ STANDARD_HEADERS
+ )
+ .then((res) => res.json())
.then(
(result) => {
setProcessGroup(result);
@@ -22,85 +24,84 @@ export default function ProcessGroupEdit() {
(error) => {
console.log(error);
}
- )
+ );
}, [params]);
- const updateProcessGroup = ((event) => {
- event.preventDefault()
+ const updateProcessGroup = (event) => {
+ event.preventDefault();
fetch(`${BACKEND_BASE_URL}/process-groups/${processGroup.id}`, {
headers: new Headers({
'Content-Type': 'application/json',
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
}),
method: 'PUT',
body: JSON.stringify({
display_name: displayName,
id: processGroup.id,
}),
- })
- .then(res => res.json())
- .then(
- (result) => {
- navigate(`/process-groups/${processGroup.id}`)
- },
- // Note: it's important to handle errors here
- // instead of a catch() block so that we don't swallow
- // exceptions from actual bugs in components.
- (newError) => {
- console.log(newError);
- }
- )
+ }).then(
+ () => {
+ navigate(`/process-groups/${processGroup.id}`);
+ },
+ // Note: it's important to handle errors here
+ // instead of a catch() block so that we don't swallow
+ // exceptions from actual bugs in components.
+ (newError) => {
+ console.log(newError);
+ }
+ );
+ };
- });
-
- const deleteProcessGroup = (() => {
+ const deleteProcessGroup = () => {
fetch(`${BACKEND_BASE_URL}/process-groups/${processGroup.id}`, {
headers: new Headers({
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
}),
method: 'DELETE',
- })
- .then(res => res.json())
- .then(
- (result) => {
- navigate(`/process-groups`);
- },
- (error) => {
- console.log(error);
- }
- )
- });
+ }).then(
+ () => {
+ navigate(`/process-groups`);
+ },
+ (error) => {
+ console.log(error);
+ }
+ );
+ };
- const onDisplayNameChanged = ((newDisplayName) => {
+ const onDisplayNameChanged = (newDisplayName) => {
setDisplayName(newDisplayName);
- });
+ };
if (processGroup) {
return (
-
+
Edit Process Group: {processGroup.id}
);
- } else {
- return (<>>)
}
}
-
diff --git a/src/routes/ProcessGroupNew.js b/src/routes/ProcessGroupNew.js
index 3bc796b..c8bfc9d 100644
--- a/src/routes/ProcessGroupNew.js
+++ b/src/routes/ProcessGroupNew.js
@@ -1,71 +1,70 @@
-import React, { useState } from "react";
-import { useNavigate } from "react-router-dom";
-import { BACKEND_BASE_URL } from '../config';
-import { HOT_AUTH_TOKEN } from '../config';
-import ProcessBreadcrumb from '../components/ProcessBreadcrumb'
-import { slugifyString } from '../helpers'
+import React, { useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config';
+import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
+import { slugifyString } from '../helpers';
export default function ProcessGroupNew() {
- const [identifier, setIdentifier] = useState("");
+ const [identifier, setIdentifier] = useState('');
const [idHasBeenUpdatedByUser, setIdHasBeenUpdatedByUser] = useState(false);
- const [displayName, setDisplayName] = useState("");
+ const [displayName, setDisplayName] = useState('');
const navigate = useNavigate();
- const addProcessGroup = ((event) => {
- event.preventDefault()
+ const addProcessGroup = (event) => {
+ event.preventDefault();
fetch(`${BACKEND_BASE_URL}/process-groups`, {
headers: new Headers({
'Content-Type': 'application/json',
- 'Authorization': `Bearer ${HOT_AUTH_TOKEN}`
+ Authorization: `Bearer ${HOT_AUTH_TOKEN}`,
}),
method: 'POST',
body: JSON.stringify({
id: identifier,
display_name: displayName,
}),
- })
- .then(res => res.json())
- .then(
- (result) => {
- navigate(`/process-groups/${identifier}`)
- },
- // Note: it's important to handle errors here
- // instead of a catch() block so that we don't swallow
- // exceptions from actual bugs in components.
- (newError) => {
- console.log(newError);
- }
- )
+ }).then(
+ () => {
+ navigate(`/process-groups/${identifier}`);
+ },
+ // Note: it's important to handle errors here
+ // instead of a catch() block so that we don't swallow
+ // exceptions from actual bugs in components.
+ (newError) => {
+ console.log(newError);
+ }
+ );
+ };
- });
-
- const onDisplayNameChanged = ((newDisplayName) => {
+ const onDisplayNameChanged = (newDisplayName) => {
setDisplayName(newDisplayName);
if (!idHasBeenUpdatedByUser) {
setIdentifier(slugifyString(newDisplayName));
}
- });
+ };
return (
-
+
Add Process Group