Merge pull request #43 from sartography/send_filters
Send filters used in process_instance_list to the front end
This commit is contained in:
commit
1ec6a1922a
|
@ -439,6 +439,12 @@ paths:
|
|||
description: For filtering - not_started, user_input_required, waiting, complete, error, or suspended
|
||||
schema:
|
||||
type: string
|
||||
- name: user_filter
|
||||
in: query
|
||||
required: false
|
||||
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
|
||||
|
|
|
@ -72,6 +72,9 @@ from spiffworkflow_backend.services.message_service import MessageService
|
|||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_instance_report_service import (
|
||||
ProcessInstanceReportFilter,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_instance_report_service import (
|
||||
ProcessInstanceReportService,
|
||||
)
|
||||
|
@ -732,18 +735,32 @@ def process_instance_list(
|
|||
end_from: Optional[int] = None,
|
||||
end_to: Optional[int] = None,
|
||||
process_status: Optional[str] = None,
|
||||
user_filter: Optional[bool] = False,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_list."""
|
||||
process_instance_report = ProcessInstanceReportModel.default_report(g.user)
|
||||
report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
|
||||
process_instance_report,
|
||||
process_model_identifier,
|
||||
start_from,
|
||||
start_to,
|
||||
end_from,
|
||||
end_to,
|
||||
process_status,
|
||||
)
|
||||
|
||||
if user_filter:
|
||||
report_filter = ProcessInstanceReportFilter(
|
||||
process_model_identifier,
|
||||
start_from,
|
||||
start_to,
|
||||
end_from,
|
||||
end_to,
|
||||
process_status.split(",") if process_status else None,
|
||||
)
|
||||
else:
|
||||
report_filter = (
|
||||
ProcessInstanceReportService.filter_from_metadata_with_overrides(
|
||||
process_instance_report,
|
||||
process_model_identifier,
|
||||
start_from,
|
||||
start_to,
|
||||
end_from,
|
||||
end_to,
|
||||
process_status,
|
||||
)
|
||||
)
|
||||
|
||||
# process_model_identifier = un_modify_modified_process_model_id(modified_process_model_identifier)
|
||||
process_instance_query = ProcessInstanceModel.query
|
||||
|
@ -811,6 +828,7 @@ def process_instance_list(
|
|||
response_json = {
|
||||
"report_metadata": report_metadata,
|
||||
"results": results,
|
||||
"filters": report_filter.to_dict(),
|
||||
"pagination": {
|
||||
"count": len(results),
|
||||
"total": process_instances.total,
|
||||
|
|
|
@ -18,6 +18,25 @@ class ProcessInstanceReportFilter:
|
|||
end_to: Optional[int] = None
|
||||
process_status: Optional[list[str]] = None
|
||||
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
"""To_dict."""
|
||||
d = {}
|
||||
|
||||
if self.process_model_identifier is not None:
|
||||
d["process_model_identifier"] = self.process_model_identifier
|
||||
if self.start_from is not None:
|
||||
d["start_from"] = str(self.start_from)
|
||||
if self.start_to is not None:
|
||||
d["start_to"] = str(self.start_to)
|
||||
if self.end_from is not None:
|
||||
d["end_from"] = str(self.end_from)
|
||||
if self.end_to is not None:
|
||||
d["end_to"] = str(self.end_to)
|
||||
if self.process_status is not None:
|
||||
d["process_status"] = ",".join(self.process_status)
|
||||
|
||||
return d
|
||||
|
||||
|
||||
class ProcessInstanceReportService:
|
||||
"""ProcessInstanceReportService."""
|
||||
|
|
|
@ -17,6 +17,80 @@ from spiffworkflow_backend.services.process_instance_report_service import (
|
|||
)
|
||||
|
||||
|
||||
class TestProcessInstanceReportFilter(BaseTest):
|
||||
"""TestProcessInstanceReportFilter."""
|
||||
|
||||
def test_empty_filter_to_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Docstring."""
|
||||
d = ProcessInstanceReportFilter().to_dict()
|
||||
|
||||
assert d == {}
|
||||
|
||||
def test_string_value_filter_to_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Docstring."""
|
||||
d = ProcessInstanceReportFilter(process_model_identifier="bob").to_dict()
|
||||
|
||||
assert d == {"process_model_identifier": "bob"}
|
||||
|
||||
def test_int_value_filter_to_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Docstring."""
|
||||
d = ProcessInstanceReportFilter(
|
||||
start_from=1,
|
||||
start_to=2,
|
||||
end_from=3,
|
||||
end_to=4,
|
||||
).to_dict()
|
||||
|
||||
assert d == {
|
||||
"start_from": "1",
|
||||
"start_to": "2",
|
||||
"end_from": "3",
|
||||
"end_to": "4",
|
||||
}
|
||||
|
||||
def test_list_single_value_filter_to_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Docstring."""
|
||||
d = ProcessInstanceReportFilter(process_status=["bob"]).to_dict()
|
||||
|
||||
assert d == {"process_status": "bob"}
|
||||
|
||||
def test_list_multiple_value_filter_to_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Docstring."""
|
||||
d = ProcessInstanceReportFilter(process_status=["joe", "bob", "sue"]).to_dict()
|
||||
|
||||
assert d == {"process_status": "joe,bob,sue"}
|
||||
|
||||
|
||||
class TestProcessInstanceReportService(BaseTest):
|
||||
"""TestProcessInstanceReportService."""
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ export default function ProcessInstanceListTable({
|
|||
const [processInstances, setProcessInstances] = useState([]);
|
||||
const [reportMetadata, setReportMetadata] = useState({});
|
||||
const [pagination, setPagination] = useState<PaginationObject | null>(null);
|
||||
const [processInstanceFilters, setProcessInstanceFilters] = useState({});
|
||||
|
||||
const oneHourInSeconds = 3600;
|
||||
const oneMonthInSeconds = oneHourInSeconds * 24 * 30;
|
||||
|
@ -108,6 +109,7 @@ export default function ProcessInstanceListTable({
|
|||
setProcessInstances(processInstancesFromApi);
|
||||
setReportMetadata(result.report_metadata);
|
||||
setPagination(result.pagination);
|
||||
setProcessInstanceFilters(result.filters);
|
||||
}
|
||||
function getProcessInstances() {
|
||||
// eslint-disable-next-line prefer-const
|
||||
|
@ -123,6 +125,11 @@ export default function ProcessInstanceListTable({
|
|||
}
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
|
||||
const userAppliedFilter = searchParams.get('user_filter');
|
||||
if (userAppliedFilter) {
|
||||
queryParamString += `&user_filter=${userAppliedFilter}`;
|
||||
}
|
||||
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
|
@ -212,6 +219,45 @@ export default function ProcessInstanceListTable({
|
|||
perPageOptions,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const filters = processInstanceFilters as any;
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
const paramValue = filters[paramName];
|
||||
functionToCall('');
|
||||
if (paramValue) {
|
||||
const dateString = convertSecondsToFormattedDate(paramValue as any);
|
||||
functionToCall(dateString);
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
});
|
||||
|
||||
setProcessModelSelection(null);
|
||||
processModelAvailableItems.forEach((item: any) => {
|
||||
if (item.id === filters.process_model_identifier) {
|
||||
setProcessModelSelection(item);
|
||||
}
|
||||
});
|
||||
|
||||
const processStatusSelectedArray: string[] = [];
|
||||
if (filters.process_status) {
|
||||
PROCESS_STATUSES.forEach((processStatusOption: any) => {
|
||||
const regex = new RegExp(`\\b${processStatusOption}\\b`);
|
||||
if (filters.process_status.match(regex)) {
|
||||
processStatusSelectedArray.push(processStatusOption);
|
||||
}
|
||||
});
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
setProcessStatusSelection(processStatusSelectedArray);
|
||||
}, [
|
||||
processInstanceFilters,
|
||||
parametersToAlwaysFilterBy,
|
||||
parametersToGetFromSearchParams,
|
||||
processModelAvailableItems,
|
||||
]);
|
||||
|
||||
// does the comparison, but also returns false if either argument
|
||||
// is not truthy and therefore not comparable.
|
||||
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
||||
|
@ -237,7 +283,7 @@ export default function ProcessInstanceListTable({
|
|||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
let queryParamString = `per_page=${perPage}&page=${page}&user_filter=true`;
|
||||
|
||||
const startFromSeconds = convertDateStringToSeconds(startFrom);
|
||||
const endFromSeconds = convertDateStringToSeconds(endFrom);
|
||||
|
|
Loading…
Reference in New Issue