added crud support for reports w/ burnettk

This commit is contained in:
jasquat 2022-07-11 16:16:27 -04:00
parent 0ed60ab6e7
commit 0aa158d13b
5 changed files with 336 additions and 3 deletions

View File

@ -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={<ProcessInstanceReportShow />}
/>
<Route
path="process-models/:process_group_id/:process_model_id/process-instances/reports/new"
element={<ProcessInstanceReportNew />}
/>
<Route
path="process-models/:process_group_id/:process_model_id/process-instances/reports/:report_identifier/edit"
element={<ProcessInstanceReportEdit />}
/>
</Routes>
);
}

View File

@ -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 (
<main style={{ padding: '1rem 0' }}>
<ProcessBreadcrumb />
<h2>Edit Process Instance Report: {params.report_identifier}</h2>
<Button onClick={deleteProcessInstanceReport} variant="danger">
Delete report
</Button>
<br />
<br />
<form onSubmit={editProcessInstanceReport}>
<label htmlFor="columns">
columns:
<input
name="columns"
id="columns"
type="text"
value={columns}
onChange={(e) => setColumns(e.target.value)}
/>
</label>
<br />
<label htmlFor="order_by">
order_by:
<input
name="order_by"
id="order_by"
type="text"
value={orderBy}
onChange={(e) => setOrderBy(e.target.value)}
/>
</label>
<br />
<br />
<p>Like: month=3,milestone=2</p>
<label htmlFor="filter_by">
filter_by:
<input
name="filter_by"
id="filter_by"
type="text"
value={filterBy}
onChange={(e) => setFilterBy(e.target.value)}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
</main>
);
}

View File

@ -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 (
<main>
{headerStuff}
<Button
href={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/new`}
>
Add a process instance report
</Button>
{buildTable()}
</main>
);

View File

@ -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 (
<main style={{ padding: '1rem 0' }}>
<ProcessBreadcrumb />
<h2>Add Process Model</h2>
<form onSubmit={addProcessInstanceReport}>
<label htmlFor="identifier">
identifier:
<input
name="identifier"
id="identifier"
type="text"
value={identifier}
onChange={(e) => setIdentifier(e.target.value)}
/>
</label>
<br />
<label htmlFor="columns">
columns:
<input
name="columns"
id="columns"
type="text"
value={columns}
onChange={(e) => setColumns(e.target.value)}
/>
</label>
<br />
<label htmlFor="order_by">
order_by:
<input
name="order_by"
id="order_by"
type="text"
value={orderBy}
onChange={(e) => setOrderBy(e.target.value)}
/>
</label>
<br />
<br />
<p>Like: month=3,milestone=2</p>
<label htmlFor="filter_by">
filter_by:
<input
name="filter_by"
id="filter_by"
type="text"
value={filterBy}
onChange={(e) => setFilterBy(e.target.value)}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
</main>
);
}

View File

@ -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"
/>
<h2>Process Instance Report: {params.report_identifier}</h2>
<Button
href={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_identifier}/edit`}
>
Edit process instance report
</Button>
<PaginationForTable
page={page}
perPage={perPage}