diff --git a/src/routes/AdminRoutes.tsx b/src/routes/AdminRoutes.tsx index b6c6288..e13a023 100644 --- a/src/routes/AdminRoutes.tsx +++ b/src/routes/AdminRoutes.tsx @@ -13,6 +13,8 @@ import ProcessModelEdit from './ProcessModelEdit'; import ProcessInstanceShow from './ProcessInstanceShow'; import UserService from '../services/UserService'; import ProcessInstanceReportList from './ProcessInstanceReportList'; +import ProcessInstanceReportNew from './ProcessInstanceReportNew'; +import ProcessInstanceReportEdit from './ProcessInstanceReportEdit'; export default function AdminRoutes() { if (UserService.hasRole(['admin'])) { @@ -78,6 +80,14 @@ export default function AdminRoutes() { // @ts-expect-error TS(2786) FIXME: 'ProcessInstanceReport' cannot be used as a JSX co... Remove this comment to see the full error message element={} /> + } + /> + } + /> ); } diff --git a/src/routes/ProcessInstanceReportEdit.tsx b/src/routes/ProcessInstanceReportEdit.tsx new file mode 100644 index 0000000..5ac6828 --- /dev/null +++ b/src/routes/ProcessInstanceReportEdit.tsx @@ -0,0 +1,189 @@ +import { useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { Button } from 'react-bootstrap'; +import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config'; +import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; + +type ReportColumn = { + Header: string; + accessor: string; +}; + +type ReportFilterBy = { + field_name: string; + operator: string; + field_value: string; +}; + +export default function ProcessInstanceReportEdit() { + const params = useParams(); + const navigate = useNavigate(); + + const [columns, setColumns] = useState(''); + const [orderBy, setOrderBy] = useState(''); + const [filterBy, setFilterBy] = useState(''); + + useEffect(() => { + function getProcessInstanceReport() { + fetch( + `${BACKEND_BASE_URL}/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_identifier}?per_page=1`, + { + headers: new Headers({ + Authorization: `Bearer ${HOT_AUTH_TOKEN}`, + }), + } + ) + .then((res) => res.json()) + .then( + (result) => { + const reportMetadata = result.report_metadata; + const columnCsv = reportMetadata.columns + .map((column: ReportColumn) => column.accessor) + .join(','); + setColumns(columnCsv); + + if (reportMetadata.order_by) { + setOrderBy(reportMetadata.order_by.join(',')); + } + const filterByCsv = reportMetadata.filter_by + .map( + (filterByItem: ReportFilterBy) => + `${filterByItem.field_name}=${filterByItem.field_value}` + ) + .join(','); + setFilterBy(filterByCsv); + }, + (error) => { + console.log(error); + } + ); + } + + getProcessInstanceReport(); + }, [params]); + + const editProcessInstanceReport = (event: any) => { + event.preventDefault(); + + const columnArray = columns.split(',').map((column) => { + return { Header: column, accessor: column }; + }); + const orderByArray = orderBy.split(',').filter((n) => n); + + const filterByArray = filterBy + .split(',') + .map((filterByItem) => { + const [fieldName, fieldValue] = filterByItem.split('='); + if (fieldValue) { + return { + field_name: fieldName, + operator: 'equals', + field_value: fieldValue, + }; + } + return null; + }) + .filter((n) => n); + + fetch( + `${BACKEND_BASE_URL}/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_identifier}`, + { + headers: new Headers({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${HOT_AUTH_TOKEN}`, + }), + method: 'PUT', + body: JSON.stringify({ + report_metadata: { + columns: columnArray, + order_by: orderByArray, + filter_by: filterByArray, + }, + }), + } + ).then( + () => { + navigate( + `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_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 deleteProcessInstanceReport = () => { + fetch( + `${BACKEND_BASE_URL}/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_identifier}`, + { + headers: new Headers({ + Authorization: `Bearer ${HOT_AUTH_TOKEN}`, + }), + method: 'DELETE', + } + ).then( + () => { + navigate( + `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports` + ); + }, + (error) => { + console.log(error); + } + ); + }; + + return ( +
+ +

Edit Process Instance Report: {params.report_identifier}

+ +
+
+
+ +
+ +
+
+

Like: month=3,milestone=2

+ +
+ +
+
+ ); +} diff --git a/src/routes/ProcessInstanceReportList.tsx b/src/routes/ProcessInstanceReportList.tsx index 9149ca3..96be686 100644 --- a/src/routes/ProcessInstanceReportList.tsx +++ b/src/routes/ProcessInstanceReportList.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Table } from 'react-bootstrap'; +import { Button, Table } from 'react-bootstrap'; import { useParams, Link } from 'react-router-dom'; import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; @@ -68,6 +68,11 @@ export default function ProcessInstanceReportList() { return (
{headerStuff} + {buildTable()}
); diff --git a/src/routes/ProcessInstanceReportNew.tsx b/src/routes/ProcessInstanceReportNew.tsx new file mode 100644 index 0000000..3a3d7b1 --- /dev/null +++ b/src/routes/ProcessInstanceReportNew.tsx @@ -0,0 +1,125 @@ +import { useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config'; +import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; + +export default function ProcessInstanceReportNew() { + const params = useParams(); + const navigate = useNavigate(); + + const [identifier, setIdentifier] = useState(''); + const [columns, setColumns] = useState(''); + const [orderBy, setOrderBy] = useState(''); + const [filterBy, setFilterBy] = useState(''); + + const addProcessInstanceReport = (event: any) => { + event.preventDefault(); + + const columnArray = columns.split(',').map((column) => { + return { Header: column, accessor: column }; + }); + const orderByArray = orderBy.split(',').filter((n) => n); + + const filterByArray = filterBy + .split(',') + .map((filterByItem) => { + const [fieldName, fieldValue] = filterByItem.split('='); + if (fieldValue) { + return { + field_name: fieldName, + operator: 'equals', + field_value: fieldValue, + }; + } + return null; + }) + .filter((n) => n); + + fetch( + `${BACKEND_BASE_URL}/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports`, + { + headers: new Headers({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${HOT_AUTH_TOKEN}`, + }), + method: 'POST', + body: JSON.stringify({ + identifier, + report_metadata: { + columns: columnArray, + order_by: orderByArray, + filter_by: filterByArray, + }, + }), + } + ).then( + () => { + navigate( + `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${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); + } + ); + }; + + return ( +
+ +

Add Process Model

+
+ +
+ +
+ +
+
+

Like: month=3,milestone=2

+ +
+ +
+
+ ); +} diff --git a/src/routes/ProcessInstanceReportShow.tsx b/src/routes/ProcessInstanceReportShow.tsx index 531d335..063c76b 100644 --- a/src/routes/ProcessInstanceReportShow.tsx +++ b/src/routes/ProcessInstanceReportShow.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; -import { Table } from 'react-bootstrap'; +import { Button, Table } from 'react-bootstrap'; import { BACKEND_BASE_URL, HOT_AUTH_TOKEN } from '../config'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; @@ -46,7 +46,6 @@ export default function ProcessInstanceReport() { (result) => { const processInstancesFromApi = result.results; setProcessInstances(processInstancesFromApi); - console.log('result.report_metaadata', result.report_metadata); setReportMetadata(result.report_metadata); setPagination(result.pagination); }, @@ -97,6 +96,11 @@ export default function ProcessInstanceReport() { linkProcessModel="true" />

Process Instance Report: {params.report_identifier}

+