mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-01-16 13:15:00 +00:00
favor report id over identifier but support both and ui updates to allow setting a condition value on a metadata field, changing the display name, and fixes for saving and updating a report
This commit is contained in:
parent
d1a69073a2
commit
a4edb5d766
@ -544,6 +544,12 @@ paths:
|
|||||||
description: Specifies the identifier of a report to use, if any
|
description: Specifies the identifier of a report to use, if any
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
- name: report_id
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: Specifies the identifier of a report to use, if any
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
get:
|
get:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_list
|
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_list
|
||||||
summary: Returns a list of process instances for a given process model
|
summary: Returns a list of process instances for a given process model
|
||||||
@ -857,14 +863,14 @@ paths:
|
|||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/Workflow"
|
$ref: "#/components/schemas/Workflow"
|
||||||
|
|
||||||
/process-instances/reports/{report_identifier}:
|
/process-instances/reports/{report_id}:
|
||||||
parameters:
|
parameters:
|
||||||
- name: report_identifier
|
- name: report_id
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The unique id of an existing report
|
description: The unique id of an existing report
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: integer
|
||||||
- name: page
|
- name: page
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
|
@ -26,6 +26,10 @@ from spiffworkflow_backend.services.process_instance_processor import (
|
|||||||
ReportMetadata = dict[str, Any]
|
ReportMetadata = dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessInstanceReportAlreadyExistsError(Exception):
|
||||||
|
"""ProcessInstanceReportAlreadyExistsError."""
|
||||||
|
|
||||||
|
|
||||||
class ProcessInstanceReportResult(TypedDict):
|
class ProcessInstanceReportResult(TypedDict):
|
||||||
"""ProcessInstanceReportResult."""
|
"""ProcessInstanceReportResult."""
|
||||||
|
|
||||||
@ -63,7 +67,7 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id: int = db.Column(db.Integer, primary_key=True)
|
||||||
identifier: str = db.Column(db.String(50), nullable=False, index=True)
|
identifier: str = db.Column(db.String(50), nullable=False, index=True)
|
||||||
report_metadata: dict = deferred(db.Column(db.JSON)) # type: ignore
|
report_metadata: dict = deferred(db.Column(db.JSON)) # type: ignore
|
||||||
created_by_id = db.Column(ForeignKey(UserModel.id), nullable=False, index=True)
|
created_by_id = db.Column(ForeignKey(UserModel.id), nullable=False, index=True)
|
||||||
@ -120,14 +124,18 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
|
|||||||
identifier: str,
|
identifier: str,
|
||||||
user: UserModel,
|
user: UserModel,
|
||||||
report_metadata: ReportMetadata,
|
report_metadata: ReportMetadata,
|
||||||
) -> None:
|
) -> ProcessInstanceReportModel:
|
||||||
"""Make_fixture_report."""
|
"""Make_fixture_report."""
|
||||||
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
created_by_id=user.id,
|
created_by_id=user.id,
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if process_instance_report is None:
|
if process_instance_report is not None:
|
||||||
|
raise ProcessInstanceReportAlreadyExistsError(
|
||||||
|
f"Process instance report with identifier already exists: {identifier}"
|
||||||
|
)
|
||||||
|
|
||||||
process_instance_report = cls(
|
process_instance_report = cls(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
created_by_id=user.id,
|
created_by_id=user.id,
|
||||||
@ -136,6 +144,8 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
|
|||||||
db.session.add(process_instance_report)
|
db.session.add(process_instance_report)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
return process_instance_report # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def ticket_for_month_report(cls) -> dict:
|
def ticket_for_month_report(cls) -> dict:
|
||||||
"""Ticket_for_month_report."""
|
"""Ticket_for_month_report."""
|
||||||
|
@ -782,10 +782,12 @@ def process_instance_list(
|
|||||||
with_tasks_completed_by_my_group: Optional[bool] = None,
|
with_tasks_completed_by_my_group: Optional[bool] = None,
|
||||||
user_filter: Optional[bool] = False,
|
user_filter: Optional[bool] = False,
|
||||||
report_identifier: Optional[str] = None,
|
report_identifier: Optional[str] = None,
|
||||||
|
report_id: Optional[int] = None,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_list."""
|
"""Process_instance_list."""
|
||||||
|
|
||||||
process_instance_report = ProcessInstanceReportService.report_with_identifier(
|
process_instance_report = ProcessInstanceReportService.report_with_identifier(
|
||||||
g.user, report_identifier
|
g.user, report_id, report_identifier
|
||||||
)
|
)
|
||||||
|
|
||||||
if user_filter:
|
if user_filter:
|
||||||
@ -960,11 +962,9 @@ def process_instance_list(
|
|||||||
results = ProcessInstanceReportService.add_metadata_columns_to_process_instance(
|
results = ProcessInstanceReportService.add_metadata_columns_to_process_instance(
|
||||||
process_instances.items, process_instance_report.report_metadata["columns"]
|
process_instances.items, process_instance_report.report_metadata["columns"]
|
||||||
)
|
)
|
||||||
report_metadata = process_instance_report.report_metadata
|
|
||||||
|
|
||||||
response_json = {
|
response_json = {
|
||||||
"report_identifier": process_instance_report.identifier,
|
"report": process_instance_report,
|
||||||
"report_metadata": report_metadata,
|
|
||||||
"results": results,
|
"results": results,
|
||||||
"filters": report_filter.to_dict(),
|
"filters": report_filter.to_dict(),
|
||||||
"pagination": {
|
"pagination": {
|
||||||
@ -982,7 +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], "filterable": True} for i in columns_for_metadata
|
{"Header": i[0], "accessor": i[0], "filterable": True}
|
||||||
|
for i in columns_for_metadata
|
||||||
]
|
]
|
||||||
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
|
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
|
||||||
|
|
||||||
@ -1043,22 +1044,22 @@ def process_instance_report_list(
|
|||||||
|
|
||||||
def process_instance_report_create(body: Dict[str, Any]) -> flask.wrappers.Response:
|
def process_instance_report_create(body: Dict[str, Any]) -> flask.wrappers.Response:
|
||||||
"""Process_instance_report_create."""
|
"""Process_instance_report_create."""
|
||||||
ProcessInstanceReportModel.create_report(
|
process_instance_report = ProcessInstanceReportModel.create_report(
|
||||||
identifier=body["identifier"],
|
identifier=body["identifier"],
|
||||||
user=g.user,
|
user=g.user,
|
||||||
report_metadata=body["report_metadata"],
|
report_metadata=body["report_metadata"],
|
||||||
)
|
)
|
||||||
|
|
||||||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
return make_response(jsonify(process_instance_report), 201)
|
||||||
|
|
||||||
|
|
||||||
def process_instance_report_update(
|
def process_instance_report_update(
|
||||||
report_identifier: str,
|
report_id: int,
|
||||||
body: Dict[str, Any],
|
body: Dict[str, Any],
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_report_create."""
|
"""Process_instance_report_create."""
|
||||||
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
identifier=report_identifier,
|
id=report_id,
|
||||||
created_by_id=g.user.id,
|
created_by_id=g.user.id,
|
||||||
).first()
|
).first()
|
||||||
if process_instance_report is None:
|
if process_instance_report is None:
|
||||||
@ -1071,15 +1072,15 @@ def process_instance_report_update(
|
|||||||
process_instance_report.report_metadata = body["report_metadata"]
|
process_instance_report.report_metadata = body["report_metadata"]
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
return make_response(jsonify(process_instance_report), 201)
|
||||||
|
|
||||||
|
|
||||||
def process_instance_report_delete(
|
def process_instance_report_delete(
|
||||||
report_identifier: str,
|
report_id: int,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_report_create."""
|
"""Process_instance_report_create."""
|
||||||
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
identifier=report_identifier,
|
id=report_id,
|
||||||
created_by_id=g.user.id,
|
created_by_id=g.user.id,
|
||||||
).first()
|
).first()
|
||||||
if process_instance_report is None:
|
if process_instance_report is None:
|
||||||
@ -1098,8 +1099,6 @@ def process_instance_report_delete(
|
|||||||
def service_tasks_show() -> flask.wrappers.Response:
|
def service_tasks_show() -> flask.wrappers.Response:
|
||||||
"""Service_tasks_show."""
|
"""Service_tasks_show."""
|
||||||
available_connectors = ServiceTaskService.available_connectors()
|
available_connectors = ServiceTaskService.available_connectors()
|
||||||
print(available_connectors)
|
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps(available_connectors), status=200, mimetype="application/json"
|
json.dumps(available_connectors), status=200, mimetype="application/json"
|
||||||
)
|
)
|
||||||
@ -1133,10 +1132,11 @@ def authentication_callback(
|
|||||||
|
|
||||||
|
|
||||||
def process_instance_report_show(
|
def process_instance_report_show(
|
||||||
report_identifier: str,
|
report_id: int,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
per_page: int = 100,
|
per_page: int = 100,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
|
"""Process_instance_report_show."""
|
||||||
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(
|
||||||
@ -1144,7 +1144,7 @@ def process_instance_report_show(
|
|||||||
)
|
)
|
||||||
|
|
||||||
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
identifier=report_identifier,
|
id=report_id,
|
||||||
created_by_id=g.user.id,
|
created_by_id=g.user.id,
|
||||||
).first()
|
).first()
|
||||||
if process_instance_report is None:
|
if process_instance_report is None:
|
||||||
@ -1421,9 +1421,6 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
|
|||||||
task.form_ui_schema = ui_form_contents
|
task.form_ui_schema = ui_form_contents
|
||||||
|
|
||||||
if task.properties and task.data and "instructionsForEndUser" in task.properties:
|
if task.properties and task.data and "instructionsForEndUser" in task.properties:
|
||||||
print(
|
|
||||||
f"task.properties['instructionsForEndUser']: {task.properties['instructionsForEndUser']}"
|
|
||||||
)
|
|
||||||
if task.properties["instructionsForEndUser"]:
|
if task.properties["instructionsForEndUser"]:
|
||||||
task.properties["instructionsForEndUser"] = render_jinja_template(
|
task.properties["instructionsForEndUser"] = render_jinja_template(
|
||||||
task.properties["instructionsForEndUser"], task.data
|
task.properties["instructionsForEndUser"], task.data
|
||||||
|
@ -29,6 +29,8 @@ class ProcessInstanceReportFilter:
|
|||||||
"""To_dict."""
|
"""To_dict."""
|
||||||
d = {}
|
d = {}
|
||||||
|
|
||||||
|
print(f"dir(self): {dir(self)}")
|
||||||
|
|
||||||
if self.process_model_identifier is not None:
|
if self.process_model_identifier is not None:
|
||||||
d["process_model_identifier"] = self.process_model_identifier
|
d["process_model_identifier"] = self.process_model_identifier
|
||||||
if self.start_from is not None:
|
if self.start_from is not None:
|
||||||
@ -60,12 +62,21 @@ class ProcessInstanceReportService:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def report_with_identifier(
|
def report_with_identifier(
|
||||||
cls, user: UserModel, report_identifier: Optional[str] = None
|
cls,
|
||||||
|
user: UserModel,
|
||||||
|
report_id: Optional[int] = None,
|
||||||
|
report_identifier: Optional[str] = None,
|
||||||
) -> ProcessInstanceReportModel:
|
) -> ProcessInstanceReportModel:
|
||||||
"""Report_with_filter."""
|
"""Report_with_filter."""
|
||||||
|
if report_id is not None:
|
||||||
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
|
id=report_id, created_by_id=user.id
|
||||||
|
).first()
|
||||||
|
if process_instance_report is not None:
|
||||||
|
return process_instance_report # type: ignore
|
||||||
|
|
||||||
if report_identifier is None:
|
if report_identifier is None:
|
||||||
report_identifier = "default"
|
report_identifier = "default"
|
||||||
|
|
||||||
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
process_instance_report = ProcessInstanceReportModel.query.filter_by(
|
||||||
identifier=report_identifier, created_by_id=user.id
|
identifier=report_identifier, created_by_id=user.id
|
||||||
).first()
|
).first()
|
||||||
@ -75,9 +86,7 @@ class ProcessInstanceReportService:
|
|||||||
|
|
||||||
# TODO replace with system reports that are loaded on launch (or similar)
|
# TODO replace with system reports that are loaded on launch (or similar)
|
||||||
temp_system_metadata_map = {
|
temp_system_metadata_map = {
|
||||||
"default": {
|
"default": {"columns": cls.builtin_column_options()},
|
||||||
"columns": cls.builtin_column_options()
|
|
||||||
},
|
|
||||||
"system_report_instances_initiated_by_me": {
|
"system_report_instances_initiated_by_me": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{"Header": "id", "accessor": "id"},
|
{"Header": "id", "accessor": "id"},
|
||||||
@ -113,6 +122,7 @@ class ProcessInstanceReportService:
|
|||||||
created_by_id=user.id,
|
created_by_id=user.id,
|
||||||
report_metadata=temp_system_metadata_map[report_identifier], # type: ignore
|
report_metadata=temp_system_metadata_map[report_identifier], # type: ignore
|
||||||
)
|
)
|
||||||
|
# db.session.add(pro
|
||||||
|
|
||||||
return process_instance_report # type: ignore
|
return process_instance_report # type: ignore
|
||||||
|
|
||||||
@ -246,7 +256,8 @@ class ProcessInstanceReportService:
|
|||||||
{"Header": "Id", "accessor": "id", "filterable": False},
|
{"Header": "Id", "accessor": "id", "filterable": False},
|
||||||
{
|
{
|
||||||
"Header": "Process",
|
"Header": "Process",
|
||||||
"accessor": "process_model_display_name", "filterable": False,
|
"accessor": "process_model_display_name",
|
||||||
|
"filterable": False,
|
||||||
},
|
},
|
||||||
{"Header": "Start", "accessor": "start_in_seconds", "filterable": False},
|
{"Header": "Start", "accessor": "start_in_seconds", "filterable": False},
|
||||||
{"Header": "End", "accessor": "end_in_seconds", "filterable": False},
|
{"Header": "End", "accessor": "end_in_seconds", "filterable": False},
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
} from '@carbon/react';
|
} from '@carbon/react';
|
||||||
import { ProcessModel } from '../interfaces';
|
import { ProcessInstanceReport, ProcessModel } from '../interfaces';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
@ -20,6 +20,8 @@ type OwnProps = {
|
|||||||
endFromSeconds: string | null;
|
endFromSeconds: string | null;
|
||||||
endToSeconds: string | null;
|
endToSeconds: string | null;
|
||||||
buttonText?: string;
|
buttonText?: string;
|
||||||
|
buttonClassName?: string;
|
||||||
|
processInstanceReportSelection?: ProcessInstanceReport | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProcessInstanceListSaveAsReport({
|
export default function ProcessInstanceListSaveAsReport({
|
||||||
@ -27,25 +29,33 @@ export default function ProcessInstanceListSaveAsReport({
|
|||||||
columnArray,
|
columnArray,
|
||||||
orderBy,
|
orderBy,
|
||||||
processModelSelection,
|
processModelSelection,
|
||||||
|
processInstanceReportSelection,
|
||||||
processStatusSelection,
|
processStatusSelection,
|
||||||
startFromSeconds,
|
startFromSeconds,
|
||||||
startToSeconds,
|
startToSeconds,
|
||||||
endFromSeconds,
|
endFromSeconds,
|
||||||
endToSeconds,
|
endToSeconds,
|
||||||
buttonText = 'Save as Perspective',
|
buttonText = 'Save as Perspective',
|
||||||
|
buttonClassName,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const [identifier, setIdentifier] = useState('');
|
const [identifier, setIdentifier] = useState<string>(
|
||||||
|
processInstanceReportSelection?.identifier || ''
|
||||||
|
);
|
||||||
|
|
||||||
const hasIdentifier = () => {
|
const hasIdentifier = () => {
|
||||||
return identifier?.length > 0;
|
return identifier?.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const responseHandler = (result: any) => {
|
const responseHandler = (result: any) => {
|
||||||
if (result.ok === true) {
|
if (result) {
|
||||||
onSuccess(identifier);
|
onSuccess(result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isEditMode = () => {
|
||||||
|
return !!processInstanceReportSelection;
|
||||||
|
};
|
||||||
|
|
||||||
const addProcessInstanceReport = (event: any) => {
|
const addProcessInstanceReport = (event: any) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -94,10 +104,17 @@ export default function ProcessInstanceListSaveAsReport({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let path = `/process-instances/reports`;
|
||||||
|
let httpMethod = 'POST';
|
||||||
|
if (isEditMode() && processInstanceReportSelection) {
|
||||||
|
httpMethod = 'PUT';
|
||||||
|
path = `${path}/${processInstanceReportSelection.id}`;
|
||||||
|
}
|
||||||
|
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: `/process-instances/reports`,
|
path,
|
||||||
successCallback: responseHandler,
|
successCallback: responseHandler,
|
||||||
httpMethod: 'POST',
|
httpMethod,
|
||||||
postBody: {
|
postBody: {
|
||||||
identifier,
|
identifier,
|
||||||
report_metadata: {
|
report_metadata: {
|
||||||
@ -109,9 +126,9 @@ export default function ProcessInstanceListSaveAsReport({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
let textInputComponent = null;
|
||||||
<Form onSubmit={addProcessInstanceReport}>
|
if (!isEditMode()) {
|
||||||
<Stack gap={5} orientation="horizontal">
|
textInputComponent = (
|
||||||
<TextInput
|
<TextInput
|
||||||
id="identifier"
|
id="identifier"
|
||||||
name="identifier"
|
name="identifier"
|
||||||
@ -121,7 +138,19 @@ 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" type="submit">
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form onSubmit={addProcessInstanceReport}>
|
||||||
|
<Stack gap={5} orientation="horizontal">
|
||||||
|
{textInputComponent}
|
||||||
|
<Button
|
||||||
|
disabled={!hasIdentifier()}
|
||||||
|
size="sm"
|
||||||
|
type="submit"
|
||||||
|
className={buttonClassName}
|
||||||
|
>
|
||||||
{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, AddAlt, AddFilled } from '@carbon/icons-react';
|
import { Filter, Close, AddAlt } from '@carbon/icons-react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonSet,
|
ButtonSet,
|
||||||
@ -27,6 +27,7 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
ComboBox,
|
ComboBox,
|
||||||
TextInput,
|
TextInput,
|
||||||
|
FormLabel,
|
||||||
// @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';
|
||||||
@ -93,7 +94,7 @@ export default function ProcessInstanceListTable({
|
|||||||
autoReload = false,
|
autoReload = false,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [processInstances, setProcessInstances] = useState([]);
|
const [processInstances, setProcessInstances] = useState([]);
|
||||||
@ -175,16 +176,12 @@ export default function ProcessInstanceListTable({
|
|||||||
function setProcessInstancesFromResult(result: any) {
|
function setProcessInstancesFromResult(result: any) {
|
||||||
const processInstancesFromApi = result.results;
|
const processInstancesFromApi = result.results;
|
||||||
setProcessInstances(processInstancesFromApi);
|
setProcessInstances(processInstancesFromApi);
|
||||||
setReportMetadata(result.report_metadata);
|
|
||||||
setPagination(result.pagination);
|
setPagination(result.pagination);
|
||||||
setProcessInstanceFilters(result.filters);
|
setProcessInstanceFilters(result.filters);
|
||||||
|
|
||||||
// TODO: need to iron out this interaction some more
|
setReportMetadata(result.report.report_metadata);
|
||||||
if (result.report_identifier !== 'default') {
|
if (result.report.id) {
|
||||||
setProcessInstanceReportSelection({
|
setProcessInstanceReportSelection(result.report);
|
||||||
id: result.report_identifier,
|
|
||||||
display_name: result.report_identifier,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getProcessInstances() {
|
function getProcessInstances() {
|
||||||
@ -206,14 +203,10 @@ export default function ProcessInstanceListTable({
|
|||||||
queryParamString += `&user_filter=${userAppliedFilter}`;
|
queryParamString += `&user_filter=${userAppliedFilter}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let reportIdentifierToUse: any = reportIdentifier;
|
if (searchParams.get('report_id')) {
|
||||||
|
queryParamString += `&report_id=${searchParams.get('report_id')}`;
|
||||||
if (!reportIdentifierToUse) {
|
} else if (reportIdentifier) {
|
||||||
reportIdentifierToUse = searchParams.get('report_identifier');
|
queryParamString += `&report_identifier=${reportIdentifier}`;
|
||||||
}
|
|
||||||
|
|
||||||
if (reportIdentifierToUse) {
|
|
||||||
queryParamString += `&report_identifier=${reportIdentifierToUse}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(dateParametersToAlwaysFilterBy).forEach(
|
Object.keys(dateParametersToAlwaysFilterBy).forEach(
|
||||||
@ -376,7 +369,7 @@ export default function ProcessInstanceListTable({
|
|||||||
title="Perspective Saved"
|
title="Perspective Saved"
|
||||||
subtitle={`as '${
|
subtitle={`as '${
|
||||||
processInstanceReportSelection
|
processInstanceReportSelection
|
||||||
? processInstanceReportSelection.display_name
|
? processInstanceReportSelection.identifier
|
||||||
: ''
|
: ''
|
||||||
}'`}
|
}'`}
|
||||||
kind="success"
|
kind="success"
|
||||||
@ -498,7 +491,7 @@ export default function ProcessInstanceListTable({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (processInstanceReportSelection) {
|
if (processInstanceReportSelection) {
|
||||||
queryParamString += `&report_identifier=${processInstanceReportSelection.id}`;
|
queryParamString += `&report_id=${processInstanceReportSelection.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
@ -595,18 +588,17 @@ export default function ProcessInstanceListTable({
|
|||||||
savedReport: boolean = false
|
savedReport: boolean = false
|
||||||
) => {
|
) => {
|
||||||
clearFilters();
|
clearFilters();
|
||||||
|
|
||||||
const selectedReport = selection.selectedItem;
|
const selectedReport = selection.selectedItem;
|
||||||
setProcessInstanceReportSelection(selectedReport);
|
setProcessInstanceReportSelection(selectedReport);
|
||||||
|
|
||||||
let queryParamString = '';
|
let queryParamString = '';
|
||||||
if (selectedReport) {
|
if (selectedReport) {
|
||||||
queryParamString = `&report_identifier=${selectedReport.id}`;
|
queryParamString = `?report_id=${selectedReport.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
setProcessInstanceReportJustSaved(savedReport);
|
setProcessInstanceReportJustSaved(savedReport);
|
||||||
navigate(`/admin/process-instances?${queryParamString}`);
|
navigate(`/admin/process-instances${queryParamString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const reportColumns = () => {
|
const reportColumns = () => {
|
||||||
@ -619,16 +611,17 @@ export default function ProcessInstanceListTable({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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 onSaveReportSuccess = (result: any) => {
|
||||||
processInstanceReportDidChange(
|
processInstanceReportDidChange(
|
||||||
{
|
{
|
||||||
selectedItem: { id: identifier, display_name: identifier },
|
selectedItem: result,
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveAsReportComponent = () => {
|
||||||
const {
|
const {
|
||||||
valid,
|
valid,
|
||||||
startFromSeconds,
|
startFromSeconds,
|
||||||
@ -642,9 +635,10 @@ export default function ProcessInstanceListTable({
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ProcessInstanceListSaveAsReport
|
<ProcessInstanceListSaveAsReport
|
||||||
onSuccess={callback}
|
onSuccess={onSaveReportSuccess}
|
||||||
columnArray={reportColumns()}
|
columnArray={reportColumns()}
|
||||||
orderBy=""
|
orderBy=""
|
||||||
|
buttonText="Save As New Perspective"
|
||||||
processModelSelection={processModelSelection}
|
processModelSelection={processModelSelection}
|
||||||
processStatusSelection={processStatusSelection}
|
processStatusSelection={processStatusSelection}
|
||||||
startFromSeconds={startFromSeconds}
|
startFromSeconds={startFromSeconds}
|
||||||
@ -710,6 +704,16 @@ export default function ProcessInstanceListTable({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setReportColumnConditionValue = (event: any) => {
|
||||||
|
if (reportColumnToOperateOn) {
|
||||||
|
const reportColumnToOperateOnCopy = {
|
||||||
|
...reportColumnToOperateOn,
|
||||||
|
};
|
||||||
|
reportColumnToOperateOnCopy.condition_value = event.target.value;
|
||||||
|
setReportColumnToOperateOn(reportColumnToOperateOnCopy);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const reportColumnForm = () => {
|
const reportColumnForm = () => {
|
||||||
if (reportColumnFormMode === '') {
|
if (reportColumnFormMode === '') {
|
||||||
return null;
|
return null;
|
||||||
@ -732,6 +736,22 @@ export default function ProcessInstanceListTable({
|
|||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
];
|
];
|
||||||
|
if (reportColumnToOperateOn && reportColumnToOperateOn.filterable) {
|
||||||
|
console.log('reportColumnToOperateOn', reportColumnToOperateOn);
|
||||||
|
formElements.push(
|
||||||
|
<TextInput
|
||||||
|
id="report-column-condition-value"
|
||||||
|
name="report-column-condition-value"
|
||||||
|
labelText="Condition Value"
|
||||||
|
value={
|
||||||
|
reportColumnToOperateOn
|
||||||
|
? reportColumnToOperateOn.condition_value
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
onChange={setReportColumnConditionValue}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
if (reportColumnFormMode === 'new') {
|
if (reportColumnFormMode === 'new') {
|
||||||
formElements.push(
|
formElements.push(
|
||||||
<ComboBox
|
<ComboBox
|
||||||
@ -783,20 +803,24 @@ export default function ProcessInstanceListTable({
|
|||||||
if (reportColumn.filterable) {
|
if (reportColumn.filterable) {
|
||||||
tagType = 'green';
|
tagType = 'green';
|
||||||
}
|
}
|
||||||
|
let reportColumnLabel = reportColumn.Header;
|
||||||
|
if (reportColumn.condition_value) {
|
||||||
|
reportColumnLabel = `${reportColumnLabel}=${reportColumn.condition_value}`;
|
||||||
|
}
|
||||||
tags.push(
|
tags.push(
|
||||||
<Tag type={tagType} size="sm" title={reportColumn.accessor}>
|
<Tag type={tagType} size="sm">
|
||||||
<Button
|
<Button
|
||||||
kind="ghost"
|
kind="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="button-tag-icon"
|
className="button-tag-icon"
|
||||||
title="Edit Header"
|
title={`Edit ${reportColumn.accessor}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setReportColumnToOperateOn(reportColumn);
|
setReportColumnToOperateOn(reportColumn);
|
||||||
setShowReportColumnForm(true);
|
setShowReportColumnForm(true);
|
||||||
setReportColumnFormMode('edit');
|
setReportColumnFormMode('edit');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{reportColumn.Header}
|
{reportColumnLabel}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
data-qa="remove-report-column"
|
data-qa="remove-report-column"
|
||||||
@ -841,6 +865,8 @@ export default function ProcessInstanceListTable({
|
|||||||
<>
|
<>
|
||||||
<Grid fullWidth className="with-bottom-margin">
|
<Grid fullWidth className="with-bottom-margin">
|
||||||
<Column md={8} lg={16} sm={4}>
|
<Column md={8} lg={16} sm={4}>
|
||||||
|
<FormLabel>Columns</FormLabel>
|
||||||
|
<br />
|
||||||
{columnSelections()}
|
{columnSelections()}
|
||||||
</Column>
|
</Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -1043,11 +1069,40 @@ export default function ProcessInstanceListTable({
|
|||||||
|
|
||||||
const reportSearchComponent = () => {
|
const reportSearchComponent = () => {
|
||||||
if (showReports) {
|
if (showReports) {
|
||||||
return (
|
const { startFromSeconds, startToSeconds, endFromSeconds, endToSeconds } =
|
||||||
|
calculateStartAndEndSeconds();
|
||||||
|
const columns = [
|
||||||
|
<Column sm={2} md={4} lg={7}>
|
||||||
<ProcessInstanceReportSearch
|
<ProcessInstanceReportSearch
|
||||||
onChange={processInstanceReportDidChange}
|
onChange={processInstanceReportDidChange}
|
||||||
selectedItem={processInstanceReportSelection}
|
selectedItem={processInstanceReportSelection}
|
||||||
/>
|
/>
|
||||||
|
</Column>,
|
||||||
|
];
|
||||||
|
if (processInstanceReportSelection && showFilterOptions) {
|
||||||
|
columns.push(
|
||||||
|
<Column sm={2} md={4} lg={2}>
|
||||||
|
<ProcessInstanceListSaveAsReport
|
||||||
|
buttonClassName="with-tiny-top-margin"
|
||||||
|
onSuccess={onSaveReportSuccess}
|
||||||
|
columnArray={reportColumns()}
|
||||||
|
orderBy=""
|
||||||
|
buttonText="Save"
|
||||||
|
processModelSelection={processModelSelection}
|
||||||
|
processStatusSelection={processStatusSelection}
|
||||||
|
startFromSeconds={startFromSeconds}
|
||||||
|
startToSeconds={startToSeconds}
|
||||||
|
endFromSeconds={endFromSeconds}
|
||||||
|
endToSeconds={endToSeconds}
|
||||||
|
processInstanceReportSelection={processInstanceReportSelection}
|
||||||
|
/>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Grid className="with-tiny-bottom-margin" fullWidth>
|
||||||
|
{columns}
|
||||||
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
ComboBox,
|
ComboBox,
|
||||||
|
Stack,
|
||||||
|
FormLabel,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
} from '@carbon/react';
|
} from '@carbon/react';
|
||||||
import { truncateString } from '../helpers';
|
import { truncateString } from '../helpers';
|
||||||
@ -22,34 +24,42 @@ export default function ProcessInstanceReportSearch({
|
|||||||
ProcessInstanceReport[] | null
|
ProcessInstanceReport[] | null
|
||||||
>(null);
|
>(null);
|
||||||
|
|
||||||
function setProcessInstanceReportsFromResult(result: any) {
|
useEffect(() => {
|
||||||
const processInstanceReportsFromApi = result.map((item: any) => {
|
function setProcessInstanceReportsFromResult(
|
||||||
return { id: item.identifier, display_name: item.identifier };
|
result: ProcessInstanceReport[]
|
||||||
});
|
) {
|
||||||
setProcessInstanceReports(processInstanceReportsFromApi);
|
setProcessInstanceReports(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processInstanceReports === null) {
|
|
||||||
setProcessInstanceReports([]);
|
setProcessInstanceReports([]);
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: `/process-instances/reports`,
|
path: `/process-instances/reports`,
|
||||||
successCallback: setProcessInstanceReportsFromResult,
|
successCallback: setProcessInstanceReportsFromResult,
|
||||||
});
|
});
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
|
const reportSelectionString = (
|
||||||
|
processInstanceReport: ProcessInstanceReport
|
||||||
|
) => {
|
||||||
|
return `${truncateString(processInstanceReport.identifier, 20)} (${
|
||||||
|
processInstanceReport.id
|
||||||
|
})`;
|
||||||
|
};
|
||||||
|
|
||||||
const shouldFilterProcessInstanceReport = (options: any) => {
|
const shouldFilterProcessInstanceReport = (options: any) => {
|
||||||
const processInstanceReport: ProcessInstanceReport = options.item;
|
const processInstanceReport: ProcessInstanceReport = options.item;
|
||||||
const { inputValue } = options;
|
const { inputValue } = options;
|
||||||
return `${processInstanceReport.id} (${processInstanceReport.display_name})`.includes(
|
return reportSelectionString(processInstanceReport).includes(inputValue);
|
||||||
inputValue
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const reportsAvailable = () => {
|
const reportsAvailable = () => {
|
||||||
return processInstanceReports && processInstanceReports.length > 0;
|
return processInstanceReports && processInstanceReports.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
return reportsAvailable() ? (
|
if (reportsAvailable()) {
|
||||||
|
return (
|
||||||
|
<Stack orientation="horizontal" gap={2}>
|
||||||
|
<FormLabel className="with-top-margin">{titleText}</FormLabel>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
id="process-instance-report-select"
|
id="process-instance-report-select"
|
||||||
@ -57,17 +67,16 @@ export default function ProcessInstanceReportSearch({
|
|||||||
items={processInstanceReports}
|
items={processInstanceReports}
|
||||||
itemToString={(processInstanceReport: ProcessInstanceReport) => {
|
itemToString={(processInstanceReport: ProcessInstanceReport) => {
|
||||||
if (processInstanceReport) {
|
if (processInstanceReport) {
|
||||||
return `${processInstanceReport.id} (${truncateString(
|
return reportSelectionString(processInstanceReport);
|
||||||
processInstanceReport.display_name,
|
|
||||||
20
|
|
||||||
)})`;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}}
|
}}
|
||||||
shouldFilterItem={shouldFilterProcessInstanceReport}
|
shouldFilterItem={shouldFilterProcessInstanceReport}
|
||||||
placeholder="Choose a process instance perspective"
|
placeholder="Choose a process instance perspective"
|
||||||
titleText={titleText}
|
|
||||||
selectedItem={selectedItem}
|
selectedItem={selectedItem}
|
||||||
/>
|
/>
|
||||||
) : null;
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,10 @@ h1.with-icons {
|
|||||||
margin-bottom: 3em;
|
margin-bottom: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.with-tiny-bottom-margin {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.diagram-viewer-canvas {
|
.diagram-viewer-canvas {
|
||||||
border:1px solid #000000;
|
border:1px solid #000000;
|
||||||
height:70vh;
|
height:70vh;
|
||||||
|
@ -63,9 +63,22 @@ export interface MessageInstance {
|
|||||||
message_correlations?: MessageCorrelations;
|
message_correlations?: MessageCorrelations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ReportColumn {
|
||||||
|
Header: string;
|
||||||
|
accessor: string;
|
||||||
|
filterable: boolean;
|
||||||
|
condition_value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReportMetadata {
|
||||||
|
columns: ReportColumn[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProcessInstanceReport {
|
export interface ProcessInstanceReport {
|
||||||
id: string;
|
id: number;
|
||||||
display_name: string;
|
identifier: string;
|
||||||
|
name: string;
|
||||||
|
report_metadata: ReportMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProcessGroupLite {
|
export interface ProcessGroupLite {
|
||||||
@ -152,9 +165,3 @@ export interface FormField {
|
|||||||
type: string;
|
type: string;
|
||||||
enum: string[];
|
enum: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReportColumn {
|
|
||||||
Header: string;
|
|
||||||
accessor: string;
|
|
||||||
filterable: boolean;
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user