displaying process instances instead of tasks functionality is mostly complete. still need to update text on homepage and some cleanup

This commit is contained in:
jasquat 2023-04-13 14:12:09 -04:00
parent 091efb3d01
commit 9204bc490a
No known key found for this signature in database
4 changed files with 190 additions and 15 deletions

View File

@ -161,9 +161,12 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
@classmethod @classmethod
def terminal_statuses(cls) -> list[str]: def terminal_statuses(cls) -> list[str]:
"""Terminal_statuses."""
return ["complete", "error", "terminated"] return ["complete", "error", "terminated"]
@classmethod
def active_statuses(cls) -> list[str]:
return ["user_input_required", "waiting"]
class ProcessInstanceModelSchema(Schema): class ProcessInstanceModelSchema(Schema):
"""ProcessInstanceModelSchema.""" """ProcessInstanceModelSchema."""

View File

@ -1,5 +1,7 @@
"""Process_instance_report_service.""" """Process_instance_report_service."""
import re import re
from flask import current_app
from sqlalchemy.orm.util import AliasedClass
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from typing import Optional from typing import Optional
@ -17,7 +19,7 @@ from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel, ProcessInstanceStatus
from spiffworkflow_backend.models.process_instance_metadata import ( from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel, ProcessInstanceMetadataModel,
) )
@ -46,6 +48,7 @@ class ProcessInstanceReportFilter:
process_status: Optional[list[str]] = None process_status: Optional[list[str]] = None
initiated_by_me: Optional[bool] = None initiated_by_me: Optional[bool] = None
has_terminal_status: Optional[bool] = None has_terminal_status: Optional[bool] = None
has_active_status: Optional[bool] = None
with_tasks_completed_by_me: Optional[bool] = None with_tasks_completed_by_me: Optional[bool] = None
with_tasks_i_can_complete: Optional[bool] = None with_tasks_i_can_complete: Optional[bool] = None
with_tasks_assigned_to_my_group: Optional[bool] = None with_tasks_assigned_to_my_group: Optional[bool] = None
@ -53,6 +56,7 @@ class ProcessInstanceReportFilter:
process_initiator_username: Optional[str] = None process_initiator_username: Optional[str] = None
report_column_list: Optional[list] = None report_column_list: Optional[list] = None
report_filter_by_list: Optional[list] = None report_filter_by_list: Optional[list] = None
oldest_open_human_task_fields: Optional[list] = None
def to_dict(self) -> dict[str, str]: def to_dict(self) -> dict[str, str]:
"""To_dict.""" """To_dict."""
@ -76,6 +80,8 @@ class ProcessInstanceReportFilter:
d["initiated_by_me"] = str(self.initiated_by_me).lower() d["initiated_by_me"] = str(self.initiated_by_me).lower()
if self.has_terminal_status is not None: if self.has_terminal_status is not None:
d["has_terminal_status"] = str(self.has_terminal_status).lower() d["has_terminal_status"] = str(self.has_terminal_status).lower()
if self.has_active_status is not None:
d["has_active_status"] = str(self.has_active_status).lower()
if self.with_tasks_completed_by_me is not None: if self.with_tasks_completed_by_me is not None:
d["with_tasks_completed_by_me"] = str(self.with_tasks_completed_by_me).lower() d["with_tasks_completed_by_me"] = str(self.with_tasks_completed_by_me).lower()
if self.with_tasks_i_can_complete is not None: if self.with_tasks_i_can_complete is not None:
@ -90,6 +96,8 @@ class ProcessInstanceReportFilter:
d["report_column_list"] = str(self.report_column_list) d["report_column_list"] = str(self.report_column_list)
if self.report_filter_by_list is not None: if self.report_filter_by_list is not None:
d["report_filter_by_list"] = str(self.report_filter_by_list) d["report_filter_by_list"] = str(self.report_filter_by_list)
if self.oldest_open_human_task_fields is not None:
d["oldest_open_human_task_fields"] = str(self.oldest_open_human_task_fields)
return d return d
@ -150,32 +158,57 @@ class ProcessInstanceReportService:
"Header": "process_model_display_name", "Header": "process_model_display_name",
"accessor": "process_model_display_name", "accessor": "process_model_display_name",
}, },
{"Header": "start_in_seconds", "accessor": "start_in_seconds"}, {"Header": "Task", "accessor": "task_title"},
{"Header": "end_in_seconds", "accessor": "end_in_seconds"}, {"Header": "Waiting For", "accessor": "waiting_for"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
{"Header": "status", "accessor": "status"}, {"Header": "status", "accessor": "status"},
], ],
"filter_by": [ "filter_by": [
{"field_name": "initiated_by_me", "field_value": "true"}, {"field_name": "initiated_by_me", "field_value": "true"},
{"field_name": "has_terminal_status", "field_value": "false"}, {"field_name": "has_terminal_status", "field_value": "false"},
{"field_name": "oldest_open_human_task_fields", "field_value": ['task_id', 'task_title', 'task_name', 'potential_owner_usernames', 'assigned_user_group_identifier']},
], ],
"order_by": ["-start_in_seconds", "-id"], "order_by": ["-start_in_seconds", "-id"],
}, },
"system_report_in_progress_instances_with_tasks_for_me": { "system_report_in_progress_instances_with_tasks_for_me": {
"columns": cls.builtin_column_options(), "columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [ "filter_by": [
{"field_name": "with_tasks_i_can_complete", "field_value": "true"}, {"field_name": "with_tasks_i_can_complete", "field_value": "true"},
{"field_name": "has_terminal_status", "field_value": "false"}, {"field_name": "has_active_status", "field_value": "true"},
{"field_name": "oldest_open_human_task_fields", "field_value": ['task_id', 'task_title', 'task_name']},
], ],
"order_by": ["-start_in_seconds", "-id"], "order_by": ["-start_in_seconds", "-id"],
}, },
"system_report_in_progress_instances_with_tasks_for_my_group": { "system_report_in_progress_instances_with_tasks_for_my_group": {
"columns": cls.builtin_column_options(), "columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [ "filter_by": [
{ {
"field_name": "with_tasks_assigned_to_my_group", "field_name": "with_tasks_assigned_to_my_group",
"field_value": "true", "field_value": "true",
}, },
{"field_name": "has_terminal_status", "field_value": "false"}, {"field_name": "has_active_status", "field_value": "true"},
{"field_name": "oldest_open_human_task_fields", "field_value": ['task_id', 'task_title', 'task_name']},
], ],
"order_by": ["-start_in_seconds", "-id"], "order_by": ["-start_in_seconds", "-id"],
}, },
@ -251,7 +284,11 @@ class ProcessInstanceReportService:
def list_value(key: str) -> Optional[list[str]]: def list_value(key: str) -> Optional[list[str]]:
"""List_value.""" """List_value."""
return filters[key].split(",") if key in filters else None if key not in filters:
return None
if isinstance(filters[key], list):
return filters[key]
return filters[key].split(",")
process_model_identifier = filters.get("process_model_identifier") process_model_identifier = filters.get("process_model_identifier")
user_group_identifier = filters.get("user_group_identifier") user_group_identifier = filters.get("user_group_identifier")
@ -262,6 +299,7 @@ class ProcessInstanceReportService:
process_status = list_value("process_status") process_status = list_value("process_status")
initiated_by_me = bool_value("initiated_by_me") initiated_by_me = bool_value("initiated_by_me")
has_terminal_status = bool_value("has_terminal_status") has_terminal_status = bool_value("has_terminal_status")
has_active_status = bool_value("has_active_status")
with_tasks_completed_by_me = bool_value("with_tasks_completed_by_me") with_tasks_completed_by_me = bool_value("with_tasks_completed_by_me")
with_tasks_i_can_complete = bool_value("with_tasks_i_can_complete") with_tasks_i_can_complete = bool_value("with_tasks_i_can_complete")
with_tasks_assigned_to_my_group = bool_value("with_tasks_assigned_to_my_group") with_tasks_assigned_to_my_group = bool_value("with_tasks_assigned_to_my_group")
@ -269,6 +307,7 @@ class ProcessInstanceReportService:
process_initiator_username = filters.get("process_initiator_username") process_initiator_username = filters.get("process_initiator_username")
report_column_list = list_value("report_column_list") report_column_list = list_value("report_column_list")
report_filter_by_list = list_value("report_filter_by_list") report_filter_by_list = list_value("report_filter_by_list")
oldest_open_human_task_fields = list_value("oldest_open_human_task_fields")
report_filter = ProcessInstanceReportFilter( report_filter = ProcessInstanceReportFilter(
process_model_identifier=process_model_identifier, process_model_identifier=process_model_identifier,
@ -280,6 +319,7 @@ class ProcessInstanceReportService:
process_status=process_status, process_status=process_status,
initiated_by_me=initiated_by_me, initiated_by_me=initiated_by_me,
has_terminal_status=has_terminal_status, has_terminal_status=has_terminal_status,
has_active_status=has_active_status,
with_tasks_completed_by_me=with_tasks_completed_by_me, with_tasks_completed_by_me=with_tasks_completed_by_me,
with_tasks_i_can_complete=with_tasks_i_can_complete, with_tasks_i_can_complete=with_tasks_i_can_complete,
with_tasks_assigned_to_my_group=with_tasks_assigned_to_my_group, with_tasks_assigned_to_my_group=with_tasks_assigned_to_my_group,
@ -287,6 +327,7 @@ class ProcessInstanceReportService:
process_initiator_username=process_initiator_username, process_initiator_username=process_initiator_username,
report_column_list=report_column_list, report_column_list=report_column_list,
report_filter_by_list=report_filter_by_list, report_filter_by_list=report_filter_by_list,
oldest_open_human_task_fields=oldest_open_human_task_fields,
) )
return report_filter return report_filter
@ -304,6 +345,7 @@ class ProcessInstanceReportService:
process_status: Optional[str] = None, process_status: Optional[str] = None,
initiated_by_me: Optional[bool] = None, initiated_by_me: Optional[bool] = None,
has_terminal_status: Optional[bool] = None, has_terminal_status: Optional[bool] = None,
has_active_status: Optional[bool] = None,
with_tasks_completed_by_me: Optional[bool] = None, with_tasks_completed_by_me: Optional[bool] = None,
with_tasks_i_can_complete: Optional[bool] = None, with_tasks_i_can_complete: Optional[bool] = None,
with_tasks_assigned_to_my_group: Optional[bool] = None, with_tasks_assigned_to_my_group: Optional[bool] = None,
@ -311,6 +353,7 @@ class ProcessInstanceReportService:
process_initiator_username: Optional[str] = None, process_initiator_username: Optional[str] = None,
report_column_list: Optional[list] = None, report_column_list: Optional[list] = None,
report_filter_by_list: Optional[list] = None, report_filter_by_list: Optional[list] = None,
oldest_open_human_task_fields: Optional[list] = None,
) -> ProcessInstanceReportFilter: ) -> ProcessInstanceReportFilter:
"""Filter_from_metadata_with_overrides.""" """Filter_from_metadata_with_overrides."""
report_filter = cls.filter_from_metadata(process_instance_report) report_filter = cls.filter_from_metadata(process_instance_report)
@ -333,6 +376,8 @@ class ProcessInstanceReportService:
report_filter.initiated_by_me = initiated_by_me report_filter.initiated_by_me = initiated_by_me
if has_terminal_status is not None: if has_terminal_status is not None:
report_filter.has_terminal_status = has_terminal_status report_filter.has_terminal_status = has_terminal_status
if has_active_status is not None:
report_filter.has_active_status = has_active_status
if with_tasks_completed_by_me is not None: if with_tasks_completed_by_me is not None:
report_filter.with_tasks_completed_by_me = with_tasks_completed_by_me report_filter.with_tasks_completed_by_me = with_tasks_completed_by_me
if with_tasks_i_can_complete is not None: if with_tasks_i_can_complete is not None:
@ -343,6 +388,8 @@ class ProcessInstanceReportService:
report_filter.report_column_list = report_column_list report_filter.report_column_list = report_column_list
if report_filter_by_list is not None: if report_filter_by_list is not None:
report_filter.report_filter_by_list = report_filter_by_list report_filter.report_filter_by_list = report_filter_by_list
if oldest_open_human_task_fields is not None:
report_filter.oldest_open_human_task_fields = oldest_open_human_task_fields
if with_tasks_assigned_to_my_group is not None: if with_tasks_assigned_to_my_group is not None:
report_filter.with_tasks_assigned_to_my_group = with_tasks_assigned_to_my_group report_filter.with_tasks_assigned_to_my_group = with_tasks_assigned_to_my_group
if with_relation_to_me is not None: if with_relation_to_me is not None:
@ -361,8 +408,6 @@ class ProcessInstanceReportService:
for process_instance_row in process_instance_sqlalchemy_rows: for process_instance_row in process_instance_sqlalchemy_rows:
process_instance_mapping = process_instance_row._mapping process_instance_mapping = process_instance_row._mapping
process_instance_dict = process_instance_row[0].serialized process_instance_dict = process_instance_row[0].serialized
if 'task_guid' in process_instance_mapping:
process_instance_dict['task_guid'] = process_instance_mapping['task_guid']
for metadata_column in metadata_columns: for metadata_column in metadata_columns:
if metadata_column["accessor"] not in process_instance_dict: if metadata_column["accessor"] not in process_instance_dict:
process_instance_dict[metadata_column["accessor"]] = process_instance_mapping[ process_instance_dict[metadata_column["accessor"]] = process_instance_mapping[
@ -372,6 +417,50 @@ class ProcessInstanceReportService:
results.append(process_instance_dict) results.append(process_instance_dict)
return results return results
@classmethod
def add_human_task_fields(cls, process_instance_dicts: list[dict], oldest_open_human_task_fields: list) -> list[dict]:
for process_instance_dict in process_instance_dicts:
assigned_user = aliased(UserModel)
human_task_query = (
HumanTaskModel.query.filter_by(process_instance_id=process_instance_dict['id'])
.group_by(HumanTaskModel.id)
.outerjoin(
HumanTaskUserModel,
HumanTaskModel.id == HumanTaskUserModel.human_task_id,
)
.outerjoin(assigned_user, assigned_user.id == HumanTaskUserModel.user_id)
.outerjoin(GroupModel, GroupModel.id == HumanTaskModel.lane_assignment_id)
)
potential_owner_usernames_from_group_concat_or_similar = cls._get_potential_owner_usernames(assigned_user)
human_task = (
human_task_query.add_columns(
HumanTaskModel.task_id,
HumanTaskModel.task_name,
HumanTaskModel.task_title,
func.max(GroupModel.identifier).label("assigned_user_group_identifier"),
potential_owner_usernames_from_group_concat_or_similar
).order_by(HumanTaskModel.id.asc()).first() # type: ignore
)
if human_task is not None:
for field in oldest_open_human_task_fields:
process_instance_dict[field] = getattr(human_task, field)
return process_instance_dicts
@classmethod
def _get_potential_owner_usernames(cls, assigned_user: AliasedClass) -> Any:
"""_get_potential_owner_usernames."""
potential_owner_usernames_from_group_concat_or_similar = func.group_concat(
assigned_user.username.distinct()
).label("potential_owner_usernames")
db_type = current_app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE")
if db_type == "postgres":
potential_owner_usernames_from_group_concat_or_similar = func.string_agg(
assigned_user.username.distinct(), ", "
).label("potential_owner_usernames")
return potential_owner_usernames_from_group_concat_or_similar
@classmethod @classmethod
def get_column_names_for_model(cls, model: Type[SpiffworkflowBaseDBModel]) -> list[str]: def get_column_names_for_model(cls, model: Type[SpiffworkflowBaseDBModel]) -> list[str]:
"""Get_column_names_for_model.""" """Get_column_names_for_model."""
@ -460,6 +549,10 @@ class ProcessInstanceReportService:
process_instance_query = process_instance_query.filter( process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.not_in(ProcessInstanceModel.terminal_statuses()) # type: ignore ProcessInstanceModel.status.not_in(ProcessInstanceModel.terminal_statuses()) # type: ignore
) )
if report_filter.has_active_status is True:
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.in_(ProcessInstanceModel.active_statuses()) # type: ignore
)
if report_filter.process_initiator_username is not None: if report_filter.process_initiator_username is not None:
initiator = UserModel.query.filter_by(username=report_filter.process_initiator_username).first() initiator = UserModel.query.filter_by(username=report_filter.process_initiator_username).first()
@ -531,7 +624,7 @@ class ProcessInstanceReportService:
process_instance_query = process_instance_query.filter(UserGroupAssignmentModel.user_id == user.id) process_instance_query = process_instance_query.filter(UserGroupAssignmentModel.user_id == user.id)
instance_metadata_aliases = {} instance_metadata_aliases = {}
stock_columns = ProcessInstanceReportService.get_column_names_for_model(ProcessInstanceModel) stock_columns = cls.get_column_names_for_model(ProcessInstanceModel)
if isinstance(report_filter.report_column_list, list): if isinstance(report_filter.report_column_list, list):
process_instance_report.report_metadata["columns"] = report_filter.report_column_list process_instance_report.report_metadata["columns"] = report_filter.report_column_list
if isinstance(report_filter.report_filter_by_list, list): if isinstance(report_filter.report_filter_by_list, list):
@ -581,16 +674,19 @@ class ProcessInstanceReportService:
order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).desc()) order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).desc())
else: else:
order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).asc()) order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).asc())
# return process_instance_query
process_instances = ( process_instances = (
process_instance_query.group_by(ProcessInstanceModel.id) process_instance_query.group_by(ProcessInstanceModel.id)
.add_columns(ProcessInstanceModel.id) .add_columns(ProcessInstanceModel.id)
.order_by(*order_by_query_array) .order_by(*order_by_query_array)
.paginate(page=page, per_page=per_page, error_out=False) .paginate(page=page, per_page=per_page, error_out=False)
) )
results = ProcessInstanceReportService.add_metadata_columns_to_process_instance( results = cls.add_metadata_columns_to_process_instance(
process_instances.items, process_instance_report.report_metadata["columns"] process_instances.items, process_instance_report.report_metadata["columns"]
) )
if report_filter.oldest_open_human_task_fields:
results = cls.add_human_task_fields(results, report_filter.oldest_open_human_task_fields)
response_json = { response_json = {
"report": process_instance_report, "report": process_instance_report,
"results": results, "results": results,

View File

@ -69,6 +69,8 @@ import { Notification } from './Notification';
import useAPIError from '../hooks/UseApiError'; import useAPIError from '../hooks/UseApiError';
import { usePermissionFetcher } from '../hooks/PermissionService'; import { usePermissionFetcher } from '../hooks/PermissionService';
import { Can } from '../contexts/Can'; import { Can } from '../contexts/Can';
import TableCellWithTimeAgoInWords from './TableCellWithTimeAgoInWords';
import UserService from '../services/UserService';
type OwnProps = { type OwnProps = {
filtersEnabled?: boolean; filtersEnabled?: boolean;
@ -82,6 +84,8 @@ type OwnProps = {
autoReload?: boolean; autoReload?: boolean;
additionalParams?: string; additionalParams?: string;
variant?: string; variant?: string;
canCompleteAllTasks?: boolean;
showActionsColumn?: boolean;
}; };
interface dateParameters { interface dateParameters {
@ -100,6 +104,8 @@ export default function ProcessInstanceListTable({
paginationClassName, paginationClassName,
autoReload = false, autoReload = false,
variant = 'for-me', variant = 'for-me',
canCompleteAllTasks = false,
showActionsColumn = false,
}: OwnProps) { }: OwnProps) {
let apiPath = '/process-instances/for-me'; let apiPath = '/process-instances/for-me';
if (variant === 'all') { if (variant === 'all') {
@ -141,6 +147,9 @@ export default function ProcessInstanceListTable({
const [requiresRefilter, setRequiresRefilter] = useState<boolean>(false); const [requiresRefilter, setRequiresRefilter] = useState<boolean>(false);
const [lastColumnFilter, setLastColumnFilter] = useState<string>(''); const [lastColumnFilter, setLastColumnFilter] = useState<string>('');
const preferredUsername = UserService.getPreferredUsername();
const userEmail = UserService.getUserEmail();
const processInstanceListPathPrefix = const processInstanceListPathPrefix =
variant === 'all' variant === 'all'
? '/admin/process-instances/all' ? '/admin/process-instances/all'
@ -1308,9 +1317,11 @@ export default function ProcessInstanceListTable({
return headerLabels[header] ?? header; return headerLabels[header] ?? header;
}; };
const headers = reportColumns().map((column: any) => { const headers = reportColumns().map((column: any) => {
// return <th>{getHeaderLabel((column as any).Header)}</th>;
return getHeaderLabel((column as any).Header); return getHeaderLabel((column as any).Header);
}); });
if (showActionsColumn) {
headers.push('Actions');
}
const formatProcessInstanceId = (row: ProcessInstance, id: number) => { const formatProcessInstanceId = (row: ProcessInstance, id: number) => {
return <span data-qa="paginated-entity-id">{id}</span>; return <span data-qa="paginated-entity-id">{id}</span>;
@ -1329,12 +1340,34 @@ export default function ProcessInstanceListTable({
return value; return value;
}; };
const getWaitingForTableCellComponent = (processInstanceTask: any) => {
let fullUsernameString = '';
let shortUsernameString = '';
if (processInstanceTask.potential_owner_usernames) {
fullUsernameString = processInstanceTask.potential_owner_usernames;
const usernames =
processInstanceTask.potential_owner_usernames.split(',');
const firstTwoUsernames = usernames.slice(0, 2);
if (usernames.length > 2) {
firstTwoUsernames.push('...');
}
shortUsernameString = firstTwoUsernames.join(',');
}
if (processInstanceTask.assigned_user_group_identifier) {
fullUsernameString = processInstanceTask.assigned_user_group_identifier;
shortUsernameString =
processInstanceTask.assigned_user_group_identifier;
}
return <span title={fullUsernameString}>{shortUsernameString}</span>;
};
const reportColumnFormatters: Record<string, any> = { const reportColumnFormatters: Record<string, any> = {
id: formatProcessInstanceId, id: formatProcessInstanceId,
process_model_identifier: formatProcessModelIdentifier, process_model_identifier: formatProcessModelIdentifier,
process_model_display_name: formatProcessModelDisplayName, process_model_display_name: formatProcessModelDisplayName,
start_in_seconds: formatSecondsForDisplay, start_in_seconds: formatSecondsForDisplay,
end_in_seconds: formatSecondsForDisplay, end_in_seconds: formatSecondsForDisplay,
updated_at_in_seconds: formatSecondsForDisplay,
}; };
const formattedColumn = (row: any, column: any) => { const formattedColumn = (row: any, column: any) => {
const formatter = const formatter =
@ -1377,6 +1410,16 @@ export default function ProcessInstanceListTable({
</td> </td>
); );
} }
if (column.accessor === 'waiting_for') {
return <td>{getWaitingForTableCellComponent(row)}</td>;
}
if (column.accessor === 'updated_at_in_seconds') {
return (
<TableCellWithTimeAgoInWords
timeInSeconds={row.updated_at_in_seconds}
/>
);
}
return ( return (
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
<td <td
@ -1393,7 +1436,35 @@ export default function ProcessInstanceListTable({
const currentRow = reportColumns().map((column: any) => { const currentRow = reportColumns().map((column: any) => {
return formattedColumn(row, column); return formattedColumn(row, column);
}); });
if (showActionsColumn) {
let buttonElement = null;
if (row.task_id) {
const taskUrl = `/tasks/${row.id}/${row.task_id}`;
const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`);
let hasAccessToCompleteTask = false;
if (
canCompleteAllTasks ||
(row.potential_owner_usernames || '').match(regex)
) {
hasAccessToCompleteTask = true;
}
buttonElement = (
<Button
variant="primary"
href={taskUrl}
hidden={row.status === 'suspended'}
disabled={!hasAccessToCompleteTask}
>
Go
</Button>
);
}
currentRow.push(<td>{buttonElement}</td>);
}
const rowStyle = { cursor: 'pointer' }; const rowStyle = { cursor: 'pointer' };
return ( return (
<tr style={rowStyle} key={row.id}> <tr style={rowStyle} key={row.id}>
{currentRow} {currentRow}

View File

@ -34,6 +34,8 @@ export default function InProgressInstances() {
showReports={false} showReports={false}
textToShowIfEmpty="This group has no completed instances at this time." textToShowIfEmpty="This group has no completed instances at this time."
additionalParams={`user_group_identifier=${userGroup}`} additionalParams={`user_group_identifier=${userGroup}`}
canCompleteAllTasks
showActionsColumn
autoReload={false} autoReload={false}
/> />
</> </>
@ -55,6 +57,7 @@ export default function InProgressInstances() {
showReports={false} showReports={false}
textToShowIfEmpty="There are no open instances you started at this time." textToShowIfEmpty="There are no open instances you started at this time."
paginationClassName="with-large-bottom-margin" paginationClassName="with-large-bottom-margin"
showActionsColumn
autoReload={false} autoReload={false}
/> />
<h2>With tasks I can complete</h2> <h2>With tasks I can complete</h2>
@ -69,6 +72,8 @@ export default function InProgressInstances() {
showReports={false} showReports={false}
textToShowIfEmpty="You have no completed instances at this time." textToShowIfEmpty="You have no completed instances at this time."
paginationClassName="with-large-bottom-margin" paginationClassName="with-large-bottom-margin"
canCompleteAllTasks
showActionsColumn
autoReload={false} autoReload={false}
/> />
{groupTableComponents()} {groupTableComponents()}