display groups as tiles on list page w/ burnettk

This commit is contained in:
jasquat 2022-11-18 12:42:08 -05:00
parent 358b54df0a
commit d393683794
6 changed files with 107 additions and 62 deletions

View File

@ -445,7 +445,6 @@ paths:
description: For filtering - indicates the user has manually entered a query
schema:
type: boolean
# process_instance_list
get:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_list
summary: Returns a list of process instances for a given process model

View File

@ -55,13 +55,24 @@ class ProcessGroupSchema(Schema):
"""Meta."""
model = ProcessGroup
fields = ["id", "display_name", "display_order", "admin", "process_models"]
fields = [
"id",
"display_name",
"display_order",
"admin",
"process_models",
"description",
"process_groups",
]
process_models = marshmallow.fields.List(
marshmallow.fields.Nested(
"ProcessModelInfoSchema", dump_only=True, required=False
)
)
process_groups = marshmallow.fields.List(
marshmallow.fields.Nested("ProcessGroupSchema", dump_only=True, required=False)
)
@post_load
def make_process_group(

View File

@ -71,7 +71,7 @@ h1{
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
monospace;
}
.app-logo {
@ -182,9 +182,53 @@ h1.with-icons {
}
/* Json Web Form CSS Fix - Bootstrap now requries that each li have a "list-inline-item." Also have a PR
in on this with the react-jsonschema-form repo. This is just a patch fix to allow date inputs to layout a little more cleanly */
in on this with the react-jsonschema-form repo. This is just a patch fix to allow date inputs to layout a little more cleanly */
.list-inline>li {
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}
.cds--tile.tile-process-group {
padding: 0px;
margin: 16px;
width: 354px;
height: 264px;
background: #F4F4F4;
order: 1;
float: left;
}
.tile-process-group-content-container {
width: 354px;
height: 264px;
padding: 1em;
position: relative;
}
.tile-process-group-display-name {
margin-top: 2em;
margin-bottom: 1em;
font-size: 20px;
line-height: 28px;
color: #161616;
order: 0;
}
.tile-process-group-description {
font-size: 14px;
line-height: 20px;
letter-spacing: 0.16px;
color: #161616;
order: 1;
}
.tile-process-group-children-count {
font-size: 14px;
line-height: 20px;
letter-spacing: 0.16px;
color: #161616;
order: 1;
position: absolute;
bottom: 1em;
}

View File

@ -11,12 +11,6 @@ export interface RecentProcessModel {
processModelDisplayName: string;
}
export interface ProcessGroup {
id: string;
display_name: string;
description?: string | null;
}
export interface ProcessReference {
id: string; // The unique id of the process or decision table.
name: string; // The process or decision Display name.
@ -50,6 +44,14 @@ export interface ProcessModel {
files: ProcessFile[];
}
export interface ProcessGroup {
id: string;
display_name: string;
description?: string | null;
process_models?: ProcessModel[];
process_groups?: ProcessGroup[];
}
// tuple of display value and URL
export type HotCrumbItem = [displayValue: string, url?: string];

View File

@ -1,35 +1,36 @@
import { useEffect, useState } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import { useNavigate, useSearchParams } from 'react-router-dom';
import {
ArrowRight,
// @ts-ignore
} from '@carbon/icons-react';
import {
Button,
Table,
ClickableTile,
// @ts-ignore
} from '@carbon/react';
import { Can } from '@casl/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import PaginationForTable from '../components/PaginationForTable';
import HttpService from '../services/HttpService';
import {
getPageInfoFromSearchParams,
modifyProcessModelPath,
} from '../helpers';
import { modifyProcessModelPath, truncateString } from '../helpers';
import {
CarbonComboBoxSelection,
PermissionsToCheck,
ProcessGroup,
} from '../interfaces';
import ProcessModelSearch from '../components/ProcessModelSearch';
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
import { usePermissionFetcher } from '../hooks/PermissionService';
import ProcessModelSearch from '../components/ProcessModelSearch';
// Example process group json
// {'process_group_id': 'sure', 'display_name': 'Test Workflows', 'id': 'test_process_group'}
export default function ProcessGroupList() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const [processGroups, setProcessGroups] = useState([]);
const [pagination, setPagination] = useState(null);
const [processGroups, setProcessGroups] = useState<ProcessGroup[] | null>(
null
);
const [processModelAvailableItems, setProcessModelAvailableItems] = useState(
[]
);
@ -43,7 +44,6 @@ export default function ProcessGroupList() {
useEffect(() => {
const setProcessGroupsFromResult = (result: any) => {
setProcessGroups(result.results);
setPagination(result.pagination);
};
const processResultForProcessModels = (result: any) => {
const selectionArray = result.results.map((item: any) => {
@ -54,10 +54,9 @@ export default function ProcessGroupList() {
setProcessModelAvailableItems(selectionArray);
};
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
// for browsing
HttpService.makeCallToBackend({
path: `/process-groups?per_page=${perPage}&page=${page}`,
path: `/process-groups?per_page=1000`,
successCallback: setProcessGroupsFromResult,
});
// for search box
@ -67,48 +66,38 @@ export default function ProcessGroupList() {
});
}, [searchParams]);
const buildTable = () => {
const rows = processGroups.map((row: ProcessGroup) => {
return (
<tr key={(row as any).id}>
<td>
<Link
to={`/admin/process-groups/${(row as any).id}`}
title={(row as any).id}
>
{(row as any).display_name}
</Link>
</td>
</tr>
);
});
const processGroupDirectChildrenCount = (processGroup: ProcessGroup) => {
return (
<Table striped bordered>
<thead>
<tr>
<th>Process Group</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
(processGroup.process_models || []).length +
(processGroup.process_groups || []).length
);
};
const processGroupsDisplayArea = () => {
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
let displayText = null;
if (processGroups?.length > 0) {
displayText = (
<>
<h3>Browse</h3>
<PaginationForTable
page={page}
perPage={perPage}
pagination={pagination as any}
tableToDisplay={buildTable()}
/>
</>
);
if (processGroups && processGroups.length > 0) {
displayText = (processGroups || []).map((row: ProcessGroup) => {
return (
<ClickableTile
id="tile-1"
className="tile-process-group"
href={`/admin/process-groups/${row.id}`}
>
<div className="tile-process-group-content-container">
<ArrowRight />
<div className="tile-process-group-display-name">
{row.display_name}
</div>
<p className="tile-process-group-description">
{truncateString(row.description || '', 25)}
</p>
<p className="tile-process-group-children-count">
Total Sub Items: {processGroupDirectChildrenCount(row)}
</p>
</div>
</ClickableTile>
);
});
} else {
displayText = <p>No Groups To Display</p>;
}
@ -131,7 +120,7 @@ export default function ProcessGroupList() {
);
};
if (pagination) {
if (processGroups) {
return (
<>
<ProcessBreadcrumb hotCrumbs={[['Process Groups']]} />
@ -142,6 +131,7 @@ export default function ProcessGroupList() {
<br />
<br />
</Can>
<br />
{processModelSearchArea()}
<br />
{processGroupsDisplayArea()}

View File

@ -368,7 +368,6 @@ export default function ProcessModelShow() {
return constructedTag;
});
// return <ul>{tags}</ul>;
const headers = ['Name', 'Actions'];
return (
<Table size="lg" useZebraStyles={false}>