Merge branch 'main' of github.com:sartography/spiff-arena
This commit is contained in:
commit
d645a53626
|
@ -514,6 +514,24 @@ paths:
|
|||
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: user_filter
|
||||
in: query
|
||||
required: false
|
||||
|
|
|
@ -30,6 +30,7 @@ from SpiffWorkflow.task import TaskState
|
|||
from sqlalchemy import and_
|
||||
from sqlalchemy import asc
|
||||
from sqlalchemy import desc
|
||||
from sqlalchemy import select
|
||||
|
||||
from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
||||
ProcessEntityNotFoundError,
|
||||
|
@ -63,6 +64,7 @@ from spiffworkflow_backend.models.spec_reference import SpecReferenceSchema
|
|||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
||||
from spiffworkflow_backend.models.spiff_step_details import SpiffStepDetailsModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel
|
||||
from spiffworkflow_backend.routes.user import verify_token
|
||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||
from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService
|
||||
|
@ -762,6 +764,9 @@ def process_instance_list(
|
|||
end_from: Optional[int] = None,
|
||||
end_to: Optional[int] = None,
|
||||
process_status: Optional[str] = None,
|
||||
initiated_by_me: Optional[bool] = None,
|
||||
with_tasks_completed_by_me: Optional[bool] = None,
|
||||
with_tasks_completed_by_my_group: Optional[bool] = None,
|
||||
user_filter: Optional[bool] = False,
|
||||
report_identifier: Optional[str] = None,
|
||||
) -> flask.wrappers.Response:
|
||||
|
@ -778,6 +783,9 @@ def process_instance_list(
|
|||
end_from,
|
||||
end_to,
|
||||
process_status.split(",") if process_status else None,
|
||||
initiated_by_me,
|
||||
with_tasks_completed_by_me,
|
||||
with_tasks_completed_by_my_group,
|
||||
)
|
||||
else:
|
||||
report_filter = (
|
||||
|
@ -789,6 +797,9 @@ def process_instance_list(
|
|||
end_from,
|
||||
end_to,
|
||||
process_status,
|
||||
initiated_by_me,
|
||||
with_tasks_completed_by_me,
|
||||
with_tasks_completed_by_my_group,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -837,9 +848,79 @@ def process_instance_list(
|
|||
ProcessInstanceModel.status.in_(report_filter.process_status) # type: ignore
|
||||
)
|
||||
|
||||
process_instances = process_instance_query.order_by(
|
||||
if report_filter.initiated_by_me is True:
|
||||
process_instance_query = process_instance_query.filter(
|
||||
ProcessInstanceModel.status == "complete"
|
||||
)
|
||||
process_instance_query = process_instance_query.filter_by(
|
||||
process_initiator=g.user
|
||||
)
|
||||
|
||||
# TODO: not sure if this is exactly what is wanted
|
||||
if report_filter.with_tasks_completed_by_me is True:
|
||||
process_instance_query = process_instance_query.filter(
|
||||
ProcessInstanceModel.status == "complete"
|
||||
)
|
||||
process_instance_query = process_instance_query.join(
|
||||
SpiffStepDetailsModel,
|
||||
ProcessInstanceModel.id == SpiffStepDetailsModel.process_instance_id,
|
||||
)
|
||||
process_instance_query = process_instance_query.join(
|
||||
SpiffLoggingModel,
|
||||
ProcessInstanceModel.id == SpiffLoggingModel.process_instance_id,
|
||||
)
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffLoggingModel.message.contains("COMPLETED") # type: ignore
|
||||
)
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffLoggingModel.spiff_step == SpiffStepDetailsModel.spiff_step
|
||||
)
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffStepDetailsModel.completed_by_user_id == g.user.id
|
||||
)
|
||||
|
||||
# TODO: not sure if this is exactly what is wanted
|
||||
if report_filter.with_tasks_completed_by_my_group is True:
|
||||
process_instance_query = process_instance_query.filter(
|
||||
ProcessInstanceModel.status == "complete"
|
||||
)
|
||||
process_instance_query = process_instance_query.join(
|
||||
SpiffStepDetailsModel,
|
||||
ProcessInstanceModel.id == SpiffStepDetailsModel.process_instance_id,
|
||||
)
|
||||
process_instance_query = process_instance_query.join(
|
||||
SpiffLoggingModel,
|
||||
ProcessInstanceModel.id == SpiffLoggingModel.process_instance_id,
|
||||
)
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffLoggingModel.message.contains("COMPLETED") # type: ignore
|
||||
)
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffLoggingModel.spiff_step == SpiffStepDetailsModel.spiff_step
|
||||
)
|
||||
|
||||
my_groups = (
|
||||
select(UserGroupAssignmentModel) # type: ignore
|
||||
.where(UserGroupAssignmentModel.user_id == g.user.id)
|
||||
.with_only_columns(UserGroupAssignmentModel.group_id)
|
||||
)
|
||||
users_in_my_groups = (
|
||||
select(UserGroupAssignmentModel) # type: ignore
|
||||
.where(UserGroupAssignmentModel.group_id.in_(my_groups))
|
||||
.with_only_columns(UserGroupAssignmentModel.user_id)
|
||||
)
|
||||
|
||||
process_instance_query = process_instance_query.filter(
|
||||
SpiffStepDetailsModel.completed_by_user_id.in_(users_in_my_groups) # type: ignore
|
||||
)
|
||||
|
||||
process_instances = (
|
||||
process_instance_query.distinct()
|
||||
.order_by(
|
||||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||
).paginate(page=page, per_page=per_page, error_out=False)
|
||||
)
|
||||
.paginate(page=page, per_page=per_page, error_out=False)
|
||||
)
|
||||
|
||||
results = list(
|
||||
map(
|
||||
|
@ -1005,7 +1086,7 @@ def authentication_callback(
|
|||
f"{service}/{auth_method}", response, g.user.id, create_if_not_exists=True
|
||||
)
|
||||
return redirect(
|
||||
f"{current_app.config['SPIFFWORKFLOW_FRONTEND_URL']}/admin/authentications"
|
||||
f"{current_app.config['SPIFFWORKFLOW_FRONTEND_URL']}/admin/configuration"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ class ProcessInstanceReportFilter:
|
|||
end_from: Optional[int] = None
|
||||
end_to: Optional[int] = None
|
||||
process_status: Optional[list[str]] = None
|
||||
initiated_by_me: Optional[bool] = None
|
||||
with_tasks_completed_by_me: Optional[bool] = None
|
||||
with_tasks_completed_by_my_group: Optional[bool] = None
|
||||
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
"""To_dict."""
|
||||
|
@ -35,6 +38,16 @@ class ProcessInstanceReportFilter:
|
|||
d["end_to"] = str(self.end_to)
|
||||
if self.process_status is not None:
|
||||
d["process_status"] = ",".join(self.process_status)
|
||||
if self.initiated_by_me is not None:
|
||||
d["initiated_by_me"] = str(self.initiated_by_me).lower()
|
||||
if self.with_tasks_completed_by_me is not None:
|
||||
d["with_tasks_completed_by_me"] = str(
|
||||
self.with_tasks_completed_by_me
|
||||
).lower()
|
||||
if self.with_tasks_completed_by_my_group is not None:
|
||||
d["with_tasks_completed_by_my_group"] = str(
|
||||
self.with_tasks_completed_by_my_group
|
||||
).lower()
|
||||
|
||||
return d
|
||||
|
||||
|
@ -73,30 +86,35 @@ class ProcessInstanceReportService:
|
|||
},
|
||||
"system_report_instances_initiated_by_me": {
|
||||
"columns": [
|
||||
{"Header": "id", "accessor": "id"},
|
||||
{
|
||||
"Header": "process_model_identifier",
|
||||
"accessor": "process_model_identifier",
|
||||
},
|
||||
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
|
||||
{"Header": "id", "accessor": "id"},
|
||||
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
|
||||
{"Header": "status", "accessor": "status"},
|
||||
],
|
||||
"filter_by": [{"field_name": "initiated_by_me", "field_value": True}],
|
||||
},
|
||||
"system_report_instances_with_tasks_completed_by_me": {
|
||||
"columns": [
|
||||
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
|
||||
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
|
||||
{"Header": "status", "accessor": "status"},
|
||||
{"Header": "id", "accessor": "id"},
|
||||
{
|
||||
"Header": "process_model_identifier",
|
||||
"accessor": "process_model_identifier",
|
||||
},
|
||||
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
|
||||
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
|
||||
{"Header": "status", "accessor": "status"},
|
||||
],
|
||||
"filter_by": [
|
||||
{"field_name": "with_tasks_completed_by_me", "field_value": True}
|
||||
],
|
||||
},
|
||||
"system_report_instances_with_tasks_completed_by_my_groups": {
|
||||
"columns": [
|
||||
{"Header": "id", "accessor": "id"},
|
||||
{
|
||||
"Header": "process_model_identifier",
|
||||
"accessor": "process_model_identifier",
|
||||
|
@ -104,7 +122,12 @@ class ProcessInstanceReportService:
|
|||
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
|
||||
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
|
||||
{"Header": "status", "accessor": "status"},
|
||||
{"Header": "id", "accessor": "id"},
|
||||
],
|
||||
"filter_by": [
|
||||
{
|
||||
"field_name": "with_tasks_completed_by_my_group",
|
||||
"field_value": True,
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
@ -112,7 +135,7 @@ class ProcessInstanceReportService:
|
|||
process_instance_report = ProcessInstanceReportModel(
|
||||
identifier=report_identifier,
|
||||
created_by_id=user.id,
|
||||
report_metadata=temp_system_metadata_map[report_identifier],
|
||||
report_metadata=temp_system_metadata_map[report_identifier], # type: ignore
|
||||
)
|
||||
|
||||
return process_instance_report # type: ignore
|
||||
|
@ -138,6 +161,10 @@ class ProcessInstanceReportService:
|
|||
"""Filter_from_metadata."""
|
||||
filters = cls.filter_by_to_dict(process_instance_report)
|
||||
|
||||
def bool_value(key: str) -> Optional[bool]:
|
||||
"""Bool_value."""
|
||||
return bool(filters[key]) if key in filters else None
|
||||
|
||||
def int_value(key: str) -> Optional[int]:
|
||||
"""Int_value."""
|
||||
return int(filters[key]) if key in filters else None
|
||||
|
@ -152,6 +179,11 @@ class ProcessInstanceReportService:
|
|||
end_from = int_value("end_from")
|
||||
end_to = int_value("end_to")
|
||||
process_status = list_value("process_status")
|
||||
initiated_by_me = bool_value("initiated_by_me")
|
||||
with_tasks_completed_by_me = bool_value("with_tasks_completed_by_me")
|
||||
with_tasks_completed_by_my_group = bool_value(
|
||||
"with_tasks_completed_by_my_group"
|
||||
)
|
||||
|
||||
report_filter = ProcessInstanceReportFilter(
|
||||
process_model_identifier,
|
||||
|
@ -160,6 +192,9 @@ class ProcessInstanceReportService:
|
|||
end_from,
|
||||
end_to,
|
||||
process_status,
|
||||
initiated_by_me,
|
||||
with_tasks_completed_by_me,
|
||||
with_tasks_completed_by_my_group,
|
||||
)
|
||||
|
||||
return report_filter
|
||||
|
@ -174,6 +209,9 @@ class ProcessInstanceReportService:
|
|||
end_from: Optional[int] = None,
|
||||
end_to: Optional[int] = None,
|
||||
process_status: Optional[str] = None,
|
||||
initiated_by_me: Optional[bool] = None,
|
||||
with_tasks_completed_by_me: Optional[bool] = None,
|
||||
with_tasks_completed_by_my_group: Optional[bool] = None,
|
||||
) -> ProcessInstanceReportFilter:
|
||||
"""Filter_from_metadata_with_overrides."""
|
||||
report_filter = cls.filter_from_metadata(process_instance_report)
|
||||
|
@ -190,5 +228,13 @@ class ProcessInstanceReportService:
|
|||
report_filter.end_to = end_to
|
||||
if process_status is not None:
|
||||
report_filter.process_status = process_status.split(",")
|
||||
if initiated_by_me is not None:
|
||||
report_filter.initiated_by_me = initiated_by_me
|
||||
if with_tasks_completed_by_me is not None:
|
||||
report_filter.with_tasks_completed_by_me = with_tasks_completed_by_me
|
||||
if with_tasks_completed_by_my_group is not None:
|
||||
report_filter.with_tasks_completed_by_my_group = (
|
||||
with_tasks_completed_by_my_group
|
||||
)
|
||||
|
||||
return report_filter
|
||||
|
|
|
@ -8,6 +8,8 @@ export default function MyCompletedInstances() {
|
|||
filtersEnabled={false}
|
||||
paginationQueryParamPrefix={paginationQueryParamPrefix}
|
||||
perPageOptions={[2, 5, 25]}
|
||||
reportIdentifier="system_report_instances_initiated_by_me"
|
||||
showReports={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ type OwnProps = {
|
|||
paginationQueryParamPrefix?: string;
|
||||
perPageOptions?: number[];
|
||||
showReports?: boolean;
|
||||
reportIdentifier?: string;
|
||||
};
|
||||
|
||||
interface dateParameters {
|
||||
|
@ -69,6 +70,7 @@ export default function ProcessInstanceListTable({
|
|||
paginationQueryParamPrefix,
|
||||
perPageOptions,
|
||||
showReports = true,
|
||||
reportIdentifier,
|
||||
}: OwnProps) {
|
||||
const params = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
@ -173,9 +175,14 @@ export default function ProcessInstanceListTable({
|
|||
queryParamString += `&user_filter=${userAppliedFilter}`;
|
||||
}
|
||||
|
||||
const reportIdentifier = searchParams.get('report_identifier');
|
||||
if (reportIdentifier) {
|
||||
queryParamString += `&report_identifier=${reportIdentifier}`;
|
||||
let reportIdentifierToUse: any = reportIdentifier;
|
||||
|
||||
if (!reportIdentifierToUse) {
|
||||
reportIdentifierToUse = searchParams.get('report_identifier');
|
||||
}
|
||||
|
||||
if (reportIdentifierToUse) {
|
||||
queryParamString += `&report_identifier=${reportIdentifierToUse}`;
|
||||
}
|
||||
|
||||
Object.keys(dateParametersToAlwaysFilterBy).forEach(
|
||||
|
@ -273,6 +280,7 @@ export default function ProcessInstanceListTable({
|
|||
paginationQueryParamPrefix,
|
||||
processModelFullIdentifier,
|
||||
perPageOptions,
|
||||
reportIdentifier,
|
||||
]);
|
||||
|
||||
// This sets the filter data using the saved reports returned from the initial instance_list query.
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
import MyCompletedInstances from '../components/MyCompletedInstances';
|
||||
import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
|
||||
|
||||
export default function CompletedInstances() {
|
||||
return <MyCompletedInstances />;
|
||||
return (
|
||||
<>
|
||||
<h1>Initiated By Me</h1>
|
||||
<ProcessInstanceListTable
|
||||
filtersEnabled={false}
|
||||
paginationQueryParamPrefix="my_completed_instances"
|
||||
perPageOptions={[2, 5, 25]}
|
||||
reportIdentifier="system_report_instances_initiated_by_me"
|
||||
showReports={false}
|
||||
/>
|
||||
<h1 style={{ marginTop: '1em' }}>With Tasks Completed By Me</h1>
|
||||
<ProcessInstanceListTable
|
||||
filtersEnabled={false}
|
||||
paginationQueryParamPrefix="my_completed_tasks"
|
||||
perPageOptions={[2, 5, 25]}
|
||||
reportIdentifier="system_report_instances_with_tasks_completed_by_me"
|
||||
showReports={false}
|
||||
/>
|
||||
<h1 style={{ marginTop: '1em' }}>With Tasks Completed By My Group</h1>
|
||||
<ProcessInstanceListTable
|
||||
filtersEnabled={false}
|
||||
paginationQueryParamPrefix="group_completed_tasks"
|
||||
perPageOptions={[2, 5, 25]}
|
||||
reportIdentifier="system_report_instances_with_tasks_completed_by_my_groups"
|
||||
showReports={false}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue