filtering by metadata works w/ burnettk
This commit is contained in:
parent
a4edb5d766
commit
ae2bc38588
|
@ -785,7 +785,6 @@ def process_instance_list(
|
|||
report_id: Optional[int] = None,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_list."""
|
||||
|
||||
process_instance_report = ProcessInstanceReportService.report_with_identifier(
|
||||
g.user, report_id, report_identifier
|
||||
)
|
||||
|
@ -942,12 +941,18 @@ def process_instance_list(
|
|||
if column["accessor"] in stock_columns:
|
||||
continue
|
||||
instance_metadata_alias = aliased(ProcessInstanceMetadataModel)
|
||||
process_instance_query = process_instance_query.outerjoin(
|
||||
|
||||
filter_for_column = next((f for f in process_instance_report.report_metadata['filter_by'] if f['field_name'] == column['accessor']), None)
|
||||
isouter = True
|
||||
conditions = [ProcessInstanceModel.id == instance_metadata_alias.process_instance_id,
|
||||
instance_metadata_alias.key == column["accessor"]]
|
||||
if filter_for_column:
|
||||
isouter = False
|
||||
conditions.append(instance_metadata_alias.value == filter_for_column["field_value"])
|
||||
process_instance_query = process_instance_query.join(
|
||||
instance_metadata_alias,
|
||||
and_(
|
||||
ProcessInstanceModel.id == instance_metadata_alias.process_instance_id,
|
||||
instance_metadata_alias.key == column["accessor"],
|
||||
),
|
||||
and_(*conditions),
|
||||
isouter=isouter
|
||||
).add_columns(func.max(instance_metadata_alias.value).label(column["accessor"]))
|
||||
|
||||
process_instances = (
|
||||
|
|
|
@ -29,8 +29,6 @@ class ProcessInstanceReportFilter:
|
|||
"""To_dict."""
|
||||
d = {}
|
||||
|
||||
print(f"dir(self): {dir(self)}")
|
||||
|
||||
if self.process_model_identifier is not None:
|
||||
d["process_model_identifier"] = self.process_model_identifier
|
||||
if self.start_from is not None:
|
||||
|
@ -86,7 +84,7 @@ class ProcessInstanceReportService:
|
|||
|
||||
# TODO replace with system reports that are loaded on launch (or similar)
|
||||
temp_system_metadata_map = {
|
||||
"default": {"columns": cls.builtin_column_options()},
|
||||
"default": {"columns": cls.builtin_column_options(), "filter_by": [], 'order_by': ['-start_in_seconds', '-id']},
|
||||
"system_report_instances_initiated_by_me": {
|
||||
"columns": [
|
||||
{"Header": "id", "accessor": "id"},
|
||||
|
@ -98,13 +96,13 @@ class ProcessInstanceReportService:
|
|||
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
|
||||
{"Header": "status", "accessor": "status"},
|
||||
],
|
||||
"filter_by": [{"field_name": "initiated_by_me", "field_value": True}],
|
||||
"filter_by": [{"field_name": "initiated_by_me", "field_value": True}],'order_by': ['-start_in_seconds', '-id']
|
||||
},
|
||||
"system_report_instances_with_tasks_completed_by_me": {
|
||||
"columns": cls.builtin_column_options(),
|
||||
"filter_by": [
|
||||
{"field_name": "with_tasks_completed_by_me", "field_value": True}
|
||||
],
|
||||
],'order_by': ['-start_in_seconds', '-id']
|
||||
},
|
||||
"system_report_instances_with_tasks_completed_by_my_groups": {
|
||||
"columns": cls.builtin_column_options(),
|
||||
|
@ -113,16 +111,15 @@ class ProcessInstanceReportService:
|
|||
"field_name": "with_tasks_completed_by_my_group",
|
||||
"field_value": True,
|
||||
}
|
||||
],
|
||||
],'order_by': ['-start_in_seconds', '-id']
|
||||
},
|
||||
}
|
||||
|
||||
process_instance_report = ProcessInstanceReportModel(
|
||||
identifier=report_identifier,
|
||||
created_by_id=user.id,
|
||||
report_metadata=temp_system_metadata_map[report_identifier], # type: ignore
|
||||
report_metadata=temp_system_metadata_map[report_identifier],
|
||||
)
|
||||
# db.session.add(pro
|
||||
|
||||
return process_instance_report # type: ignore
|
||||
|
||||
|
|
|
@ -6,12 +6,18 @@ import {
|
|||
Stack,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { ProcessInstanceReport, ProcessModel } from '../interfaces';
|
||||
import {
|
||||
ReportFilter,
|
||||
ProcessInstanceReport,
|
||||
ProcessModel,
|
||||
ReportColumn,
|
||||
ReportMetadata,
|
||||
} from '../interfaces';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
type OwnProps = {
|
||||
onSuccess: (..._args: any[]) => any;
|
||||
columnArray: { Header: string; accessor: string };
|
||||
columnArray: ReportColumn[];
|
||||
orderBy: string;
|
||||
processModelSelection: ProcessModel | null;
|
||||
processStatusSelection: string[];
|
||||
|
@ -22,6 +28,7 @@ type OwnProps = {
|
|||
buttonText?: string;
|
||||
buttonClassName?: string;
|
||||
processInstanceReportSelection?: ProcessInstanceReport | null;
|
||||
reportMetadata: ReportMetadata;
|
||||
};
|
||||
|
||||
export default function ProcessInstanceListSaveAsReport({
|
||||
|
@ -37,6 +44,7 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
endToSeconds,
|
||||
buttonText = 'Save as Perspective',
|
||||
buttonClassName,
|
||||
reportMetadata,
|
||||
}: OwnProps) {
|
||||
const [identifier, setIdentifier] = useState<string>(
|
||||
processInstanceReportSelection?.identifier || ''
|
||||
|
@ -59,7 +67,11 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
const addProcessInstanceReport = (event: any) => {
|
||||
event.preventDefault();
|
||||
|
||||
const orderByArray = orderBy.split(',').filter((n) => n);
|
||||
// TODO: make a field to set this
|
||||
let orderByArray = ['-start_in_seconds', '-id'];
|
||||
if (orderBy) {
|
||||
orderByArray = orderBy.split(',').filter((n) => n);
|
||||
}
|
||||
const filterByArray: any = [];
|
||||
|
||||
if (processModelSelection) {
|
||||
|
@ -72,7 +84,8 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
if (processStatusSelection.length > 0) {
|
||||
filterByArray.push({
|
||||
field_name: 'process_status',
|
||||
field_value: processStatusSelection[0], // TODO: support more than one status
|
||||
field_value: processStatusSelection.join(','),
|
||||
operator: 'in',
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -104,6 +117,17 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
});
|
||||
}
|
||||
|
||||
reportMetadata.filter_by.forEach((reportFilter: ReportFilter) => {
|
||||
columnArray.forEach((reportColumn: ReportColumn) => {
|
||||
if (
|
||||
reportColumn.accessor === reportFilter.field_name &&
|
||||
reportColumn.filterable
|
||||
) {
|
||||
filterByArray.push(reportFilter);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let path = `/process-instances/reports`;
|
||||
let httpMethod = 'POST';
|
||||
if (isEditMode() && processInstanceReportSelection) {
|
||||
|
|
|
@ -57,6 +57,9 @@ import {
|
|||
ProcessInstanceReport,
|
||||
ProcessInstance,
|
||||
ReportColumn,
|
||||
ReportColumnForEditing,
|
||||
ReportMetadata,
|
||||
ReportFilter,
|
||||
} from '../interfaces';
|
||||
import ProcessModelSearch from './ProcessModelSearch';
|
||||
import ProcessInstanceReportSearch from './ProcessInstanceReportSearch';
|
||||
|
@ -98,7 +101,7 @@ export default function ProcessInstanceListTable({
|
|||
const navigate = useNavigate();
|
||||
|
||||
const [processInstances, setProcessInstances] = useState([]);
|
||||
const [reportMetadata, setReportMetadata] = useState({});
|
||||
const [reportMetadata, setReportMetadata] = useState<ReportMetadata | null>();
|
||||
const [pagination, setPagination] = useState<PaginationObject | null>(null);
|
||||
const [processInstanceFilters, setProcessInstanceFilters] = useState({});
|
||||
|
||||
|
@ -143,7 +146,7 @@ export default function ProcessInstanceListTable({
|
|||
const [showReportColumnForm, setShowReportColumnForm] =
|
||||
useState<boolean>(false);
|
||||
const [reportColumnToOperateOn, setReportColumnToOperateOn] =
|
||||
useState<ReportColumn | null>(null);
|
||||
useState<ReportColumnForEditing | null>(null);
|
||||
const [reportColumnFormMode, setReportColumnFormMode] = useState<string>('');
|
||||
|
||||
const dateParametersToAlwaysFilterBy: dateParameters = useMemo(() => {
|
||||
|
@ -630,17 +633,19 @@ export default function ProcessInstanceListTable({
|
|||
endToSeconds,
|
||||
} = calculateStartAndEndSeconds();
|
||||
|
||||
if (!valid) {
|
||||
if (!valid || !reportMetadata) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ProcessInstanceListSaveAsReport
|
||||
onSuccess={onSaveReportSuccess}
|
||||
buttonClassName="narrow-button"
|
||||
columnArray={reportColumns()}
|
||||
orderBy=""
|
||||
buttonText="Save As New Perspective"
|
||||
buttonText="Save New Perspective"
|
||||
processModelSelection={processModelSelection}
|
||||
processStatusSelection={processStatusSelection}
|
||||
reportMetadata={reportMetadata}
|
||||
startFromSeconds={startFromSeconds}
|
||||
startToSeconds={startToSeconds}
|
||||
endFromSeconds={endFromSeconds}
|
||||
|
@ -650,12 +655,14 @@ export default function ProcessInstanceListTable({
|
|||
};
|
||||
|
||||
const removeColumn = (reportColumn: ReportColumn) => {
|
||||
const reportMetadataCopy = { ...reportMetadata };
|
||||
const newColumns = reportColumns().filter(
|
||||
(rc: ReportColumn) => rc.accessor !== reportColumn.accessor
|
||||
);
|
||||
Object.assign(reportMetadataCopy, { columns: newColumns });
|
||||
setReportMetadata(reportMetadataCopy);
|
||||
if (reportMetadata) {
|
||||
const reportMetadataCopy = { ...reportMetadata };
|
||||
const newColumns = reportColumns().filter(
|
||||
(rc: ReportColumn) => rc.accessor !== reportColumn.accessor
|
||||
);
|
||||
Object.assign(reportMetadataCopy, { columns: newColumns });
|
||||
setReportMetadata(reportMetadataCopy);
|
||||
}
|
||||
};
|
||||
|
||||
const handleColumnFormClose = () => {
|
||||
|
@ -664,8 +671,49 @@ export default function ProcessInstanceListTable({
|
|||
setReportColumnToOperateOn(null);
|
||||
};
|
||||
|
||||
const handleUpdateColumn = () => {
|
||||
if (reportColumnToOperateOn) {
|
||||
const getFilterByFromReportMetadata = (reportColumnAccessor: string) => {
|
||||
if (reportMetadata) {
|
||||
return reportMetadata.filter_by.find((reportFilter: ReportFilter) => {
|
||||
return reportColumnAccessor === reportFilter.field_name;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const getNewFiltersFromReportForEditing = (
|
||||
reportColumnForEditing: ReportColumnForEditing
|
||||
) => {
|
||||
if (!reportMetadata) {
|
||||
return null;
|
||||
}
|
||||
const reportMetadataCopy = { ...reportMetadata };
|
||||
let newReportFilters = reportMetadataCopy.filter_by;
|
||||
if (reportColumnForEditing.filterable) {
|
||||
const newReportFilter: ReportFilter = {
|
||||
field_name: reportColumnForEditing.accessor,
|
||||
field_value: reportColumnForEditing.filter_field_value,
|
||||
operator: reportColumnForEditing.filter_operator || 'equals',
|
||||
};
|
||||
const existingReportFilter = getFilterByFromReportMetadata(
|
||||
reportColumnForEditing.accessor
|
||||
);
|
||||
if (existingReportFilter) {
|
||||
const existingReportFilterIndex =
|
||||
reportMetadataCopy.filter_by.indexOf(existingReportFilter);
|
||||
if (reportColumnForEditing.filter_field_value) {
|
||||
newReportFilters[existingReportFilterIndex] = newReportFilter;
|
||||
} else {
|
||||
newReportFilters.splice(existingReportFilterIndex, 1);
|
||||
}
|
||||
} else {
|
||||
newReportFilters = newReportFilters.concat([newReportFilter]);
|
||||
}
|
||||
}
|
||||
return newReportFilters;
|
||||
};
|
||||
|
||||
const handleUpdateReportColumn = () => {
|
||||
if (reportColumnToOperateOn && reportMetadata) {
|
||||
const reportMetadataCopy = { ...reportMetadata };
|
||||
let newReportColumns = null;
|
||||
if (reportColumnFormMode === 'new') {
|
||||
|
@ -680,6 +728,7 @@ export default function ProcessInstanceListTable({
|
|||
}
|
||||
Object.assign(reportMetadataCopy, {
|
||||
columns: newReportColumns,
|
||||
filter_by: getNewFiltersFromReportForEditing(reportColumnToOperateOn),
|
||||
});
|
||||
setReportMetadata(reportMetadataCopy);
|
||||
setReportColumnToOperateOn(null);
|
||||
|
@ -688,8 +737,27 @@ export default function ProcessInstanceListTable({
|
|||
}
|
||||
};
|
||||
|
||||
const reportColumnToReportColumnForEditing = (reportColumn: ReportColumn) => {
|
||||
const reportColumnForEditing: ReportColumnForEditing = Object.assign(
|
||||
reportColumn,
|
||||
{ filter_field_value: '', filter_operator: '' }
|
||||
);
|
||||
const reportFilter = getFilterByFromReportMetadata(
|
||||
reportColumnForEditing.accessor
|
||||
);
|
||||
if (reportFilter) {
|
||||
reportColumnForEditing.filter_field_value = reportFilter.field_value;
|
||||
reportColumnForEditing.filter_operator =
|
||||
reportFilter.operator || 'equals';
|
||||
}
|
||||
return reportColumnForEditing;
|
||||
};
|
||||
|
||||
const updateReportColumn = (event: any) => {
|
||||
setReportColumnToOperateOn(event.selectedItem);
|
||||
const reportColumnForEditing = reportColumnToReportColumnForEditing(
|
||||
event.selectedItem
|
||||
);
|
||||
setReportColumnToOperateOn(reportColumnForEditing);
|
||||
};
|
||||
|
||||
// options includes item and inputValue
|
||||
|
@ -709,7 +777,7 @@ export default function ProcessInstanceListTable({
|
|||
const reportColumnToOperateOnCopy = {
|
||||
...reportColumnToOperateOn,
|
||||
};
|
||||
reportColumnToOperateOnCopy.condition_value = event.target.value;
|
||||
reportColumnToOperateOnCopy.filter_field_value = event.target.value;
|
||||
setReportColumnToOperateOn(reportColumnToOperateOnCopy);
|
||||
}
|
||||
};
|
||||
|
@ -737,7 +805,6 @@ export default function ProcessInstanceListTable({
|
|||
/>,
|
||||
];
|
||||
if (reportColumnToOperateOn && reportColumnToOperateOn.filterable) {
|
||||
console.log('reportColumnToOperateOn', reportColumnToOperateOn);
|
||||
formElements.push(
|
||||
<TextInput
|
||||
id="report-column-condition-value"
|
||||
|
@ -745,7 +812,7 @@ export default function ProcessInstanceListTable({
|
|||
labelText="Condition Value"
|
||||
value={
|
||||
reportColumnToOperateOn
|
||||
? reportColumnToOperateOn.condition_value
|
||||
? reportColumnToOperateOn.filter_field_value
|
||||
: ''
|
||||
}
|
||||
onChange={setReportColumnConditionValue}
|
||||
|
@ -785,7 +852,7 @@ export default function ProcessInstanceListTable({
|
|||
modalHeading={modalHeading}
|
||||
primaryButtonText="Save"
|
||||
primaryButtonDisabled={!reportColumnToOperateOn}
|
||||
onRequestSubmit={handleUpdateColumn}
|
||||
onRequestSubmit={handleUpdateReportColumn}
|
||||
onRequestClose={handleColumnFormClose}
|
||||
hasScrollingContent
|
||||
>
|
||||
|
@ -799,13 +866,16 @@ export default function ProcessInstanceListTable({
|
|||
const tags: any = [];
|
||||
|
||||
(reportColumns() as any).forEach((reportColumn: ReportColumn) => {
|
||||
const reportColumnForEditing =
|
||||
reportColumnToReportColumnForEditing(reportColumn);
|
||||
|
||||
let tagType = 'cool-gray';
|
||||
if (reportColumn.filterable) {
|
||||
if (reportColumnForEditing.filterable) {
|
||||
tagType = 'green';
|
||||
}
|
||||
let reportColumnLabel = reportColumn.Header;
|
||||
if (reportColumn.condition_value) {
|
||||
reportColumnLabel = `${reportColumnLabel}=${reportColumn.condition_value}`;
|
||||
let reportColumnLabel = reportColumnForEditing.Header;
|
||||
if (reportColumnForEditing.filter_field_value) {
|
||||
reportColumnLabel = `${reportColumnLabel}=${reportColumnForEditing.filter_field_value}`;
|
||||
}
|
||||
tags.push(
|
||||
<Tag type={tagType} size="sm">
|
||||
|
@ -813,9 +883,9 @@ export default function ProcessInstanceListTable({
|
|||
kind="ghost"
|
||||
size="sm"
|
||||
className="button-tag-icon"
|
||||
title={`Edit ${reportColumn.accessor}`}
|
||||
title={`Edit ${reportColumnForEditing.accessor}`}
|
||||
onClick={() => {
|
||||
setReportColumnToOperateOn(reportColumn);
|
||||
setReportColumnToOperateOn(reportColumnForEditing);
|
||||
setShowReportColumnForm(true);
|
||||
setReportColumnFormMode('edit');
|
||||
}}
|
||||
|
@ -830,7 +900,7 @@ export default function ProcessInstanceListTable({
|
|||
hasIconOnly
|
||||
size="sm"
|
||||
kind="ghost"
|
||||
onClick={() => removeColumn(reportColumn)}
|
||||
onClick={() => removeColumn(reportColumnForEditing)}
|
||||
/>
|
||||
</Tag>
|
||||
);
|
||||
|
@ -933,11 +1003,14 @@ export default function ProcessInstanceListTable({
|
|||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={4}>
|
||||
<Column sm={4} md={4} lg={8}>
|
||||
{saveAsReportComponent()}
|
||||
</Column>
|
||||
<Column sm={4} md={4} lg={8}>
|
||||
<ButtonSet>
|
||||
<Button
|
||||
kind=""
|
||||
className="button-white-background"
|
||||
className="button-white-background narrow-button"
|
||||
onClick={clearFilters}
|
||||
>
|
||||
Clear
|
||||
|
@ -946,17 +1019,13 @@ export default function ProcessInstanceListTable({
|
|||
kind="secondary"
|
||||
onClick={applyFilter}
|
||||
data-qa="filter-button"
|
||||
className="narrow-button"
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</ButtonSet>
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={7} lg={13} sm={3}>
|
||||
{saveAsReportComponent()}
|
||||
</Column>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1079,7 +1148,11 @@ export default function ProcessInstanceListTable({
|
|||
/>
|
||||
</Column>,
|
||||
];
|
||||
if (processInstanceReportSelection && showFilterOptions) {
|
||||
if (
|
||||
processInstanceReportSelection &&
|
||||
showFilterOptions &&
|
||||
reportMetadata
|
||||
) {
|
||||
columns.push(
|
||||
<Column sm={2} md={4} lg={2}>
|
||||
<ProcessInstanceListSaveAsReport
|
||||
|
@ -1090,6 +1163,7 @@ export default function ProcessInstanceListTable({
|
|||
buttonText="Save"
|
||||
processModelSelection={processModelSelection}
|
||||
processStatusSelection={processStatusSelection}
|
||||
reportMetadata={reportMetadata}
|
||||
startFromSeconds={startFromSeconds}
|
||||
startToSeconds={startToSeconds}
|
||||
endFromSeconds={endFromSeconds}
|
||||
|
|
|
@ -41,7 +41,7 @@ export default function ProcessInstanceReportSearch({
|
|||
const reportSelectionString = (
|
||||
processInstanceReport: ProcessInstanceReport
|
||||
) => {
|
||||
return `${truncateString(processInstanceReport.identifier, 20)} (${
|
||||
return `${truncateString(processInstanceReport.identifier, 20)} (Id: ${
|
||||
processInstanceReport.id
|
||||
})`;
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ export const PROCESS_STATUSES = [
|
|||
'complete',
|
||||
'error',
|
||||
'suspended',
|
||||
'terminated',
|
||||
];
|
||||
|
||||
// with time: yyyy-MM-dd HH:mm:ss
|
||||
|
|
|
@ -346,3 +346,10 @@ td.actions-cell {
|
|||
.combo-box-in-modal {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.cds--btn.narrow-button {
|
||||
max-width: 10rem;
|
||||
min-width: 5rem;
|
||||
word-break: normal;
|
||||
|
||||
}
|
||||
|
|
|
@ -63,15 +63,27 @@ export interface MessageInstance {
|
|||
message_correlations?: MessageCorrelations;
|
||||
}
|
||||
|
||||
export interface ReportFilter {
|
||||
field_name: string;
|
||||
field_value: string;
|
||||
operator?: string;
|
||||
}
|
||||
|
||||
export interface ReportColumn {
|
||||
Header: string;
|
||||
accessor: string;
|
||||
filterable: boolean;
|
||||
condition_value?: string;
|
||||
}
|
||||
|
||||
export interface ReportColumnForEditing extends ReportColumn {
|
||||
filter_field_value: string;
|
||||
filter_operator: string;
|
||||
}
|
||||
|
||||
export interface ReportMetadata {
|
||||
columns: ReportColumn[];
|
||||
filter_by: ReportFilter[];
|
||||
order_by: string[];
|
||||
}
|
||||
|
||||
export interface ProcessInstanceReport {
|
||||
|
|
Loading…
Reference in New Issue