added ability to update the display name for perspective columns w/ burnettk
This commit is contained in:
parent
98c775db8e
commit
3bf23f6624
|
@ -816,7 +816,6 @@ def process_instance_list(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# process_model_identifier = un_modify_modified_process_model_id(modified_process_model_identifier)
|
|
||||||
process_instance_query = ProcessInstanceModel.query
|
process_instance_query = ProcessInstanceModel.query
|
||||||
# Always join that hot user table for good performance at serialization time.
|
# Always join that hot user table for good performance at serialization time.
|
||||||
process_instance_query = process_instance_query.options(
|
process_instance_query = process_instance_query.options(
|
||||||
|
@ -983,9 +982,8 @@ def process_instance_report_column_list() -> flask.wrappers.Response:
|
||||||
table_columns = ProcessInstanceReportService.builtin_column_options()
|
table_columns = ProcessInstanceReportService.builtin_column_options()
|
||||||
columns_for_metadata = db.session.query(ProcessInstanceMetadataModel.key).distinct().all() # type: ignore
|
columns_for_metadata = db.session.query(ProcessInstanceMetadataModel.key).distinct().all() # type: ignore
|
||||||
columns_for_metadata_strings = [
|
columns_for_metadata_strings = [
|
||||||
{"Header": i[0], "accessor": i[0]} for i in columns_for_metadata
|
{"Header": i[0], "accessor": i[0], "filterable": True} for i in columns_for_metadata
|
||||||
]
|
]
|
||||||
# columns = sorted(table_columns + columns_for_metadata_strings)
|
|
||||||
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
|
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1139,7 +1137,6 @@ def process_instance_report_show(
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
per_page: int = 100,
|
per_page: int = 100,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_list."""
|
|
||||||
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
|
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
|
||||||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||||
).paginate(
|
).paginate(
|
||||||
|
|
|
@ -243,13 +243,13 @@ class ProcessInstanceReportService:
|
||||||
def builtin_column_options(cls) -> list[dict]:
|
def builtin_column_options(cls) -> list[dict]:
|
||||||
"""Builtin_column_options."""
|
"""Builtin_column_options."""
|
||||||
return [
|
return [
|
||||||
{"Header": "Id", "accessor": "id"},
|
{"Header": "Id", "accessor": "id", "filterable": False},
|
||||||
{
|
{
|
||||||
"Header": "Process",
|
"Header": "Process",
|
||||||
"accessor": "process_model_display_name",
|
"accessor": "process_model_display_name", "filterable": False,
|
||||||
},
|
},
|
||||||
{"Header": "Start", "accessor": "start_in_seconds"},
|
{"Header": "Start", "accessor": "start_in_seconds", "filterable": False},
|
||||||
{"Header": "End", "accessor": "end_in_seconds"},
|
{"Header": "End", "accessor": "end_in_seconds", "filterable": False},
|
||||||
{"Header": "Username", "accessor": "username"},
|
{"Header": "Username", "accessor": "username", "filterable": False},
|
||||||
{"Header": "Status", "accessor": "status"},
|
{"Header": "Status", "accessor": "status", "filterable": False},
|
||||||
]
|
]
|
||||||
|
|
|
@ -50,7 +50,6 @@ export default function ProcessInstanceListSaveAsReport({
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const orderByArray = orderBy.split(',').filter((n) => n);
|
const orderByArray = orderBy.split(',').filter((n) => n);
|
||||||
|
|
||||||
const filterByArray: any = [];
|
const filterByArray: any = [];
|
||||||
|
|
||||||
if (processModelSelection) {
|
if (processModelSelection) {
|
||||||
|
@ -122,7 +121,7 @@ export default function ProcessInstanceListSaveAsReport({
|
||||||
value={identifier}
|
value={identifier}
|
||||||
onChange={(e: any) => setIdentifier(e.target.value)}
|
onChange={(e: any) => setIdentifier(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Button disabled={!hasIdentifier()} size="sm">
|
<Button disabled={!hasIdentifier()} size="sm" type="submit">
|
||||||
{buttonText}
|
{buttonText}
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { Filter, Close } from '@carbon/icons-react';
|
import { Filter, Close, AddAlt, AddFilled } from '@carbon/icons-react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonSet,
|
ButtonSet,
|
||||||
|
@ -22,6 +22,11 @@ import {
|
||||||
TableRow,
|
TableRow,
|
||||||
TimePicker,
|
TimePicker,
|
||||||
Tag,
|
Tag,
|
||||||
|
InlineNotification,
|
||||||
|
Stack,
|
||||||
|
Modal,
|
||||||
|
ComboBox,
|
||||||
|
TextInput,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
} from '@carbon/react';
|
} from '@carbon/react';
|
||||||
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
||||||
|
@ -88,7 +93,7 @@ export default function ProcessInstanceListTable({
|
||||||
autoReload = false,
|
autoReload = false,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [processInstances, setProcessInstances] = useState([]);
|
const [processInstances, setProcessInstances] = useState([]);
|
||||||
|
@ -132,6 +137,12 @@ export default function ProcessInstanceListTable({
|
||||||
const [availableReportColumns, setAvailableReportColumns] = useState<
|
const [availableReportColumns, setAvailableReportColumns] = useState<
|
||||||
ReportColumn[]
|
ReportColumn[]
|
||||||
>([]);
|
>([]);
|
||||||
|
const [processInstanceReportJustSaved, setProcessInstanceReportJustSaved] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
const [showColumnForm, setShowColumnForm] = useState<boolean>(false);
|
||||||
|
const [reportColumnToOperateOn, setReportColumnToOperateOn] =
|
||||||
|
useState<ReportColumn | null>(null);
|
||||||
|
const [columnFormMode, setColumnFormMode] = useState<string>('');
|
||||||
|
|
||||||
const dateParametersToAlwaysFilterBy: dateParameters = useMemo(() => {
|
const dateParametersToAlwaysFilterBy: dateParameters = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
|
@ -357,6 +368,23 @@ export default function ProcessInstanceListTable({
|
||||||
processModelAvailableItems,
|
processModelAvailableItems,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const processInstanceReportSaveTag = () => {
|
||||||
|
if (processInstanceReportJustSaved) {
|
||||||
|
return (
|
||||||
|
<InlineNotification
|
||||||
|
title="Perspective Saved"
|
||||||
|
subtitle={`as '${
|
||||||
|
processInstanceReportSelection
|
||||||
|
? processInstanceReportSelection.display_name
|
||||||
|
: ''
|
||||||
|
}'`}
|
||||||
|
kind="success"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
// does the comparison, but also returns false if either argument
|
// does the comparison, but also returns false if either argument
|
||||||
// is not truthy and therefore not comparable.
|
// is not truthy and therefore not comparable.
|
||||||
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
||||||
|
@ -473,6 +501,7 @@ export default function ProcessInstanceListTable({
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
|
setProcessInstanceReportJustSaved(false);
|
||||||
navigate(`/admin/process-instances?${queryParamString}`);
|
navigate(`/admin/process-instances?${queryParamString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -560,17 +589,22 @@ export default function ProcessInstanceListTable({
|
||||||
setEndToTime('');
|
setEndToTime('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const processInstanceReportDidChange = (selection: any) => {
|
const processInstanceReportDidChange = (
|
||||||
|
selection: any,
|
||||||
|
savedReport: boolean = false
|
||||||
|
) => {
|
||||||
clearFilters();
|
clearFilters();
|
||||||
|
|
||||||
const selectedReport = selection.selectedItem;
|
const selectedReport = selection.selectedItem;
|
||||||
setProcessInstanceReportSelection(selectedReport);
|
setProcessInstanceReportSelection(selectedReport);
|
||||||
|
|
||||||
const queryParamString = selectedReport
|
let queryParamString = '';
|
||||||
? `&report_identifier=${selectedReport.id}`
|
if (selectedReport) {
|
||||||
: '';
|
queryParamString = `&report_identifier=${selectedReport.id}`;
|
||||||
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
|
setProcessInstanceReportJustSaved(savedReport);
|
||||||
navigate(`/admin/process-instances?${queryParamString}`);
|
navigate(`/admin/process-instances?${queryParamString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -578,12 +612,21 @@ export default function ProcessInstanceListTable({
|
||||||
return (reportMetadata as any).columns;
|
return (reportMetadata as any).columns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const reportColumnAccessors = () => {
|
||||||
|
return reportColumns().map((reportColumn: ReportColumn) => {
|
||||||
|
return reportColumn.accessor;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const saveAsReportComponent = () => {
|
const saveAsReportComponent = () => {
|
||||||
// TODO onSuccess reload/select the new report in the report search
|
// TODO onSuccess reload/select the new report in the report search
|
||||||
const callback = (identifier: string) => {
|
const callback = (identifier: string) => {
|
||||||
processInstanceReportDidChange({
|
processInstanceReportDidChange(
|
||||||
selectedItem: { id: identifier, display_name: identifier },
|
{
|
||||||
});
|
selectedItem: { id: identifier, display_name: identifier },
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const {
|
const {
|
||||||
valid,
|
valid,
|
||||||
|
@ -611,18 +654,146 @@ 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleColumnFormClose = () => {
|
||||||
|
setShowColumnForm(false);
|
||||||
|
setColumnFormMode('');
|
||||||
|
setReportColumnToOperateOn(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateColumn = () => {
|
||||||
|
if (reportColumnToOperateOn) {
|
||||||
|
const reportMetadataCopy = { ...reportMetadata };
|
||||||
|
let newReportColumns = null;
|
||||||
|
if (columnFormMode === 'new') {
|
||||||
|
newReportColumns = reportColumns().concat([reportColumnToOperateOn]);
|
||||||
|
} else {
|
||||||
|
newReportColumns = reportColumns().map((rc: ReportColumn) => {
|
||||||
|
if (rc.accessor === reportColumnToOperateOn.accessor) {
|
||||||
|
return reportColumnToOperateOn;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Object.assign(reportMetadataCopy, {
|
||||||
|
columns: newReportColumns,
|
||||||
|
});
|
||||||
|
setReportMetadata(reportMetadataCopy);
|
||||||
|
setReportColumnToOperateOn(null);
|
||||||
|
setShowColumnForm(false);
|
||||||
|
setShowColumnForm(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateReportColumn = (event: any) => {
|
||||||
|
setReportColumnToOperateOn(event.selectedItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
// options includes item and inputValue
|
||||||
|
const shouldFilterReportColumn = (options: any) => {
|
||||||
|
const reportColumn: ReportColumn = options.item;
|
||||||
|
const { inputValue } = options;
|
||||||
|
return (
|
||||||
|
!reportColumnAccessors().includes(reportColumn.accessor) &&
|
||||||
|
(reportColumn.accessor || '')
|
||||||
|
.toLowerCase()
|
||||||
|
.includes((inputValue || '').toLowerCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columnForm = () => {
|
||||||
|
if (columnFormMode === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const formElements = [
|
||||||
|
<TextInput
|
||||||
|
id="report-column-display-name"
|
||||||
|
name="report-column-display-name"
|
||||||
|
labelText="Display Name"
|
||||||
|
disabled={!reportColumnToOperateOn}
|
||||||
|
value={reportColumnToOperateOn ? reportColumnToOperateOn.Header : ''}
|
||||||
|
onChange={(event: any) => {
|
||||||
|
if (reportColumnToOperateOn) {
|
||||||
|
const reportColumnToOperateOnCopy = {
|
||||||
|
...reportColumnToOperateOn,
|
||||||
|
};
|
||||||
|
reportColumnToOperateOnCopy.Header = event.target.value;
|
||||||
|
setReportColumnToOperateOn(reportColumnToOperateOnCopy);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
];
|
||||||
|
if (columnFormMode === 'new') {
|
||||||
|
formElements.push(
|
||||||
|
<ComboBox
|
||||||
|
onChange={updateReportColumn}
|
||||||
|
className="combo-box-in-modal"
|
||||||
|
id="report-column-selection"
|
||||||
|
data-qa="report-column-selection"
|
||||||
|
data-modal-primary-focus
|
||||||
|
items={availableReportColumns}
|
||||||
|
itemToString={(reportColumn: ReportColumn) => {
|
||||||
|
if (reportColumn) {
|
||||||
|
return reportColumn.accessor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
shouldFilterItem={shouldFilterReportColumn}
|
||||||
|
placeholder="Choose a report column"
|
||||||
|
titleText="Report Column"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const modalHeading =
|
||||||
|
columnFormMode === 'new'
|
||||||
|
? 'Add Column'
|
||||||
|
: `Edit ${
|
||||||
|
reportColumnToOperateOn ? reportColumnToOperateOn.accessor : ''
|
||||||
|
} column`;
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={showColumnForm}
|
||||||
|
modalHeading={modalHeading}
|
||||||
|
primaryButtonText="Save"
|
||||||
|
primaryButtonDisabled={!reportColumnToOperateOn}
|
||||||
|
onRequestSubmit={handleUpdateColumn}
|
||||||
|
onRequestClose={handleColumnFormClose}
|
||||||
|
hasScrollingContent
|
||||||
|
>
|
||||||
|
{formElements}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const columnSelections = () => {
|
const columnSelections = () => {
|
||||||
if (reportColumns()) {
|
if (reportColumns()) {
|
||||||
const tags: any = [];
|
const tags: any = [];
|
||||||
|
|
||||||
(reportColumns() as any).forEach((reportColumn: ReportColumn) => {
|
(reportColumns() as any).forEach((reportColumn: ReportColumn) => {
|
||||||
|
let tagType = 'cool-gray';
|
||||||
|
if (reportColumn.filterable) {
|
||||||
|
tagType = 'green';
|
||||||
|
}
|
||||||
tags.push(
|
tags.push(
|
||||||
<Tag type="cool-gray" size="sm" title={reportColumn.accessor}>
|
<Tag type={tagType} size="sm" title={reportColumn.accessor}>
|
||||||
<Button
|
<Button
|
||||||
kind="ghost"
|
kind="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="button-tag-icon"
|
className="button-tag-icon"
|
||||||
title="Edit Header"
|
title="Edit Header"
|
||||||
|
onClick={() => {
|
||||||
|
setReportColumnToOperateOn(reportColumn);
|
||||||
|
setShowColumnForm(true);
|
||||||
|
setColumnFormMode('edit');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{reportColumn.Header}
|
{reportColumn.Header}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -634,12 +805,29 @@ export default function ProcessInstanceListTable({
|
||||||
hasIconOnly
|
hasIconOnly
|
||||||
size="sm"
|
size="sm"
|
||||||
kind="ghost"
|
kind="ghost"
|
||||||
onClick={toggleShowFilterOptions}
|
onClick={() => removeColumn(reportColumn)}
|
||||||
/>
|
/>
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return tags;
|
return (
|
||||||
|
<Stack orientation="horizontal">
|
||||||
|
{tags}
|
||||||
|
<Button
|
||||||
|
data-qa="add-column-button"
|
||||||
|
renderIcon={AddAlt}
|
||||||
|
iconDescription="Filter Options"
|
||||||
|
className="with-tiny-top-margin"
|
||||||
|
kind="ghost"
|
||||||
|
hasIconOnly
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setShowColumnForm(true);
|
||||||
|
setColumnFormMode('new');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -651,7 +839,9 @@ export default function ProcessInstanceListTable({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid fullWidth className="with-bottom-margin">
|
<Grid fullWidth className="with-bottom-margin">
|
||||||
<Column md={8}>{columnSelections()}</Column>
|
<Column md={8} lg={16} sm={4}>
|
||||||
|
{columnSelections()}
|
||||||
|
</Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid fullWidth className="with-bottom-margin">
|
<Grid fullWidth className="with-bottom-margin">
|
||||||
<Column md={8}>
|
<Column md={8}>
|
||||||
|
@ -903,6 +1093,8 @@ export default function ProcessInstanceListTable({
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{columnForm()}
|
||||||
|
{processInstanceReportSaveTag()}
|
||||||
{filterComponent()}
|
{filterComponent()}
|
||||||
{reportSearchComponent()}
|
{reportSearchComponent()}
|
||||||
<PaginationForTable
|
<PaginationForTable
|
||||||
|
|
|
@ -169,6 +169,10 @@ h1.with-icons {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.with-tiny-top-margin {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.with-large-bottom-margin {
|
.with-large-bottom-margin {
|
||||||
margin-bottom: 3em;
|
margin-bottom: 3em;
|
||||||
}
|
}
|
||||||
|
@ -334,3 +338,7 @@ td.actions-cell {
|
||||||
.no-wrap .cds--label--inline{
|
.no-wrap .cds--label--inline{
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.combo-box-in-modal {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
|
@ -156,4 +156,5 @@ export interface FormField {
|
||||||
export interface ReportColumn {
|
export interface ReportColumn {
|
||||||
Header: string;
|
Header: string;
|
||||||
accessor: string;
|
accessor: string;
|
||||||
|
filterable: boolean;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue