added some support to add process model metadata. need to fix frontend w/ burnettk
This commit is contained in:
parent
20ca5a2978
commit
6b75fc32a3
|
@ -38,6 +38,7 @@ class ProcessModelInfo:
|
||||||
fault_or_suspend_on_exception: str = NotificationType.fault.value
|
fault_or_suspend_on_exception: str = NotificationType.fault.value
|
||||||
exception_notification_addresses: list[str] = field(default_factory=list)
|
exception_notification_addresses: list[str] = field(default_factory=list)
|
||||||
parent_groups: list[dict] | None = None
|
parent_groups: list[dict] | None = None
|
||||||
|
metadata_extraction_paths: dict[str, str] | None = None
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
"""__post_init__."""
|
"""__post_init__."""
|
||||||
|
@ -76,6 +77,8 @@ class ProcessModelInfoSchema(Schema):
|
||||||
exception_notification_addresses = marshmallow.fields.List(
|
exception_notification_addresses = marshmallow.fields.List(
|
||||||
marshmallow.fields.String
|
marshmallow.fields.String
|
||||||
)
|
)
|
||||||
|
metadata_extraction_paths = marshmallow.fields.Dict(keys=marshmallow.fields.Str(required=False), values=marshmallow.fields.Str(required=False), required=False)
|
||||||
|
|
||||||
|
|
||||||
@post_load
|
@post_load
|
||||||
def make_spec(
|
def make_spec(
|
||||||
|
|
|
@ -261,19 +261,26 @@ def process_model_create(
|
||||||
modified_process_group_id: str, body: Dict[str, Union[str, bool, int]]
|
modified_process_group_id: str, body: Dict[str, Union[str, bool, int]]
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_model_create."""
|
"""Process_model_create."""
|
||||||
process_model_info = ProcessModelInfoSchema().load(body)
|
body_include_list = [
|
||||||
|
"id",
|
||||||
|
"display_name",
|
||||||
|
"primary_file_name",
|
||||||
|
"primary_process_id",
|
||||||
|
"description",
|
||||||
|
"metadata_extraction_paths",
|
||||||
|
]
|
||||||
|
body_filtered = {
|
||||||
|
include_item: body[include_item]
|
||||||
|
for include_item in body_include_list
|
||||||
|
if include_item in body
|
||||||
|
}
|
||||||
|
|
||||||
if modified_process_group_id is None:
|
if modified_process_group_id is None:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
error_code="process_group_id_not_specified",
|
error_code="process_group_id_not_specified",
|
||||||
message="Process Model could not be created when process_group_id path param is unspecified",
|
message="Process Model could not be created when process_group_id path param is unspecified",
|
||||||
status_code=400,
|
status_code=400,
|
||||||
)
|
)
|
||||||
if process_model_info is None:
|
|
||||||
raise ApiError(
|
|
||||||
error_code="process_model_could_not_be_created",
|
|
||||||
message=f"Process Model could not be created from given body: {body}",
|
|
||||||
status_code=400,
|
|
||||||
)
|
|
||||||
|
|
||||||
unmodified_process_group_id = un_modify_modified_process_model_id(
|
unmodified_process_group_id = un_modify_modified_process_model_id(
|
||||||
modified_process_group_id
|
modified_process_group_id
|
||||||
|
@ -286,6 +293,14 @@ def process_model_create(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
process_model_info = ProcessModelInfo(**body_filtered) # type: ignore
|
||||||
|
if process_model_info is None:
|
||||||
|
raise ApiError(
|
||||||
|
error_code="process_model_could_not_be_created",
|
||||||
|
message=f"Process Model could not be created from given body: {body}",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
ProcessModelService.add_process_model(process_model_info)
|
ProcessModelService.add_process_model(process_model_info)
|
||||||
return Response(
|
return Response(
|
||||||
json.dumps(ProcessModelInfoSchema().dump(process_model_info)),
|
json.dumps(ProcessModelInfoSchema().dump(process_model_info)),
|
||||||
|
@ -299,7 +314,6 @@ def process_model_delete(
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_model_delete."""
|
"""Process_model_delete."""
|
||||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
|
||||||
ProcessModelService().process_model_delete(process_model_identifier)
|
ProcessModelService().process_model_delete(process_model_identifier)
|
||||||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
||||||
|
|
||||||
|
@ -314,6 +328,7 @@ def process_model_update(
|
||||||
"primary_file_name",
|
"primary_file_name",
|
||||||
"primary_process_id",
|
"primary_process_id",
|
||||||
"description",
|
"description",
|
||||||
|
"metadata_extraction_paths",
|
||||||
]
|
]
|
||||||
body_filtered = {
|
body_filtered = {
|
||||||
include_item: body[include_item]
|
include_item: body[include_item]
|
||||||
|
@ -321,7 +336,6 @@ def process_model_update(
|
||||||
if include_item in body
|
if include_item in body
|
||||||
}
|
}
|
||||||
|
|
||||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
|
||||||
process_model = get_process_model(process_model_identifier)
|
process_model = get_process_model(process_model_identifier)
|
||||||
ProcessModelService.update_process_model(process_model, body_filtered)
|
ProcessModelService.update_process_model(process_model, body_filtered)
|
||||||
return ProcessModelInfoSchema().dump(process_model)
|
return ProcessModelInfoSchema().dump(process_model)
|
||||||
|
@ -330,10 +344,7 @@ def process_model_update(
|
||||||
def process_model_show(modified_process_model_identifier: str) -> Any:
|
def process_model_show(modified_process_model_identifier: str) -> Any:
|
||||||
"""Process_model_show."""
|
"""Process_model_show."""
|
||||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
|
||||||
process_model = get_process_model(process_model_identifier)
|
process_model = get_process_model(process_model_identifier)
|
||||||
# TODO: Temporary. Should not need the next line once models have correct ids
|
|
||||||
# process_model.id = process_model_identifier
|
|
||||||
files = sorted(SpecFileService.get_files(process_model))
|
files = sorted(SpecFileService.get_files(process_model))
|
||||||
process_model.files = files
|
process_model.files = files
|
||||||
for file in process_model.files:
|
for file in process_model.files:
|
||||||
|
@ -425,7 +436,6 @@ def process_model_file_update(
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_model_file_update."""
|
"""Process_model_file_update."""
|
||||||
process_model_identifier = modified_process_model_id.replace(":", "/")
|
process_model_identifier = modified_process_model_id.replace(":", "/")
|
||||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
|
||||||
process_model = get_process_model(process_model_identifier)
|
process_model = get_process_model(process_model_identifier)
|
||||||
|
|
||||||
request_file = get_file_from_request()
|
request_file = get_file_from_request()
|
||||||
|
@ -1142,7 +1152,7 @@ def process_instance_report_show(
|
||||||
per_page: int = 100,
|
per_page: int = 100,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_report_show."""
|
"""Process_instance_report_show."""
|
||||||
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
|
process_instances = ProcessInstanceModel.query.order_by(
|
||||||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||||
).paginate(
|
).paginate(
|
||||||
page=page, per_page=per_page, error_out=False
|
page=page, per_page=per_page, error_out=False
|
||||||
|
|
|
@ -333,6 +333,7 @@ class TestProcessApi(BaseTest):
|
||||||
process_model.display_name = "Updated Display Name"
|
process_model.display_name = "Updated Display Name"
|
||||||
process_model.primary_file_name = "superduper.bpmn"
|
process_model.primary_file_name = "superduper.bpmn"
|
||||||
process_model.primary_process_id = "superduper"
|
process_model.primary_process_id = "superduper"
|
||||||
|
process_model.metadata_extraction_paths = {'extraction1': 'path1'}
|
||||||
|
|
||||||
modified_process_model_identifier = process_model_identifier.replace("/", ":")
|
modified_process_model_identifier = process_model_identifier.replace("/", ":")
|
||||||
response = client.put(
|
response = client.put(
|
||||||
|
@ -346,6 +347,7 @@ class TestProcessApi(BaseTest):
|
||||||
assert response.json["display_name"] == "Updated Display Name"
|
assert response.json["display_name"] == "Updated Display Name"
|
||||||
assert response.json["primary_file_name"] == "superduper.bpmn"
|
assert response.json["primary_file_name"] == "superduper.bpmn"
|
||||||
assert response.json["primary_process_id"] == "superduper"
|
assert response.json["primary_process_id"] == "superduper"
|
||||||
|
assert response.json["metadata_extraction_paths"] == {'extraction1': 'path1'}
|
||||||
|
|
||||||
def test_process_model_list_all(
|
def test_process_model_list_all(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -142,7 +142,7 @@ export default function ProcessInstanceListTable({
|
||||||
ReportColumn[]
|
ReportColumn[]
|
||||||
>([]);
|
>([]);
|
||||||
const [processInstanceReportJustSaved, setProcessInstanceReportJustSaved] =
|
const [processInstanceReportJustSaved, setProcessInstanceReportJustSaved] =
|
||||||
useState<boolean>(false);
|
useState<string | null>(null);
|
||||||
const [showReportColumnForm, setShowReportColumnForm] =
|
const [showReportColumnForm, setShowReportColumnForm] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const [reportColumnToOperateOn, setReportColumnToOperateOn] =
|
const [reportColumnToOperateOn, setReportColumnToOperateOn] =
|
||||||
|
@ -367,10 +367,14 @@ export default function ProcessInstanceListTable({
|
||||||
|
|
||||||
const processInstanceReportSaveTag = () => {
|
const processInstanceReportSaveTag = () => {
|
||||||
if (processInstanceReportJustSaved) {
|
if (processInstanceReportJustSaved) {
|
||||||
|
let titleOperation = 'Updated';
|
||||||
|
if (processInstanceReportJustSaved === 'new') {
|
||||||
|
titleOperation = 'Created';
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<InlineNotification
|
<InlineNotification
|
||||||
title="Perspective Saved"
|
title={`Perspective ${titleOperation}:`}
|
||||||
subtitle={`as '${
|
subtitle={`'${
|
||||||
processInstanceReportSelection
|
processInstanceReportSelection
|
||||||
? processInstanceReportSelection.identifier
|
? processInstanceReportSelection.identifier
|
||||||
: ''
|
: ''
|
||||||
|
@ -498,7 +502,7 @@ export default function ProcessInstanceListTable({
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
setProcessInstanceReportJustSaved(false);
|
setProcessInstanceReportJustSaved(null);
|
||||||
navigate(`/admin/process-instances?${queryParamString}`);
|
navigate(`/admin/process-instances?${queryParamString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -586,10 +590,7 @@ export default function ProcessInstanceListTable({
|
||||||
setEndToTime('');
|
setEndToTime('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const processInstanceReportDidChange = (
|
const processInstanceReportDidChange = (selection: any, mode?: string) => {
|
||||||
selection: any,
|
|
||||||
savedReport: boolean = false
|
|
||||||
) => {
|
|
||||||
clearFilters();
|
clearFilters();
|
||||||
const selectedReport = selection.selectedItem;
|
const selectedReport = selection.selectedItem;
|
||||||
setProcessInstanceReportSelection(selectedReport);
|
setProcessInstanceReportSelection(selectedReport);
|
||||||
|
@ -600,7 +601,7 @@ export default function ProcessInstanceListTable({
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
setProcessInstanceReportJustSaved(savedReport);
|
setProcessInstanceReportJustSaved(mode || null);
|
||||||
navigate(`/admin/process-instances${queryParamString}`);
|
navigate(`/admin/process-instances${queryParamString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -615,12 +616,12 @@ export default function ProcessInstanceListTable({
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO onSuccess reload/select the new report in the report search
|
// TODO onSuccess reload/select the new report in the report search
|
||||||
const onSaveReportSuccess = (result: any) => {
|
const onSaveReportSuccess = (result: any, mode: string) => {
|
||||||
processInstanceReportDidChange(
|
processInstanceReportDidChange(
|
||||||
{
|
{
|
||||||
selectedItem: result,
|
selectedItem: result,
|
||||||
},
|
},
|
||||||
true
|
mode
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -638,7 +639,7 @@ export default function ProcessInstanceListTable({
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ProcessInstanceListSaveAsReport
|
<ProcessInstanceListSaveAsReport
|
||||||
onSuccess={onSaveReportSuccess}
|
onSuccess={(result: any) => onSaveReportSuccess(result, 'new')}
|
||||||
buttonClassName="narrow-button"
|
buttonClassName="narrow-button"
|
||||||
columnArray={reportColumns()}
|
columnArray={reportColumns()}
|
||||||
orderBy=""
|
orderBy=""
|
||||||
|
@ -705,7 +706,7 @@ export default function ProcessInstanceListTable({
|
||||||
} else {
|
} else {
|
||||||
newReportFilters.splice(existingReportFilterIndex, 1);
|
newReportFilters.splice(existingReportFilterIndex, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (reportColumnForEditing.filter_field_value) {
|
||||||
newReportFilters = newReportFilters.concat([newReportFilter]);
|
newReportFilters = newReportFilters.concat([newReportFilter]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1157,7 +1158,7 @@ export default function ProcessInstanceListTable({
|
||||||
<Column sm={2} md={4} lg={2}>
|
<Column sm={2} md={4} lg={2}>
|
||||||
<ProcessInstanceListSaveAsReport
|
<ProcessInstanceListSaveAsReport
|
||||||
buttonClassName="with-tiny-top-margin"
|
buttonClassName="with-tiny-top-margin"
|
||||||
onSuccess={onSaveReportSuccess}
|
onSuccess={(result: any) => onSaveReportSuccess(result, 'edit')}
|
||||||
columnArray={reportColumns()}
|
columnArray={reportColumns()}
|
||||||
orderBy=""
|
orderBy=""
|
||||||
buttonText="Save"
|
buttonText="Save"
|
||||||
|
|
|
@ -2,9 +2,11 @@ import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { Button, ButtonSet, Form, Stack, TextInput } from '@carbon/react';
|
import { Button, ButtonSet, Form, Stack, TextInput } from '@carbon/react';
|
||||||
|
// @ts-ignore
|
||||||
|
import { AddAlt } from '@carbon/icons-react';
|
||||||
import { modifyProcessIdentifierForPathParam, slugifyString } from '../helpers';
|
import { modifyProcessIdentifierForPathParam, slugifyString } from '../helpers';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import { ProcessModel } from '../interfaces';
|
import { MetadataExtractionPaths, ProcessModel } from '../interfaces';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
mode: string;
|
mode: string;
|
||||||
|
@ -23,6 +25,7 @@ export default function ProcessModelForm({
|
||||||
const [idHasBeenUpdatedByUser, setIdHasBeenUpdatedByUser] =
|
const [idHasBeenUpdatedByUser, setIdHasBeenUpdatedByUser] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const [displayNameInvalid, setDisplayNameInvalid] = useState<boolean>(false);
|
const [displayNameInvalid, setDisplayNameInvalid] = useState<boolean>(false);
|
||||||
|
useState<boolean>(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const navigateToProcessModel = (result: ProcessModel) => {
|
const navigateToProcessModel = (result: ProcessModel) => {
|
||||||
|
@ -64,6 +67,7 @@ export default function ProcessModelForm({
|
||||||
const postBody = {
|
const postBody = {
|
||||||
display_name: processModel.display_name,
|
display_name: processModel.display_name,
|
||||||
description: processModel.description,
|
description: processModel.description,
|
||||||
|
metadata_extraction_paths: processModel.metadata_extraction_paths,
|
||||||
};
|
};
|
||||||
if (mode === 'new') {
|
if (mode === 'new') {
|
||||||
Object.assign(postBody, {
|
Object.assign(postBody, {
|
||||||
|
@ -87,6 +91,66 @@ export default function ProcessModelForm({
|
||||||
setProcessModel(processModelToCopy);
|
setProcessModel(processModelToCopy);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const metadataExtractionPathForm = (
|
||||||
|
metadataKey: string,
|
||||||
|
metadataPath: string
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TextInput
|
||||||
|
id="process-model-metadata-extraction-path-key"
|
||||||
|
labelText="Extraction Key"
|
||||||
|
value={metadataKey}
|
||||||
|
onChange={(event: any) => {
|
||||||
|
const cep: MetadataExtractionPaths =
|
||||||
|
processModel.metadata_extraction_paths || {};
|
||||||
|
delete cep[metadataKey];
|
||||||
|
cep[event.target.value] = metadataPath;
|
||||||
|
updateProcessModel({ metadata_extraction_paths: cep });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
id="process-model-metadata-extraction-path"
|
||||||
|
labelText="Extraction Path"
|
||||||
|
value={metadataPath}
|
||||||
|
onChange={(event: any) => {
|
||||||
|
const cep: MetadataExtractionPaths =
|
||||||
|
processModel.metadata_extraction_paths || {};
|
||||||
|
cep[metadataKey] = event.target.value;
|
||||||
|
updateProcessModel({ metadata_extraction_paths: cep });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const metadataExtractionPathFormArea = () => {
|
||||||
|
if (processModel.metadata_extraction_paths) {
|
||||||
|
console.log(
|
||||||
|
'processModel.metadata_extraction_paths',
|
||||||
|
processModel.metadata_extraction_paths
|
||||||
|
);
|
||||||
|
return Object.keys(processModel.metadata_extraction_paths).map(
|
||||||
|
(metadataKey: string) => {
|
||||||
|
return metadataExtractionPathForm(
|
||||||
|
metadataKey,
|
||||||
|
processModel.metadata_extraction_paths
|
||||||
|
? processModel.metadata_extraction_paths[metadataKey]
|
||||||
|
: ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addBlankMetadataExtractionPath = () => {
|
||||||
|
const cep: MetadataExtractionPaths =
|
||||||
|
processModel.metadata_extraction_paths || {};
|
||||||
|
Object.assign(cep, { '': '' });
|
||||||
|
updateProcessModel({ metadata_extraction_paths: cep });
|
||||||
|
};
|
||||||
|
|
||||||
const onDisplayNameChanged = (newDisplayName: any) => {
|
const onDisplayNameChanged = (newDisplayName: any) => {
|
||||||
setDisplayNameInvalid(false);
|
setDisplayNameInvalid(false);
|
||||||
const updateDict = { display_name: newDisplayName };
|
const updateDict = { display_name: newDisplayName };
|
||||||
|
@ -145,6 +209,22 @@ export default function ProcessModelForm({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
textInputs.push(<>{metadataExtractionPathFormArea()}</>);
|
||||||
|
textInputs.push(
|
||||||
|
<Button
|
||||||
|
data-qa="add-metadata-extraction-path-button"
|
||||||
|
renderIcon={AddAlt}
|
||||||
|
className="button-white-background"
|
||||||
|
kind=""
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
addBlankMetadataExtractionPath();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Metadata Extraction Path
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
return textInputs;
|
return textInputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,10 @@ export interface ProcessGroupLite {
|
||||||
display_name: string;
|
display_name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MetadataExtractionPaths {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProcessModel {
|
export interface ProcessModel {
|
||||||
id: string;
|
id: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
@ -105,6 +109,7 @@ export interface ProcessModel {
|
||||||
primary_file_name: string;
|
primary_file_name: string;
|
||||||
files: ProcessFile[];
|
files: ProcessFile[];
|
||||||
parent_groups?: ProcessGroupLite[];
|
parent_groups?: ProcessGroupLite[];
|
||||||
|
metadata_extraction_paths?: MetadataExtractionPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProcessGroup {
|
export interface ProcessGroup {
|
||||||
|
|
Loading…
Reference in New Issue