Merge pull request #43 from sartography/send_filters

Send filters used in process_instance_list to the front end
This commit is contained in:
Dan Funk 2022-11-16 17:11:20 -05:00 committed by GitHub
commit 1ec6a1922a
5 changed files with 173 additions and 10 deletions

View File

@ -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

View File

@ -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,

View File

@ -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."""

View File

@ -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."""

View File

@ -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);