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
|
||||
# Always join that hot user table for good performance at serialization time.
|
||||
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()
|
||||
columns_for_metadata = db.session.query(ProcessInstanceMetadataModel.key).distinct().all() # type: ignore
|
||||
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)
|
||||
|
||||
|
||||
|
@ -1139,7 +1137,6 @@ def process_instance_report_show(
|
|||
page: int = 1,
|
||||
per_page: int = 100,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_list."""
|
||||
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
|
||||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||
).paginate(
|
||||
|
|
|
@ -243,13 +243,13 @@ class ProcessInstanceReportService:
|
|||
def builtin_column_options(cls) -> list[dict]:
|
||||
"""Builtin_column_options."""
|
||||
return [
|
||||
{"Header": "Id", "accessor": "id"},
|
||||
{"Header": "Id", "accessor": "id", "filterable": False},
|
||||
{
|
||||
"Header": "Process",
|
||||
"accessor": "process_model_display_name",
|
||||
"accessor": "process_model_display_name", "filterable": False,
|
||||
},
|
||||
{"Header": "Start", "accessor": "start_in_seconds"},
|
||||
{"Header": "End", "accessor": "end_in_seconds"},
|
||||
{"Header": "Username", "accessor": "username"},
|
||||
{"Header": "Status", "accessor": "status"},
|
||||
{"Header": "Start", "accessor": "start_in_seconds", "filterable": False},
|
||||
{"Header": "End", "accessor": "end_in_seconds", "filterable": False},
|
||||
{"Header": "Username", "accessor": "username", "filterable": False},
|
||||
{"Header": "Status", "accessor": "status", "filterable": False},
|
||||
]
|
||||
|
|
|
@ -50,7 +50,6 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
event.preventDefault();
|
||||
|
||||
const orderByArray = orderBy.split(',').filter((n) => n);
|
||||
|
||||
const filterByArray: any = [];
|
||||
|
||||
if (processModelSelection) {
|
||||
|
@ -122,7 +121,7 @@ export default function ProcessInstanceListSaveAsReport({
|
|||
value={identifier}
|
||||
onChange={(e: any) => setIdentifier(e.target.value)}
|
||||
/>
|
||||
<Button disabled={!hasIdentifier()} size="sm">
|
||||
<Button disabled={!hasIdentifier()} size="sm" type="submit">
|
||||
{buttonText}
|
||||
</Button>
|
||||
</Stack>
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
} from 'react-router-dom';
|
||||
|
||||
// @ts-ignore
|
||||
import { Filter, Close } from '@carbon/icons-react';
|
||||
import { Filter, Close, AddAlt, AddFilled } from '@carbon/icons-react';
|
||||
import {
|
||||
Button,
|
||||
ButtonSet,
|
||||
|
@ -22,6 +22,11 @@ import {
|
|||
TableRow,
|
||||
TimePicker,
|
||||
Tag,
|
||||
InlineNotification,
|
||||
Stack,
|
||||
Modal,
|
||||
ComboBox,
|
||||
TextInput,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
||||
|
@ -88,7 +93,7 @@ export default function ProcessInstanceListTable({
|
|||
autoReload = false,
|
||||
}: OwnProps) {
|
||||
const params = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [processInstances, setProcessInstances] = useState([]);
|
||||
|
@ -132,6 +137,12 @@ export default function ProcessInstanceListTable({
|
|||
const [availableReportColumns, setAvailableReportColumns] = useState<
|
||||
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(() => {
|
||||
return {
|
||||
|
@ -357,6 +368,23 @@ export default function ProcessInstanceListTable({
|
|||
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
|
||||
// is not truthy and therefore not comparable.
|
||||
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
||||
|
@ -473,6 +501,7 @@ export default function ProcessInstanceListTable({
|
|||
}
|
||||
|
||||
setErrorMessage(null);
|
||||
setProcessInstanceReportJustSaved(false);
|
||||
navigate(`/admin/process-instances?${queryParamString}`);
|
||||
};
|
||||
|
||||
|
@ -560,17 +589,22 @@ export default function ProcessInstanceListTable({
|
|||
setEndToTime('');
|
||||
};
|
||||
|
||||
const processInstanceReportDidChange = (selection: any) => {
|
||||
const processInstanceReportDidChange = (
|
||||
selection: any,
|
||||
savedReport: boolean = false
|
||||
) => {
|
||||
clearFilters();
|
||||
|
||||
const selectedReport = selection.selectedItem;
|
||||
setProcessInstanceReportSelection(selectedReport);
|
||||
|
||||
const queryParamString = selectedReport
|
||||
? `&report_identifier=${selectedReport.id}`
|
||||
: '';
|
||||
let queryParamString = '';
|
||||
if (selectedReport) {
|
||||
queryParamString = `&report_identifier=${selectedReport.id}`;
|
||||
}
|
||||
|
||||
setErrorMessage(null);
|
||||
setProcessInstanceReportJustSaved(savedReport);
|
||||
navigate(`/admin/process-instances?${queryParamString}`);
|
||||
};
|
||||
|
||||
|
@ -578,12 +612,21 @@ export default function ProcessInstanceListTable({
|
|||
return (reportMetadata as any).columns;
|
||||
};
|
||||
|
||||
const reportColumnAccessors = () => {
|
||||
return reportColumns().map((reportColumn: ReportColumn) => {
|
||||
return reportColumn.accessor;
|
||||
});
|
||||
};
|
||||
|
||||
const saveAsReportComponent = () => {
|
||||
// TODO onSuccess reload/select the new report in the report search
|
||||
const callback = (identifier: string) => {
|
||||
processInstanceReportDidChange({
|
||||
selectedItem: { id: identifier, display_name: identifier },
|
||||
});
|
||||
processInstanceReportDidChange(
|
||||
{
|
||||
selectedItem: { id: identifier, display_name: identifier },
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
const {
|
||||
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 = () => {
|
||||
if (reportColumns()) {
|
||||
const tags: any = [];
|
||||
|
||||
(reportColumns() as any).forEach((reportColumn: ReportColumn) => {
|
||||
let tagType = 'cool-gray';
|
||||
if (reportColumn.filterable) {
|
||||
tagType = 'green';
|
||||
}
|
||||
tags.push(
|
||||
<Tag type="cool-gray" size="sm" title={reportColumn.accessor}>
|
||||
<Tag type={tagType} size="sm" title={reportColumn.accessor}>
|
||||
<Button
|
||||
kind="ghost"
|
||||
size="sm"
|
||||
className="button-tag-icon"
|
||||
title="Edit Header"
|
||||
onClick={() => {
|
||||
setReportColumnToOperateOn(reportColumn);
|
||||
setShowColumnForm(true);
|
||||
setColumnFormMode('edit');
|
||||
}}
|
||||
>
|
||||
{reportColumn.Header}
|
||||
</Button>
|
||||
|
@ -634,12 +805,29 @@ export default function ProcessInstanceListTable({
|
|||
hasIconOnly
|
||||
size="sm"
|
||||
kind="ghost"
|
||||
onClick={toggleShowFilterOptions}
|
||||
onClick={() => removeColumn(reportColumn)}
|
||||
/>
|
||||
</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;
|
||||
};
|
||||
|
@ -651,7 +839,9 @@ export default function ProcessInstanceListTable({
|
|||
return (
|
||||
<>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={8}>{columnSelections()}</Column>
|
||||
<Column md={8} lg={16} sm={4}>
|
||||
{columnSelections()}
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={8}>
|
||||
|
@ -903,6 +1093,8 @@ export default function ProcessInstanceListTable({
|
|||
}
|
||||
return (
|
||||
<>
|
||||
{columnForm()}
|
||||
{processInstanceReportSaveTag()}
|
||||
{filterComponent()}
|
||||
{reportSearchComponent()}
|
||||
<PaginationForTable
|
||||
|
|
|
@ -169,6 +169,10 @@ h1.with-icons {
|
|||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.with-tiny-top-margin {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.with-large-bottom-margin {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
@ -334,3 +338,7 @@ td.actions-cell {
|
|||
.no-wrap .cds--label--inline{
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.combo-box-in-modal {
|
||||
height: 300px;
|
||||
}
|
||||
|
|
|
@ -156,4 +156,5 @@ export interface FormField {
|
|||
export interface ReportColumn {
|
||||
Header: string;
|
||||
accessor: string;
|
||||
filterable: boolean;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue