created process instance list and show pages to handle all and for-me w/ burnettk

This commit is contained in:
jasquat 2022-12-19 16:16:27 -05:00
parent bade105e7f
commit e938d81366
8 changed files with 325 additions and 27 deletions

View File

@ -509,6 +509,119 @@ paths:
schema:
$ref: "#/components/schemas/OkTrue"
/process-instances/for-me:
parameters:
- name: process_model_identifier
in: query
required: false
description: The unique id of an existing process model.
schema:
type: string
- name: page
in: query
required: false
description: The page number to return. Defaults to page 1.
schema:
type: integer
- name: per_page
in: query
required: false
description: The page number to return. Defaults to page 1.
schema:
type: integer
- name: start_from
in: query
required: false
description: For filtering - beginning of start window - in seconds since epoch
schema:
type: integer
- name: start_to
in: query
required: false
description: For filtering - end of start window - in seconds since epoch
schema:
type: integer
- name: end_from
in: query
required: false
description: For filtering - beginning of end window - in seconds since epoch
schema:
type: integer
- name: end_to
in: query
required: false
description: For filtering - end of end window - in seconds since epoch
schema:
type: integer
- name: process_status
in: query
required: false
description: For filtering - not_started, user_input_required, waiting, complete, error, or suspended
schema:
type: string
- name: initiated_by_me
in: query
required: false
description: For filtering - show instances initiated by me
schema:
type: boolean
- name: with_tasks_completed_by_me
in: query
required: false
description: For filtering - show instances with tasks completed by me
schema:
type: boolean
- name: with_tasks_completed_by_my_group
in: query
required: false
description: For filtering - show instances with tasks completed by my group
schema:
type: boolean
- name: with_relation_to_me
in: query
required: false
description: For filtering - show instances that have something to do with me
schema:
type: boolean
- name: user_filter
in: query
required: false
description: For filtering - indicates the user has manually entered a query
schema:
type: boolean
- name: report_identifier
in: query
required: false
description: Specifies the identifier of a report to use, if any
schema:
type: string
- name: report_id
in: query
required: false
description: Specifies the identifier of a report to use, if any
schema:
type: integer
- name: group_identifier
in: query
required: false
description: The identifier of the group to get the process instances for
schema:
type: string
get:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_list_for_me
summary: Returns a list of process instances that are associated with me.
tags:
- Process Instances
responses:
"200":
description: Workflow.
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Workflow"
/process-instances:
parameters:
- name: process_model_identifier
@ -609,7 +722,7 @@ paths:
type: string
get:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_list
summary: Returns a list of process instances for a given process model
summary: Returns a list of process instances.
tags:
- Process Instances
responses:
@ -732,6 +845,39 @@ paths:
items:
$ref: "#/components/schemas/Task"
/process-instances/for-me/{modified_process_model_identifier}/{process_instance_id}:
parameters:
- name: modified_process_model_identifier
in: path
required: true
description: The unique id of an existing process model
schema:
type: string
- name: process_instance_id
in: path
required: true
description: The unique id of an existing process instance.
schema:
type: integer
- name: process_identifier
in: query
required: false
description: The identifier of the process to use for the diagram. Useful for displaying the diagram for a call activity.
schema:
type: string
get:
tags:
- Process Instances
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_show_for_me
summary: Show information about a process instance that is associated with me
responses:
"200":
description: One Process Instance
content:
application/json:
schema:
$ref: "#/components/schemas/Workflow"
/process-instances/{modified_process_model_identifier}/{process_instance_id}:
parameters:
- name: modified_process_model_identifier

View File

@ -115,11 +115,11 @@ permissions:
users: []
allowed_permissions: [read]
uri: /v1.0/process-models/*
read-all-process-instance:
read-all-process-instance-for-me:
groups: [everybody]
users: []
allowed_permissions: [read]
uri: /v1.0/process-instances/*
uri: /v1.0/process-instances/for-me/*
read-process-instance-reports:
groups: [everybody]
users: []

View File

@ -848,6 +848,37 @@ def message_start(
)
def process_instance_list_for_me(
process_model_identifier: Optional[str] = None,
page: int = 1,
per_page: int = 100,
start_from: Optional[int] = None,
start_to: Optional[int] = None,
end_from: Optional[int] = None,
end_to: Optional[int] = None,
process_status: Optional[str] = None,
user_filter: Optional[bool] = False,
report_identifier: Optional[str] = None,
report_id: Optional[int] = None,
group_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
return process_instance_list(
process_model_identifier=process_model_identifier,
page=page,
per_page=per_page,
start_from=start_from,
start_to=start_to,
end_from=end_from,
end_to=end_to,
process_status=process_status,
user_filter=user_filter,
report_identifier=report_identifier,
report_id=report_id,
group_identifier=group_identifier,
with_relation_to_me=True,
)
def process_instance_list(
process_model_identifier: Optional[str] = None,
page: int = 1,
@ -951,7 +982,6 @@ def process_instance_list(
ProcessInstanceModel.status.in_(report_filter.process_status) # type: ignore
)
print(f"report_filter.with_relation_to_me: {report_filter.with_relation_to_me}")
if report_filter.with_relation_to_me is True:
process_instance_query = process_instance_query.outerjoin(
ActiveTaskModel
@ -1143,14 +1173,53 @@ def process_instance_report_column_list() -> flask.wrappers.Response:
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
def process_instance_show_for_me(
modified_process_model_identifier: str,
process_instance_id: int,
process_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
process_instance = ProcessInstanceModel.query.filter_by(id=process_instance_id).outerjoin(
ActiveTaskModel
).outerjoin(
ActiveTaskUserModel,
and_(
ActiveTaskModel.id == ActiveTaskUserModel.active_task_id,
ActiveTaskUserModel.user_id == g.user.id,
),
).filter(
or_(
ActiveTaskUserModel.id.is_not(None),
ProcessInstanceModel.process_initiator_id == g.user.id,
)
).first()
if process_instance is None:
raise (
ApiError(
error_code="process_instance_cannot_be_found",
message=f"Process instance with id {process_instance_id} cannot be found that is associated with you.",
status_code=400,
)
)
return _get_process_instance(process_instance=process_instance, modified_process_model_identifier=modified_process_model_identifier, process_identifier=process_identifier)
def process_instance_show(
modified_process_model_identifier: str,
process_instance_id: int,
process_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
"""Create_process_instance."""
process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_instance = find_process_instance_by_id_or_raise(process_instance_id)
return _get_process_instance(process_instance=process_instance, modified_process_model_identifier=modified_process_model_identifier, process_identifier=process_identifier)
def _get_process_instance(
modified_process_model_identifier: str,
process_instance: ProcessInstanceModel,
process_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
process_model_identifier = modified_process_model_identifier.replace(":", "/")
current_version_control_revision = GitService.get_current_revision()
process_model_with_diagram = None

View File

@ -70,6 +70,7 @@ const REFRESH_INTERVAL = 5;
const REFRESH_TIMEOUT = 600;
type OwnProps = {
apiPath?: string;
filtersEnabled?: boolean;
processModelFullIdentifier?: string;
paginationQueryParamPrefix?: string;
@ -80,6 +81,7 @@ type OwnProps = {
paginationClassName?: string;
autoReload?: boolean;
additionalParams?: string;
variant?: string;
};
interface dateParameters {
@ -87,6 +89,7 @@ interface dateParameters {
}
export default function ProcessInstanceListTable({
apiPath = '/process-instances',
filtersEnabled = true,
processModelFullIdentifier,
paginationQueryParamPrefix,
@ -97,6 +100,7 @@ export default function ProcessInstanceListTable({
textToShowIfEmpty,
paginationClassName,
autoReload = false,
variant = 'for-me',
}: OwnProps) {
const params = useParams();
const [searchParams] = useSearchParams();
@ -126,6 +130,11 @@ export default function ProcessInstanceListTable({
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const processInstancePathPrefix =
variant === 'all'
? '/admin/process-instances'
: '/admin/process-instances/for-me';
const [processStatusAllOptions, setProcessStatusAllOptions] = useState<any[]>(
[]
);
@ -260,7 +269,7 @@ export default function ProcessInstanceListTable({
}
HttpService.makeCallToBackend({
path: `/process-instances?${queryParamString}`,
path: `${apiPath}?${queryParamString}`,
successCallback: setProcessInstancesFromResult,
});
}
@ -516,7 +525,7 @@ export default function ProcessInstanceListTable({
setErrorMessage(null);
setProcessInstanceReportJustSaved(null);
navigate(`/admin/process-instances?${queryParamString}`);
navigate(`${processInstancePathPrefix}?${queryParamString}`);
};
const dateComponent = (
@ -615,7 +624,7 @@ export default function ProcessInstanceListTable({
setErrorMessage(null);
setProcessInstanceReportJustSaved(mode || null);
navigate(`/admin/process-instances${queryParamString}`);
navigate(`${processInstancePathPrefix}${queryParamString}`);
};
const reportColumns = () => {
@ -1081,7 +1090,7 @@ export default function ProcessInstanceListTable({
return (
<Link
data-qa="process-instance-show-link"
to={`/admin/process-instances/${modifiedProcessModelId}/${id}`}
to={`${processInstancePathPrefix}/${modifiedProcessModelId}/${id}`}
title={`View process instance ${id}`}
>
{id}

View File

@ -9,16 +9,16 @@ export const useUriListForPermissions = () => {
messageInstanceListPath: '/v1.0/messages',
processGroupListPath: '/v1.0/process-groups',
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
processInstanceCreatePath: `/v1.0/process-instances/${params.process_model_id}`,
processInstanceActionPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}`,
processInstanceResumePath: `/v1.0/process-instance-resume/${params.process_model_id}/${params.process_instance_id}`,
processInstanceSuspendPath: `/v1.0/process-instance-suspend/${params.process_model_id}/${params.process_instance_id}`,
processInstanceTerminatePath: `/v1.0/process-instance-terminate/${params.process_model_id}/${params.process_instance_id}`,
processInstanceCreatePath: `/v1.0/process-instances/${params.process_model_id}`,
processInstanceListPath: '/v1.0/process-instances',
processInstanceLogListPath: `/v1.0/logs/${params.process_model_id}/${params.process_instance_id}`,
processInstanceReportListPath: '/v1.0/process-instances/reports',
processInstanceTaskListPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}/task-info`,
processInstanceResumePath: `/v1.0/process-instance-resume/${params.process_model_id}/${params.process_instance_id}`,
processInstanceSuspendPath: `/v1.0/process-instance-suspend/${params.process_model_id}/${params.process_instance_id}`,
processInstanceTaskListDataPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`,
processInstanceTaskListPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}/task-info`,
processInstanceTerminatePath: `/v1.0/process-instance-terminate/${params.process_model_id}/${params.process_instance_id}`,
processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`,
processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`,
processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`,

View File

@ -62,21 +62,25 @@ export default function AdminRoutes() {
path="process-models/:process_model_id/files/:file_name"
element={<ProcessModelEditDiagram />}
/>
<Route
path="process-models/:process_model_id/process-instances"
element={<ProcessInstanceList />}
/>
<Route
path="process-models/:process_model_id/edit"
element={<ProcessModelEdit />}
/>
<Route
path="process-instances/for-me/:process_model_id/:process_instance_id"
element={<ProcessInstanceShow variant="for-me" />}
/>
<Route
path="process-instances/for-me/:process_model_id/:process_instance_id/:spiff_step"
element={<ProcessInstanceShow variant="for-me" />}
/>
<Route
path="process-instances/:process_model_id/:process_instance_id"
element={<ProcessInstanceShow />}
element={<ProcessInstanceShow variant="all" />}
/>
<Route
path="process-instances/:process_model_id/:process_instance_id/:spiff_step"
element={<ProcessInstanceShow />}
element={<ProcessInstanceShow variant="all" />}
/>
<Route
path="process-instances/reports"
@ -106,7 +110,18 @@ export default function AdminRoutes() {
path="logs/:process_model_id/:process_instance_id"
element={<ProcessInstanceLogList />}
/>
<Route path="process-instances" element={<ProcessInstanceList />} />
<Route
path="process-instances"
element={<ProcessInstanceList variant="for-me" />}
/>
<Route
path="process-instances/for-me"
element={<ProcessInstanceList variant="for-me" />}
/>
<Route
path="process-instances/all"
element={<ProcessInstanceList variant="all" />}
/>
<Route path="messages" element={<MessageInstanceList />} />
<Route path="configuration/*" element={<Configuration />} />
<Route

View File

@ -1,15 +1,33 @@
import { useSearchParams } from 'react-router-dom';
import { useNavigate, useSearchParams } from 'react-router-dom';
import 'react-datepicker/dist/react-datepicker.css';
import 'react-bootstrap-typeahead/css/Typeahead.css';
import 'react-bootstrap-typeahead/css/Typeahead.bs5.css';
// @ts-ignore
import { Tabs, TabList, Tab } from '@carbon/react';
import { Can } from '@casl/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
import { getProcessModelFullIdentifierFromSearchParams } from '../helpers';
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
import { PermissionsToCheck } from '../interfaces';
import { usePermissionFetcher } from '../hooks/PermissionService';
export default function ProcessInstanceList() {
type OwnProps = {
variant: string;
};
export default function ProcessInstanceList({ variant }: OwnProps) {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const { targetUris } = useUriListForPermissions();
const permissionRequestData: PermissionsToCheck = {
[targetUris.processInstanceListPath]: ['GET'],
};
const { ability } = usePermissionFetcher(permissionRequestData);
const processInstanceBreadcrumbElement = () => {
const processModelFullIdentifier =
getProcessModelFullIdentifierFromSearchParams(searchParams);
@ -33,13 +51,46 @@ export default function ProcessInstanceList() {
};
const processInstanceTitleElement = () => {
return <h1>Process Instances</h1>;
if (variant === 'all') {
return <h1>All Process Instances</h1>;
}
return <h1>My Process Instances</h1>;
};
let apiPath = '/process-instances/for-me';
let selectedTabIndex = 0;
if (variant === 'all') {
apiPath = '/process-instances';
selectedTabIndex = 1;
}
return (
<>
<Tabs selectedIndex={selectedTabIndex}>
<TabList aria-label="List of tabs">
<Tab
title="Only show process instances for the current user."
onClick={() => {
navigate('/admin/process-instances/for-me');
}}
>
For Me
</Tab>
<Can I="GET" a={targetUris.processInstanceListPath} ability={ability}>
<Tab
title="Show all process instances for all users."
onClick={() => {
navigate('/admin/process-instances/all');
}}
>
All
</Tab>
</Can>
</TabList>
</Tabs>
<br />
{processInstanceBreadcrumbElement()}
{processInstanceTitleElement()}
<ProcessInstanceListTable additionalParams="with_relation_to_me=true" />
<ProcessInstanceListTable apiPath={apiPath} variant={variant} />
</>
);
}

View File

@ -47,7 +47,11 @@ import {
import { usePermissionFetcher } from '../hooks/PermissionService';
import ProcessInstanceClass from '../classes/ProcessInstanceClass';
export default function ProcessInstanceShow() {
type OwnProps = {
variant: string;
};
export default function ProcessInstanceShow({ variant }: OwnProps) {
const navigate = useNavigate();
const params = useParams();
const [searchParams] = useSearchParams();
@ -99,8 +103,12 @@ export default function ProcessInstanceShow() {
if (processIdentifier) {
queryParams = `?process_identifier=${processIdentifier}`;
}
let apiPath = '/process-instances/for-me';
if (variant === 'all') {
apiPath = '/process-instances';
}
HttpService.makeCallToBackend({
path: `/process-instances/${modifiedProcessModelId}/${params.process_instance_id}${queryParams}`,
path: `${apiPath}/${modifiedProcessModelId}/${params.process_instance_id}${queryParams}`,
successCallback: setProcessInstance,
});
let taskParams = '?all_tasks=true';