It's time to write our second application, where there will be a list of schemes, processes, and a Workflow Designer with the ability to start a process and see its status. We will use create-react-app template to create a simple React application. Open your console and go to the folder react-example, then execute following commands:
npx create-react-app frontend
cd frontend
npm run start
You should see something similar in your console:
Compiled successfully!
You can now view frontend in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.50.125:3000
Note that the development build is not optimized.
To create a production build, use npm run build.
webpack compiled successfully
Now open your browser at http://localhost:3000 (in your case address may be different) and you will see an example React application. Let's start hack it. First we will add a navigation bar to our application. We will use React Suite library.
Stop frontend application if its running (Ctrl+C). Open your console and execute command:
npm install rsuite
Then run frontend application again:
npm run start
Open frontend application in your favourite IDE. We will use JetBrains IDEA.
Adding settings to access backend APIs
Add settings.js file under frontend src folder with the following content:
frontend/src/settings.js
const backendUrl = 'http://localhost:5139';
const settings = {
workflowUrl: `${backendUrl}/api/workflow`,
userUrl: `${backendUrl}/api/user`,
designerUrl: `${backendUrl}/designer/API`
}
export default settings;
The settings object contains following properties:
- workflowUrl - URL to access workflow API, see
WorkflowControllerclass. - userUrl - URL to access user API, see
UserControllerclass. - designerUrl - URL to access Workflow Designer API, see
DesignerControllerclass.
Adding schemes table
We will now create a simple table to show the workflow schemes from our API. Add the Schemes.js file to the frontend src folder with the following content:
frontend/src/Schemes.js
import {Table} from "rsuite";
import {useEffect, useState} from "react";
import settings from "./settings";
const {Column, HeaderCell, Cell} = Table;
const Schemes = (props) => {
const [data, setData] = useState([]);
useEffect(() => {
fetch(`${settings.workflowUrl}/schemes`)
.then(response => response.json())
.then(data => setData(data))
}, []);
return <Table data={data}
height={400}
onRowClick={rowData => props.onRowClick?.(rowData)}>
<Column flexGrow={1}>
<HeaderCell>Code</HeaderCell>
<Cell dataKey="code"/>
</Column>
<Column flexGrow={1}>
<HeaderCell>Tags</HeaderCell>
<Cell dataKey="tags"/>
</Column>
</Table>
}
export default Schemes;
The React Schemes component simply shows the data in the Table and retrieves the data from the backend in the useEffect hook. The component calls the props.onRowClick function, if it was passed through props, when the user clicks a table row.
Adding process instance table
Add the Processes.js file to the frontend src folder with the following content:
frontend/src/Processes.js
import {Table} from "rsuite";
import {useEffect, useState} from "react";
import settings from "./settings";
const {Column, HeaderCell, Cell} = Table;
const Processes = (props) => {
const [data, setData] = useState([]);
useEffect(() => {
fetch(`${settings.workflowUrl}/instances`)
.then(response => response.json())
.then(data => setData(data))
}, []);
return <Table data={data}
height={400}
onRowClick={rowData => props.onRowClick?.(rowData)}>
<Column flexGrow={1}>
<HeaderCell>Id</HeaderCell>
<Cell dataKey="id"/>
</Column>
<Column flexGrow={1}>
<HeaderCell>Scheme</HeaderCell>
<Cell dataKey="scheme"/>
</Column>
<Column flexGrow={1}>
<HeaderCell>CreationDate</HeaderCell>
<Cell dataKey="creationDate"/>
</Column>
<Column flexGrow={1}>
<HeaderCell>StateName</HeaderCell>
<Cell dataKey="stateName"/>
</Column>
<Column flexGrow={1}>
<HeaderCell>ActivityName</HeaderCell>
<Cell dataKey="activityName"/>
</Column>
</Table>
}
export default Processes;
The React Processes component works the same way as the Schemes component, but for process instances. Pay attention to useState, useEffect hooks and the onRowClick property.
Adding users SelectPicker
Now we need a component in which we can select the current user who will execute the process commands. Add the Users.js file to the frontend src folder with the following content:
frontend/src/Users.js
import {useEffect, useState} from "react";
import {SelectPicker} from "rsuite";
import settings from "./settings";
const Users = (props) => {
const [users, setUsers] = useState([]);
const onChangeUser = user =>