Feature/first five minutes (#601)

* added helpful text if no process groups and models, do not show start button on model tile if no primary file, and do not make unnecessary calls in ListTiles when we already have the info w/ burnettk

* added some help text to process model show page if not files are there w/ burnettk

---------

Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
jasquat 2023-11-09 10:49:26 -05:00 committed by GitHub
parent d5b0330609
commit 155f07d723
5 changed files with 122 additions and 133 deletions

View File

@ -16,13 +16,17 @@ import {
} from '../helpers'; } from '../helpers';
type OwnProps = { type OwnProps = {
defaultProcessGroups?: ProcessGroup[];
processGroup?: ProcessGroup; processGroup?: ProcessGroup;
headerElement?: ReactElement; headerElement?: ReactElement;
showNoItemsDisplayText?: boolean;
}; };
export default function ProcessGroupListTiles({ export default function ProcessGroupListTiles({
defaultProcessGroups,
processGroup, processGroup,
headerElement, headerElement,
showNoItemsDisplayText,
}: OwnProps) { }: OwnProps) {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
@ -34,6 +38,10 @@ export default function ProcessGroupListTiles({
const setProcessGroupsFromResult = (result: any) => { const setProcessGroupsFromResult = (result: any) => {
setProcessGroups(result.results); setProcessGroups(result.results);
}; };
if (defaultProcessGroups) {
setProcessGroups(defaultProcessGroups);
} else {
let queryParams = '?per_page=1000'; let queryParams = '?per_page=1000';
if (processGroup) { if (processGroup) {
queryParams = `${queryParams}&process_group_identifier=${processGroup.id}`; queryParams = `${queryParams}&process_group_identifier=${processGroup.id}`;
@ -42,7 +50,8 @@ export default function ProcessGroupListTiles({
path: `/process-groups${queryParams}`, path: `/process-groups${queryParams}`,
successCallback: setProcessGroupsFromResult, successCallback: setProcessGroupsFromResult,
}); });
}, [searchParams, processGroup]); }
}, [searchParams, processGroup, defaultProcessGroups]);
const processGroupDirectChildrenCount = (pg: ProcessGroup) => { const processGroupDirectChildrenCount = (pg: ProcessGroup) => {
return (pg.process_models || []).length + (pg.process_groups || []).length; return (pg.process_models || []).length + (pg.process_groups || []).length;
@ -76,13 +85,19 @@ export default function ProcessGroupListTiles({
); );
}); });
} else { } else {
displayText = <p>No Groups To Display</p>; displayText = (
<p className="no-results-message">
There are no process groups to display. You can add one by clicking
the &quot;Add a process group&quot; button. Process groups can contain
additional process groups and / or process models.
</p>
);
} }
return displayText; return displayText;
}; };
const processGroupArea = () => { const processGroupArea = () => {
if (processGroups && (!processGroup || processGroups.length > 0)) { if (processGroups && (showNoItemsDisplayText || processGroups.length > 0)) {
return ( return (
<> <>
{headerElement} {headerElement}

View File

@ -13,15 +13,21 @@ import {
import ProcessInstanceRun from './ProcessInstanceRun'; import ProcessInstanceRun from './ProcessInstanceRun';
type OwnProps = { type OwnProps = {
defaultProcessModels?: ProcessModel[];
headerElement?: ReactElement; headerElement?: ReactElement;
processGroup?: ProcessGroup; processGroup?: ProcessGroup;
checkPermissions?: boolean; checkPermissions?: boolean;
onLoadFunction?: Function;
showNoItemsDisplayText?: boolean;
}; };
export default function ProcessModelListTiles({ export default function ProcessModelListTiles({
defaultProcessModels,
headerElement, headerElement,
processGroup, processGroup,
checkPermissions = true, checkPermissions = true,
onLoadFunction,
showNoItemsDisplayText,
}: OwnProps) { }: OwnProps) {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const [processModels, setProcessModels] = useState<ProcessModel[] | null>( const [processModels, setProcessModels] = useState<ProcessModel[] | null>(
@ -31,7 +37,14 @@ export default function ProcessModelListTiles({
useEffect(() => { useEffect(() => {
const setProcessModelsFromResult = (result: any) => { const setProcessModelsFromResult = (result: any) => {
setProcessModels(result.results); setProcessModels(result.results);
if (onLoadFunction) {
onLoadFunction(result);
}
}; };
if (defaultProcessModels) {
setProcessModels(defaultProcessModels);
} else {
// only allow 10 for now until we get the backend only returning certain models for user execution // only allow 10 for now until we get the backend only returning certain models for user execution
let queryParams = '?per_page=1000'; let queryParams = '?per_page=1000';
if (processGroup) { if (processGroup) {
@ -43,7 +56,8 @@ export default function ProcessModelListTiles({
path: `/process-models${queryParams}`, path: `/process-models${queryParams}`,
successCallback: setProcessModelsFromResult, successCallback: setProcessModelsFromResult,
}); });
}, [searchParams, processGroup]); }
}, [searchParams, processGroup, onLoadFunction, defaultProcessModels]);
const processModelsDisplayArea = () => { const processModelsDisplayArea = () => {
let displayText = null; let displayText = null;
@ -69,23 +83,32 @@ export default function ProcessModelListTiles({
<p className="tile-description"> <p className="tile-description">
{truncateString(row.description || '', 100)} {truncateString(row.description || '', 100)}
</p> </p>
{row.primary_file_name ? (
<ProcessInstanceRun <ProcessInstanceRun
processModel={row} processModel={row}
className="tile-pin-bottom" className="tile-pin-bottom"
checkPermissions={checkPermissions} checkPermissions={checkPermissions}
/> />
) : null}
</div> </div>
</Tile> </Tile>
); );
}); });
} else { } else {
displayText = <p>No Models To Display</p>; displayText = (
<p className="no-results-message">
There are no process models to display. You can add one by clicking
the &quot;Add a process model&quot; button. Process models will
contain the bpmn diagrams and supporting files needed to create a
runnable workflow.
</p>
);
} }
return displayText; return displayText;
}; };
const processModelArea = () => { const processModelArea = () => {
if (processModels && processModels.length > 0) { if (processModels && (showNoItemsDisplayText || processModels.length > 0)) {
return ( return (
<> <>
{headerElement} {headerElement}

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { import {
Button, Button,
// @ts-ignore // @ts-ignore
@ -15,7 +15,6 @@ import ProcessModelSearch from '../components/ProcessModelSearch';
import ProcessGroupListTiles from '../components/ProcessGroupListTiles'; import ProcessGroupListTiles from '../components/ProcessGroupListTiles';
export default function ProcessGroupList() { export default function ProcessGroupList() {
const [searchParams] = useSearchParams();
const navigate = useNavigate(); const navigate = useNavigate();
const [processModelAvailableItems, setProcessModelAvailableItems] = useState( const [processModelAvailableItems, setProcessModelAvailableItems] = useState(
@ -43,9 +42,12 @@ export default function ProcessGroupList() {
successCallback: processResultForProcessModels, successCallback: processResultForProcessModels,
}); });
setPageTitle(['Process Groups']); setPageTitle(['Process Groups']);
}, [searchParams]); }, []);
const processModelSearchArea = () => { const processModelSearchArea = () => {
if (processModelAvailableItems.length < 1) {
return null;
}
const processModelSearchOnChange = (selection: CarbonComboBoxSelection) => { const processModelSearchOnChange = (selection: CarbonComboBoxSelection) => {
const processModel = selection.selectedItem; const processModel = selection.selectedItem;
navigate( navigate(
@ -77,7 +79,7 @@ export default function ProcessGroupList() {
<br /> <br />
{processModelSearchArea()} {processModelSearchArea()}
<br /> <br />
<ProcessGroupListTiles /> <ProcessGroupListTiles showNoItemsDisplayText />
</> </>
); );
} }

View File

@ -1,10 +1,5 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { import { useParams, useNavigate } from 'react-router-dom';
// Link,
useSearchParams,
useParams,
useNavigate,
} from 'react-router-dom';
import { import {
TrashCan, TrashCan,
Edit, Edit,
@ -15,14 +10,8 @@ import { Button, Stack } from '@carbon/react';
import { Can } from '@casl/react'; import { Can } from '@casl/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import HttpService from '../services/HttpService'; import HttpService from '../services/HttpService';
import { modifyProcessIdentifierForPathParam, setPageTitle } from '../helpers';
import { import {
getPageInfoFromSearchParams,
modifyProcessIdentifierForPathParam,
unModifyProcessIdentifierForPathParam,
setPageTitle,
} from '../helpers';
import {
PaginationObject,
PermissionsToCheck, PermissionsToCheck,
ProcessGroup, ProcessGroup,
// ProcessModel, // ProcessModel,
@ -35,13 +24,9 @@ import ProcessModelListTiles from '../components/ProcessModelListTiles';
export default function ProcessGroupShow() { export default function ProcessGroupShow() {
const params = useParams(); const params = useParams();
const [searchParams] = useSearchParams();
const navigate = useNavigate(); const navigate = useNavigate();
const [processGroup, setProcessGroup] = useState<ProcessGroup | null>(null); const [processGroup, setProcessGroup] = useState<ProcessGroup | null>(null);
// const [processModels, setProcessModels] = useState([]);
const [modelPagination, setModelPagination] =
useState<PaginationObject | null>(null);
const { targetUris } = useUriListForPermissions(); const { targetUris } = useUriListForPermissions();
const permissionRequestData: PermissionsToCheck = { const permissionRequestData: PermissionsToCheck = {
@ -52,65 +37,15 @@ export default function ProcessGroupShow() {
const { ability } = usePermissionFetcher(permissionRequestData); const { ability } = usePermissionFetcher(permissionRequestData);
useEffect(() => { useEffect(() => {
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
const setProcessModelFromResult = (result: any) => {
// setProcessModels(result.results);
setModelPagination(result.pagination);
};
const processResult = (result: any) => { const processResult = (result: any) => {
setProcessGroup(result); setProcessGroup(result);
setPageTitle([result.display_name]); setPageTitle([result.display_name]);
const unmodifiedProcessGroupId = unModifyProcessIdentifierForPathParam(
(params as any).process_group_id
);
HttpService.makeCallToBackend({
path: `/process-models?process_group_identifier=${unmodifiedProcessGroupId}&per_page=${perPage}&page=${page}`,
successCallback: setProcessModelFromResult,
});
}; };
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-groups/${params.process_group_id}`, path: `/process-groups/${params.process_group_id}`,
successCallback: processResult, successCallback: processResult,
}); });
}, [params, searchParams]); }, [params.process_group_id]);
// const buildModelTable = () => {
// if (processGroup === null) {
// return null;
// }
// const rows = processModels.map((row: ProcessModel) => {
// const modifiedProcessModelId: String =
// modifyProcessIdentifierForPathParam((row as any).id);
// return (
// <tr key={row.id}>
// <td>
// <Link
// to={`/process-models/${modifiedProcessModelId}`}
// data-qa="process-model-show-link"
// >
// {row.id}
// </Link>
// </td>
// <td>{row.display_name}</td>
// </tr>
// );
// });
// return (
// <div>
// <h2>Process Models</h2>
// <Table striped bordered>
// <thead>
// <tr>
// <th>Process Model Id</th>
// <th>Display Name</th>
// </tr>
// </thead>
// <tbody>{rows}</tbody>
// </Table>
// </div>
// );
// };
const navigateToProcessGroups = (_result: any) => { const navigateToProcessGroups = (_result: any) => {
navigate(`/process-groups`); navigate(`/process-groups`);
@ -128,11 +63,13 @@ export default function ProcessGroupShow() {
} }
}; };
if (processGroup && modelPagination) { if (processGroup) {
// const { page, perPage } = getPageInfoFromSearchParams(searchParams);
const modifiedProcessGroupId = modifyProcessIdentifierForPathParam( const modifiedProcessGroupId = modifyProcessIdentifierForPathParam(
processGroup.id processGroup.id
); );
const showNoItemsDisplayText =
(processGroup.process_groups || []).length < 1 &&
(processGroup.process_models || []).length < 1;
return ( return (
<> <>
<ProcessBreadcrumb <ProcessBreadcrumb
@ -198,21 +135,16 @@ export default function ProcessGroupShow() {
<ProcessModelListTiles <ProcessModelListTiles
headerElement={<h2>Process Models</h2>} headerElement={<h2>Process Models</h2>}
processGroup={processGroup} processGroup={processGroup}
defaultProcessModels={processGroup.process_models}
showNoItemsDisplayText={showNoItemsDisplayText}
/> />
{/* eslint-disable-next-line sonarjs/no-gratuitous-expressions */}
{/* {modelPagination && modelPagination.total > 0 && (
<PaginationForTable
page={page}
perPage={perPage}
pagination={modelPagination}
tableToDisplay={buildModelTable()}
/>
)} */}
<br /> <br />
<br /> <br />
<ProcessGroupListTiles <ProcessGroupListTiles
processGroup={processGroup} processGroup={processGroup}
headerElement={<h2 className="clear-left">Process Groups</h2>} headerElement={<h2 className="clear-left">Process Groups</h2>}
defaultProcessGroups={processGroup.process_groups}
showNoItemsDisplayText={showNoItemsDisplayText}
/> />
</ul> </ul>
</> </>

View File

@ -371,6 +371,7 @@ export default function ProcessModelShow() {
return constructedTag; return constructedTag;
}); });
if (tags.length > 0) {
return ( return (
<Table <Table
size="lg" size="lg"
@ -394,6 +395,8 @@ export default function ProcessModelShow() {
<TableBody>{tags}</TableBody> <TableBody>{tags}</TableBody>
</Table> </Table>
); );
}
return null;
}; };
const [fileUploadEvent, setFileUploadEvent] = useState(null); const [fileUploadEvent, setFileUploadEvent] = useState(null);
@ -619,6 +622,19 @@ export default function ProcessModelShow() {
return null; return null;
} }
let helpText = null;
if (processModel.files.length === 0) {
helpText = (
<p className="no-results-message with-bottom-margin">
<strong>
**This process model does not have any files associated with it. Try
creating a bpmn file by selecting &quot;New BPMN File&quot; in the
dropdown below.**
</strong>
</p>
);
}
return ( return (
<Tabs selectedIndex={selectedTabIndex} onChange={updateSelectedTab}> <Tabs selectedIndex={selectedTabIndex} onChange={updateSelectedTab}>
<TabList aria-label="List of tabs"> <TabList aria-label="List of tabs">
@ -636,6 +652,7 @@ export default function ProcessModelShow() {
a={targetUris.processModelFileCreatePath} a={targetUris.processModelFileCreatePath}
ability={ability} ability={ability}
> >
{helpText}
<div className="with-bottom-margin"> <div className="with-bottom-margin">
Files Files
{processModel && {processModel &&