Squashed 'spiffworkflow-frontend/' changes from c22d22ba5..4fd946be4
4fd946be4 Merging main 453bdb246 run_pyl b5a8ff01b Needed an additional check for empty correlation keys - which on a RECEIVE message, should always match anything. b583f84cc lint w/ burnettk fd4d7d13b removed some unused code from task and fixed the logs table a bit w/ burnettk 6f17e71e6 avoid using task-data endpoint for task data and only use it to get tasks based on spiff step instead 669c29595 removed task-data endpoints since we no longer need them w/ burnettk 5f25fffe0 added api to get task data and do not return from task data list anymore w/ burnettk 373c4f184 Merge remote-tracking branch 'origin/main' into feature/message_fixes e40c12ac8 turn on sentry detailed tracing for task-data w/ burnettk d7861aae2 Merge branch 'main' into feature/message_fixes 0a9f2480d work in progress - * Link between message instance and correlations is now a link table and many-to-many relationships as recommended by SQLAlchemy * Use the correlation keys, not the process id when accepting api messages. git-subtree-dir: spiffworkflow-frontend git-subtree-split: 4fd946be4ff716bfd1664aca8d75cb6f709b53eb
This commit is contained in:
parent
ce1e54dced
commit
7a5f961b2b
|
@ -8065,7 +8065,7 @@
|
|||
},
|
||||
"node_modules/bpmn-js-spiffworkflow": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#aca23dc56e5d37aa1ed0a3cf11acb55f76a36da7",
|
||||
"resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#f1f008e3e39be43b016718fca6a38b248ab4ecf7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
|
@ -38214,7 +38214,7 @@
|
|||
}
|
||||
},
|
||||
"bpmn-js-spiffworkflow": {
|
||||
"version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#aca23dc56e5d37aa1ed0a3cf11acb55f76a36da7",
|
||||
"version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#f1f008e3e39be43b016718fca6a38b248ab4ecf7",
|
||||
"from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#main",
|
||||
"requires": {
|
||||
"inherits": "^2.0.4",
|
||||
|
|
|
@ -17,7 +17,7 @@ export const useUriListForPermissions = () => {
|
|||
processInstanceResumePath: `/v1.0/process-instance-resume/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceSuspendPath: `/v1.0/process-instance-suspend/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceResetPath: `/v1.0/process-instance-reset/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceTaskListDataPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceTaskDataPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceSendEventPath: `/v1.0/send-event/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceCompleteTaskPath: `/v1.0/complete-task/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceTaskListPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}/task-info`,
|
||||
|
|
|
@ -112,12 +112,13 @@ export interface MessageInstance {
|
|||
process_model_identifier: string;
|
||||
process_model_display_name: string;
|
||||
process_instance_id: number;
|
||||
message_identifier: string;
|
||||
name: string;
|
||||
message_type: string;
|
||||
failure_cause: string;
|
||||
status: string;
|
||||
created_at_in_seconds: number;
|
||||
message_correlations?: MessageCorrelations;
|
||||
correlation_keys: any;
|
||||
}
|
||||
|
||||
export interface ReportFilter {
|
||||
|
|
|
@ -64,17 +64,13 @@ export default function MessageInstanceList() {
|
|||
open={!!messageInstanceForModal}
|
||||
passiveModal
|
||||
onRequestClose={handleCorrelationDisplayClose}
|
||||
modalHeading={`Message ${messageInstanceForModal.id} (${messageInstanceForModal.message_identifier}) ${messageInstanceForModal.message_type} data:`}
|
||||
modalHeading={`Message ${messageInstanceForModal.id} (${messageInstanceForModal.name}) ${messageInstanceForModal.message_type} data:`}
|
||||
modalLabel="Details"
|
||||
>
|
||||
{failureCausePre}
|
||||
<p>Correlations:</p>
|
||||
<pre>
|
||||
{JSON.stringify(
|
||||
messageInstanceForModal.message_correlations,
|
||||
null,
|
||||
2
|
||||
)}
|
||||
{JSON.stringify(messageInstanceForModal.correlation_keys, null, 2)}
|
||||
</pre>
|
||||
</Modal>
|
||||
);
|
||||
|
@ -95,21 +91,27 @@ export default function MessageInstanceList() {
|
|||
</>
|
||||
);
|
||||
}
|
||||
let processLink = <span>External Call</span>;
|
||||
let instanceLink = <span />;
|
||||
if (row.process_instance_id != null) {
|
||||
processLink = FormatProcessModelDisplayName(row);
|
||||
instanceLink = (
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
row.process_model_identifier
|
||||
)}/${row.process_instance_id}`}
|
||||
>
|
||||
{row.process_instance_id}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<tr key={row.id}>
|
||||
<td>{row.id}</td>
|
||||
<td>{FormatProcessModelDisplayName(row)}</td>
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
row.process_model_identifier
|
||||
)}/${row.process_instance_id}`}
|
||||
>
|
||||
{row.process_instance_id}
|
||||
</Link>
|
||||
</td>
|
||||
<td>{row.message_identifier}</td>
|
||||
<td>{processLink}</td>
|
||||
<td>{instanceLink}</td>
|
||||
<td>{row.name}</td>
|
||||
<td>{row.message_type}</td>
|
||||
<td>
|
||||
<Button
|
||||
|
|
|
@ -6,11 +6,11 @@ import PaginationForTable from '../components/PaginationForTable';
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
modifyProcessIdentifierForPathParam,
|
||||
convertSecondsToFormattedDateTime,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||
import UserService from '../services/UserService';
|
||||
|
||||
type OwnProps = {
|
||||
variant: string;
|
||||
|
@ -29,6 +29,8 @@ export default function ProcessInstanceLogList({ variant }: OwnProps) {
|
|||
processInstanceShowPageBaseUrl = `/admin/process-instances/${params.process_model_id}`;
|
||||
}
|
||||
|
||||
const userEmail = UserService.getUserEmail();
|
||||
|
||||
useEffect(() => {
|
||||
const setProcessInstanceLogListFromResult = (result: any) => {
|
||||
setProcessInstanceLogs(result.results);
|
||||
|
@ -46,56 +48,91 @@ export default function ProcessInstanceLogList({ variant }: OwnProps) {
|
|||
isDetailedView,
|
||||
]);
|
||||
|
||||
const getTableRow = (row: any) => {
|
||||
const tableRow = [];
|
||||
const taskNameCell = (
|
||||
<td>
|
||||
{row.bpmn_task_name ||
|
||||
(row.bpmn_task_type === 'Default Start Event'
|
||||
? 'Process Started'
|
||||
: '') ||
|
||||
(row.bpmn_task_type === 'End Event' ? 'Process Ended' : '')}
|
||||
</td>
|
||||
);
|
||||
if (isDetailedView) {
|
||||
tableRow.push(
|
||||
<>
|
||||
<td data-qa="paginated-entity-id">{row.id}</td>
|
||||
<td>{row.bpmn_process_identifier}</td>
|
||||
{taskNameCell}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
tableRow.push(
|
||||
<>
|
||||
{taskNameCell}
|
||||
<td>{row.bpmn_process_identifier}</td>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (isDetailedView) {
|
||||
tableRow.push(
|
||||
<>
|
||||
<td>{row.bpmn_task_type}</td>
|
||||
<td>{row.message}</td>
|
||||
<td>{row.username === userEmail ? 'me 🔥' : row.username}</td>
|
||||
</>
|
||||
);
|
||||
}
|
||||
tableRow.push(
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`${processInstanceShowPageBaseUrl}/${row.process_instance_id}/${row.spiff_step}`}
|
||||
>
|
||||
{convertSecondsToFormattedDateTime(row.timestamp)}
|
||||
</Link>
|
||||
</td>
|
||||
);
|
||||
return <tr key={row.id}>{tableRow}</tr>;
|
||||
};
|
||||
|
||||
const buildTable = () => {
|
||||
const rows = processInstanceLogs.map((row) => {
|
||||
const rowToUse = row as any;
|
||||
return (
|
||||
<tr key={rowToUse.id}>
|
||||
<td data-qa="paginated-entity-id">{rowToUse.id}</td>
|
||||
<td>
|
||||
{rowToUse.bpmn_task_name ||
|
||||
(rowToUse.bpmn_task_type === 'Default Start Event'
|
||||
? 'Process Started'
|
||||
: '') ||
|
||||
(rowToUse.bpmn_task_type === 'End Event' ? 'Process Ended' : '')}
|
||||
</td>
|
||||
{isDetailedView && (
|
||||
<>
|
||||
<td>{rowToUse.message}</td>
|
||||
<td>{rowToUse.bpmn_task_identifier}</td>
|
||||
<td>{rowToUse.bpmn_task_type}</td>
|
||||
</>
|
||||
)}
|
||||
<td>{rowToUse.bpmn_process_identifier}</td>
|
||||
<td>{rowToUse.username}</td>
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`${processInstanceShowPageBaseUrl}/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`}
|
||||
>
|
||||
{convertSecondsToFormattedDateTime(rowToUse.timestamp)}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
return getTableRow(row);
|
||||
});
|
||||
|
||||
const tableHeaders = [];
|
||||
if (isDetailedView) {
|
||||
tableHeaders.push(
|
||||
<>
|
||||
<th>Id</th>
|
||||
<th>Bpmn Process</th>
|
||||
<th>Task Name</th>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
tableHeaders.push(
|
||||
<>
|
||||
<th>Event</th>
|
||||
<th>Bpmn Process</th>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (isDetailedView) {
|
||||
tableHeaders.push(
|
||||
<>
|
||||
<th>Task Type</th>
|
||||
<th>Message</th>
|
||||
<th>User</th>
|
||||
</>
|
||||
);
|
||||
}
|
||||
tableHeaders.push(<th>Timestamp</th>);
|
||||
return (
|
||||
<Table size="lg">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Task Name</th>
|
||||
{isDetailedView && (
|
||||
<>
|
||||
<th>Message</th>
|
||||
<th>Task Identifier</th>
|
||||
<th>Task Type</th>
|
||||
</>
|
||||
)}
|
||||
<th>Bpmn Process Identifier</th>
|
||||
<th>User</th>
|
||||
<th>Timestamp</th>
|
||||
</tr>
|
||||
<tr>{tableHeaders}</tr>
|
||||
</thead>
|
||||
<tbody>{rows}</tbody>
|
||||
</Table>
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
Modal,
|
||||
Dropdown,
|
||||
Stack,
|
||||
Loading,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { Can } from '@casl/react';
|
||||
|
@ -65,8 +66,12 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
useState<ProcessInstance | null>(null);
|
||||
const [tasks, setTasks] = useState<ProcessInstanceTask[] | null>(null);
|
||||
const [tasksCallHadError, setTasksCallHadError] = useState<boolean>(false);
|
||||
const [taskToDisplay, setTaskToDisplay] = useState<object | null>(null);
|
||||
const [taskToDisplay, setTaskToDisplay] =
|
||||
useState<ProcessInstanceTask | null>(null);
|
||||
const [taskDataToDisplay, setTaskDataToDisplay] = useState<string>('');
|
||||
const [showTaskDataLoading, setShowTaskDataLoading] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [processDataToDisplay, setProcessDataToDisplay] =
|
||||
useState<ProcessData | null>(null);
|
||||
const [editingTaskData, setEditingTaskData] = useState<boolean>(false);
|
||||
|
@ -99,7 +104,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
[targetUris.messageInstanceListPath]: ['GET'],
|
||||
[targetUris.processInstanceActionPath]: ['DELETE'],
|
||||
[targetUris.processInstanceLogListPath]: ['GET'],
|
||||
[targetUris.processInstanceTaskListDataPath]: ['GET', 'PUT'],
|
||||
[targetUris.processInstanceTaskDataPath]: ['GET', 'PUT'],
|
||||
[targetUris.processInstanceSendEventPath]: ['POST'],
|
||||
[targetUris.processInstanceCompleteTaskPath]: ['POST'],
|
||||
[targetUris.processModelShowPath]: ['PUT'],
|
||||
|
@ -145,9 +150,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
taskParams = `${taskParams}&spiff_step=${params.spiff_step}`;
|
||||
}
|
||||
let taskPath = '';
|
||||
if (ability.can('GET', targetUris.processInstanceTaskListDataPath)) {
|
||||
taskPath = `${targetUris.processInstanceTaskListDataPath}${taskParams}`;
|
||||
} else if (ability.can('GET', taskListPath)) {
|
||||
if (ability.can('GET', taskListPath)) {
|
||||
taskPath = `${taskListPath}${taskParams}`;
|
||||
}
|
||||
if (taskPath) {
|
||||
|
@ -557,11 +560,33 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
return <div />;
|
||||
};
|
||||
|
||||
const initializeTaskDataToDisplay = (task: any) => {
|
||||
if (task == null) {
|
||||
const processTaskResult = (result: ProcessInstanceTask) => {
|
||||
if (result == null) {
|
||||
setTaskDataToDisplay('');
|
||||
} else {
|
||||
setTaskDataToDisplay(JSON.stringify(task.data, null, 2));
|
||||
setTaskDataToDisplay(JSON.stringify(result.data, null, 2));
|
||||
}
|
||||
setShowTaskDataLoading(false);
|
||||
};
|
||||
|
||||
const initializeTaskDataToDisplay = (task: ProcessInstanceTask | null) => {
|
||||
if (
|
||||
task &&
|
||||
task.state === 'COMPLETED' &&
|
||||
ability.can('GET', targetUris.processInstanceTaskDataPath)
|
||||
) {
|
||||
setShowTaskDataLoading(true);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `${targetUris.processInstanceTaskDataPath}/${task.task_spiff_step}`,
|
||||
httpMethod: 'GET',
|
||||
successCallback: processTaskResult,
|
||||
failureCallback: (error: any) => {
|
||||
setTaskDataToDisplay(`ERROR: ${error.message}`);
|
||||
setShowTaskDataLoading(false);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
setTaskDataToDisplay('');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -668,7 +693,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
const canEditTaskData = (task: any) => {
|
||||
return (
|
||||
processInstance &&
|
||||
ability.can('PUT', targetUris.processInstanceTaskListDataPath) &&
|
||||
ability.can('PUT', targetUris.processInstanceTaskDataPath) &&
|
||||
isCurrentTask(task) &&
|
||||
processInstance.status === 'suspended' &&
|
||||
showingLastSpiffStep()
|
||||
|
@ -742,8 +767,13 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
const saveTaskDataResult = (_: any) => {
|
||||
setEditingTaskData(false);
|
||||
const dataObject = taskDataStringToObject(taskDataToDisplay);
|
||||
const taskToDisplayCopy = { ...taskToDisplay, data: dataObject }; // spread operator
|
||||
setTaskToDisplay(taskToDisplayCopy);
|
||||
if (taskToDisplay) {
|
||||
const taskToDisplayCopy: ProcessInstanceTask = {
|
||||
...taskToDisplay,
|
||||
data: dataObject,
|
||||
}; // spread operator
|
||||
setTaskToDisplay(taskToDisplayCopy);
|
||||
}
|
||||
refreshPage();
|
||||
};
|
||||
|
||||
|
@ -757,7 +787,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
|
||||
const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay };
|
||||
HttpService.makeCallToBackend({
|
||||
path: `${targetUris.processInstanceTaskListDataPath}/${taskToUse.id}`,
|
||||
path: `${targetUris.processInstanceTaskDataPath}/${taskToUse.id}`,
|
||||
httpMethod: 'PUT',
|
||||
successCallback: saveTaskDataResult,
|
||||
failureCallback: addError,
|
||||
|
@ -901,6 +931,10 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
};
|
||||
|
||||
const taskDataContainer = () => {
|
||||
let taskDataClassName = '';
|
||||
if (taskDataToDisplay.startsWith('ERROR:')) {
|
||||
taskDataClassName = 'failure-string';
|
||||
}
|
||||
return editingTaskData ? (
|
||||
<Editor
|
||||
height={600}
|
||||
|
@ -910,7 +944,12 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
onChange={(value) => setTaskDataToDisplay(value || '')}
|
||||
/>
|
||||
) : (
|
||||
<pre>{taskDataToDisplay}</pre>
|
||||
<>
|
||||
{showTaskDataLoading ? (
|
||||
<Loading className="some-class" withOverlay={false} small />
|
||||
) : null}
|
||||
<pre className={taskDataClassName}>{taskDataToDisplay}</pre>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ export default function TaskShow() {
|
|||
useEffect(() => {
|
||||
const processResult = (result: ProcessInstanceTask) => {
|
||||
setTask(result);
|
||||
const url = `/task-data/${modifyProcessIdentifierForPathParam(
|
||||
const url = `/v1.0/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
result.process_model_identifier
|
||||
)}/${params.process_instance_id}`;
|
||||
// if user is unauthorized to get task-data then don't do anything
|
||||
)}/${params.process_instance_id}/task-info`;
|
||||
// if user is unauthorized to get process-instance task-info then don't do anything
|
||||
// Checking like this so we can dynamically create the url with the correct process model
|
||||
// instead of passing the process model identifier in through the params
|
||||
HttpService.makeCallToBackend({
|
||||
|
|
Loading…
Reference in New Issue