Hello,
We have an enumeration field from the document model representing the process status of our workflow. This field is used and displayed in some places including the overview.
But in one particular case, for one particular value, we overwrite the display in the overview.
So there can be multiple “Contract draft” statuses but some of them can be overwritten to “Not yet assigned”.
In the preset filters, we don’t have “Not yet assigned” as it doesn’t exist in the enumeration field. But this is a requirement.
We’d like to add this filter in the preset and when selected, it looks for all ContractDraft documents without any Task Assignee.
But we don’t want to change the whole workflow of our project just for an overwritten value (we don’t use it anywhere else).
So I created a middleware to list myself the documents with custom filters.
import { Middleware } from "redux";
import { Activity, ActivityActions, ActivitySelectors } from "@com.mgmtp.a12.client/client-core/lib/core/activity";
import { OverviewEngineActions } from "@com.mgmtp.a12.client/client-core/lib/core/view";
import { LoggerFactory } from "@com.mgmtp.a12.utils/utils-logging";
import { StoreFactories } from "@com.mgmtp.a12.client/client-core/lib/core/store";
import { OverviewEngineApi } from "@com.mgmtp.a12.overviewengine/overviewengine-core/lib/main/view/api";
import { Model, ModelSelectors } from "@com.mgmtp.a12.client/client-core/lib/core/model";
import { CandidateConstants } from "../../constants";
import { CandidateModelPath } from "../../path";
import { TASK_OVERVIEW_VIEW_KEY } from "../../../../common/constants/workflowsConstants";
import { listCandidateDocuments } from "../../../../rest/candidate/candidate";
import { LocalFieldBasedFiltering } from "../../../../utils";
import { ProcessStatus } from "../types";
import FilterMap = OverviewEngineApi.FilterMap;
import SetDataPayload = ActivityActions.SetDataPayload;
const logger = LoggerFactory.getLogger("[middlewares/candidate/queryParametersChangedMiddleware]");
export const queryParametersChangedMiddleware: Middleware = StoreFactories.createMiddleware((api, next, action) => {
if (OverviewEngineActions.queryParametersChanged.match(action)) {
const activityId = action.payload.activityId;
const activity = ActivitySelectors.activityById(activityId)(api.getState());
const { fieldBasedFilters } = action.payload;
if (!activity || !isCandidateOverviewActivity(activity) || !fieldBasedFilters) {
return next(action);
}
if (!isNotYetAssignedStatusSelected(fieldBasedFilters)) {
return next(action);
}
const documentModel = ModelSelectors.modelByName(CandidateConstants.CANDIDATE_DM, Model.isDocumentModel)(api.getState())
if (!documentModel) {
return next(action);
}
const statusFilters: OverviewEngineApi.FilterMap = getOrUpdateStatusFilterMap(fieldBasedFilters);
const newFieldBasedFilters: FilterMap = {
...fieldBasedFilters,
...statusFilters
}
const filters = LocalFieldBasedFiltering.toStringArray(newFieldBasedFilters, documentModel);
// As NotYetAssigned is selected, we'll select the filter to check that task assignee doesn't exist or is null
filters.push("-" + CandidateModelPath.Candidate.MetaData.Process.Assignees.TaskAssigneeName.toJsonPath() + ":");
listCandidateDocuments(filters).then(docs => {
const payload: SetDataPayload = {
activityId: activityId,
data: {
documents: docs,
totalDocumentsCount: docs.length
}
}
return next(ActivityActions.setData(payload))
}).catch(
error => {
logger.error("Error while loading documents", error);
}
);
}
return next(action);
});
const isCandidateOverviewActivity = (activity: Activity): boolean => {
const { descriptor } = activity;
return (
descriptor.module === CandidateConstants.CANDIDATE_MODULE &&
descriptor.view === TASK_OVERVIEW_VIEW_KEY
);
};
const isNotYetAssignedStatusSelected = (fieldBasedFilters: OverviewEngineApi.FilterMap): boolean => {
const statusFilterOptions = fieldBasedFilters[CandidateModelPath.Candidate.MetaData.Process.Status.toJsonPath()];
if (statusFilterOptions?.filterType !== "Enumeration") {
return false;
}
const criteria = statusFilterOptions.criteria as { readonly selectedValues: string[] };
return criteria.selectedValues.includes(ProcessStatus.NOT_YET_ASSIGNED);
};
const getOrUpdateStatusFilterMap = (fieldBasedFilters: OverviewEngineApi.FilterMap): OverviewEngineApi.FilterMap => {
const statusFilterOptions = fieldBasedFilters[
CandidateModelPath.Candidate.MetaData.Process.Status.toJsonPath()
] as OverviewEngineApi.Filter.EnumerationOptions;
const newSelectedValues = statusFilterOptions.criteria
? [...statusFilterOptions.criteria.selectedValues, ProcessStatus.CONTRACT_DRAFT]
: [ProcessStatus.CONTRACT_DRAFT];
const index = newSelectedValues.indexOf(ProcessStatus.NOT_YET_ASSIGNED);
if (index !== -1) {
newSelectedValues.splice(index, 1);
}
const newOptions: OverviewEngineApi.Filter.EnumerationOptions = {
filterType: statusFilterOptions.filterType,
criteria: {
selectedValues: newSelectedValues
}
};
return {
[CandidateModelPath.Candidate.MetaData.Process.Status.toJsonPath()]: newOptions
};
};
The documents are well returned by the rpc, but just after there is a TaskOverviewDataProvider operation that list documents with the preset filters, i.e in our case, the “Not yet assigned” which is never persisted.
[
{
"jsonrpc": "2.0",
"id": "TaskOverviewDataProvider-4",
"method": "LIST_DOCUMENTS",
"params": {
"documentModelName": "CandidateDMProcess",
"filter": {
"filters": [
"Candidate.MetaData.Process.Status:NotYetAssigned",
"a12wf.workflowsInternalDocumentStatus:(EMPTY OR NON_EMPTY)"
],
"fulltext": "",
"lang": ""
},
"page": {
"offset": 0,
"limit": 10
},
"sort": [],
"facets": []
}
}
]
How can we avoid this ?
Would you come up with a better solution ?
Thanks for reading.
