added better error message for failed tasks w/ burnettk

This commit is contained in:
jasquat 2022-12-28 16:29:17 -05:00
parent daf85f0efa
commit fb20d89459
13 changed files with 75 additions and 54 deletions

View File

@ -17,13 +17,11 @@ import UserService from './services/UserService';
import { Notification } from './components/Notification';
export default function App() {
const [errorMessage, setErrorMessage] = useState<ErrorForDisplay | null>(
null
);
const [errorObject, setErrorObject] = useState<ErrorForDisplay | null>(null);
const errorContextValueArray = useMemo(
() => [errorMessage, setErrorMessage],
[errorMessage]
() => [errorObject, setErrorObject],
[errorObject]
);
if (!UserService.isLoggedIn()) {
@ -34,27 +32,46 @@ export default function App() {
const ability = defineAbility(() => {});
let errorTag = null;
if (errorMessage) {
if (errorObject) {
let sentryLinkTag = null;
if (errorMessage.sentry_link) {
if (errorObject.sentry_link) {
sentryLinkTag = (
<span>
{
': Find details about this error here (it may take a moment to become available): '
}
<a href={errorMessage.sentry_link} target="_blank" rel="noreferrer">
{errorMessage.sentry_link}
<a href={errorObject.sentry_link} target="_blank" rel="noreferrer">
{errorObject.sentry_link}
</a>
</span>
);
}
let message = <div>{errorObject.message}</div>;
let title = 'Error:';
if ('task_name' in errorObject) {
title = `Error in python script:`;
message = (
<>
<br />
<div>
Task: {errorObject.task_name} ({errorObject.task_id})
</div>
<div>File name: {errorObject.file_name}</div>
<div>Line number in script task: {errorObject.line_number}</div>
<br />
<div>{errorObject.message}</div>
</>
);
}
errorTag = (
<Notification
title="Error:"
onClose={() => setErrorMessage(null)}
title={title}
onClose={() => setErrorObject(null)}
type="error"
>
{errorMessage.message}
{message}
{sentryLinkTag}
</Notification>
);

View File

@ -21,9 +21,9 @@ export function Notification({
onClose,
type = 'success',
}: OwnProps) {
let iconComponent = <Checkmark />;
let iconComponent = <Checkmark className="notification-icon" />;
if (type === 'error') {
iconComponent = <Error />;
iconComponent = <Error className="notification-icon" />;
}
return (
<div

View File

@ -132,7 +132,7 @@ export default function ProcessInstanceListTable({
const [endFromTimeInvalid, setEndFromTimeInvalid] = useState<boolean>(false);
const [endToTimeInvalid, setEndToTimeInvalid] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = (useContext as any)(ErrorContext);
const [errorObject, setErrorObject] = (useContext as any)(ErrorContext);
const processInstancePathPrefix =
variant === 'all'
@ -469,7 +469,7 @@ export default function ProcessInstanceListTable({
}
if (message !== '') {
valid = false;
setErrorMessageSafely(message, errorMessage, setErrorMessage);
setErrorMessageSafely(message, errorObject, setErrorObject);
}
}
@ -527,7 +527,7 @@ export default function ProcessInstanceListTable({
queryParamString += `&report_id=${processInstanceReportSelection.id}`;
}
setErrorMessage(null);
setErrorObject(null);
setProcessInstanceReportJustSaved(null);
navigate(`${processInstancePathPrefix}?${queryParamString}`);
};
@ -626,7 +626,7 @@ export default function ProcessInstanceListTable({
queryParamString = `?report_id=${selectedReport.id}`;
}
setErrorMessage(null);
setErrorObject(null);
setProcessInstanceReportJustSaved(mode || null);
navigate(`${processInstancePathPrefix}${queryParamString}`);
};

View File

@ -78,7 +78,7 @@ export default function ProcessInstanceRun({
checkPermissions = true,
}: OwnProps) {
const navigate = useNavigate();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const modifiedProcessModelId = modifyProcessIdentifierForPathParam(
processModel.id
);
@ -105,12 +105,12 @@ export default function ProcessInstanceRun({
};
const processModelRun = (processInstance: any) => {
setErrorMessage(null);
setErrorObject(null);
storeRecentProcessModelInLocalStorage(processModel);
HttpService.makeCallToBackend({
path: `/process-instances/${modifiedProcessModelId}/${processInstance.id}/run`,
successCallback: onProcessInstanceRun,
failureCallback: setErrorMessage,
failureCallback: setErrorObject,
httpMethod: 'POST',
});
};

View File

@ -158,6 +158,10 @@ export type HotCrumbItem = HotCrumbItemArray | HotCrumbItemObject;
export interface ErrorForDisplay {
message: string;
sentry_link?: string;
task_name?: string;
task_id?: string;
line_number?: number;
file_name?: string;
}
export interface AuthenticationParam {

View File

@ -25,11 +25,11 @@ import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
export default function AdminRoutes() {
const location = useLocation();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
useEffect(() => {
setErrorMessage(null);
}, [location, setErrorMessage]);
setErrorObject(null);
}, [location, setErrorObject]);
if (UserService.hasRole(['admin'])) {
return (

View File

@ -7,7 +7,7 @@ import HttpService from '../services/HttpService';
import UserService from '../services/UserService';
export default function AuthenticationList() {
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const [authenticationList, setAuthenticationList] = useState<
AuthenticationItem[] | null
@ -26,9 +26,9 @@ export default function AuthenticationList() {
HttpService.makeCallToBackend({
path: `/authentications`,
successCallback: processResult,
failureCallback: setErrorMessage,
failureCallback: setErrorObject,
});
}, [setErrorMessage]);
}, [setErrorObject]);
const buildTable = () => {
if (authenticationList) {

View File

@ -14,7 +14,7 @@ import { usePermissionFetcher } from '../hooks/PermissionService';
export default function Configuration() {
const location = useLocation();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
const navigate = useNavigate();
@ -26,13 +26,13 @@ export default function Configuration() {
const { ability } = usePermissionFetcher(permissionRequestData);
useEffect(() => {
setErrorMessage(null);
setErrorObject(null);
let newSelectedTabIndex = 0;
if (location.pathname.match(/^\/admin\/configuration\/authentications\b/)) {
newSelectedTabIndex = 1;
}
setSelectedTabIndex(newSelectedTabIndex);
}, [location, setErrorMessage]);
}, [location, setErrorObject]);
return (
<>

View File

@ -11,12 +11,12 @@ import CreateNewInstance from './CreateNewInstance';
export default function HomePageRoutes() {
const location = useLocation();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
const navigate = useNavigate();
useEffect(() => {
setErrorMessage(null);
setErrorObject(null);
let newSelectedTabIndex = 0;
if (location.pathname.match(/^\/tasks\/completed-instances\b/)) {
newSelectedTabIndex = 1;
@ -24,7 +24,7 @@ export default function HomePageRoutes() {
newSelectedTabIndex = 2;
}
setSelectedTabIndex(newSelectedTabIndex);
}, [location, setErrorMessage]);
}, [location, setErrorObject]);
const renderTabs = () => {
if (location.pathname.match(/^\/tasks\/\d+\/\b/)) {

View File

@ -67,7 +67,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
useState<ProcessData | null>(null);
const [editingTaskData, setEditingTaskData] = useState<boolean>(false);
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const unModifiedProcessModelId = unModifyProcessIdentifierForPathParam(
`${params.process_model_id}`
@ -511,7 +511,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
const cancelEditingTaskData = () => {
setEditingTaskData(false);
initializeTaskDataToDisplay(taskToDisplay);
setErrorMessage(null);
setErrorObject(null);
};
const taskDataStringToObject = (dataString: string) => {
@ -527,7 +527,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
};
const saveTaskDataFailure = (result: any) => {
setErrorMessage({ message: result.message });
setErrorObject({ message: result.message });
};
const saveTaskData = () => {
@ -535,7 +535,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
return;
}
setErrorMessage(null);
setErrorObject(null);
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay };

View File

@ -98,7 +98,7 @@ export default function ProcessModelEditDiagram() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const [processModelFile, setProcessModelFile] = useState<ProcessFile | null>(
null
);
@ -172,7 +172,7 @@ export default function ProcessModelEditDiagram() {
const saveDiagram = (bpmnXML: any, fileName = params.file_name) => {
setDisplaySaveFileMessage(false);
setErrorMessage(null);
setErrorObject(null);
setBpmnXmlForDiagramRendering(bpmnXML);
let url = `/process-models/${modifiedProcessModelId}/files`;
@ -198,7 +198,7 @@ export default function ProcessModelEditDiagram() {
HttpService.makeCallToBackend({
path: url,
successCallback: navigateToProcessModelFile,
failureCallback: setErrorMessage,
failureCallback: setErrorObject,
httpMethod,
postBody: formData,
});
@ -510,17 +510,17 @@ export default function ProcessModelEditDiagram() {
const unitTestFailureElement = () => {
if (scriptUnitTestResult && scriptUnitTestResult.result === false) {
let errorMessage = '';
let errorObject = '';
if (scriptUnitTestResult.context) {
errorMessage = 'Unexpected result. Please see the comparison below.';
errorObject = 'Unexpected result. Please see the comparison below.';
} else if (scriptUnitTestResult.line_number) {
errorMessage = `Error encountered running the script. Please check the code around line ${scriptUnitTestResult.line_number}`;
errorObject = `Error encountered running the script. Please check the code around line ${scriptUnitTestResult.line_number}`;
} else {
errorMessage = `Error encountered running the script. ${JSON.stringify(
errorObject = `Error encountered running the script. ${JSON.stringify(
scriptUnitTestResult.error
)}`;
}
let errorStringElement = <span>{errorMessage}</span>;
let errorStringElement = <span>{errorObject}</span>;
let errorContextElement = null;

View File

@ -52,7 +52,7 @@ import { Notification } from '../components/Notification';
export default function ProcessModelShow() {
const params = useParams();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const [processModel, setProcessModel] = useState<ProcessModel | null>(null);
const [processInstance, setProcessInstance] =
@ -148,7 +148,7 @@ export default function ProcessModelShow() {
!('file_contents' in processModelFile) ||
processModelFile.file_contents === undefined
) {
setErrorMessage({
setErrorObject({
message: `Could not file file contents for file: ${processModelFile.name}`,
});
return;
@ -169,7 +169,7 @@ export default function ProcessModelShow() {
};
const downloadFile = (fileName: string) => {
setErrorMessage(null);
setErrorObject(null);
const processModelPath = `process-models/${modifiedProcessModelId}`;
HttpService.makeCallToBackend({
path: `/${processModelPath}/files/${fileName}`,

View File

@ -36,7 +36,7 @@ export default function TaskShow() {
const params = useParams();
const navigate = useNavigate();
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const setErrorObject = (useContext as any)(ErrorContext)[1];
const { targetUris } = useUriListForPermissions();
const permissionRequestData: PermissionsToCheck = {
@ -64,30 +64,30 @@ export default function TaskShow() {
path: `/tasks/${params.process_instance_id}/${params.task_id}`,
successCallback: processResult,
// This causes the page to continuously reload
// failureCallback: setErrorMessage,
// failureCallback: setErrorObject,
});
}
}, [params, permissionsLoaded, ability, targetUris]);
const processSubmitResult = (result: any) => {
setErrorMessage(null);
setErrorObject(null);
if (result.ok) {
navigate(`/tasks`);
} else if (result.process_instance_id) {
navigate(`/tasks/${result.process_instance_id}/${result.id}`);
} else {
setErrorMessage(`Received unexpected error: ${result.message}`);
setErrorObject(`Received unexpected error: ${result.message}`);
}
};
const handleFormSubmit = (event: any) => {
setErrorMessage(null);
setErrorObject(null);
const dataToSubmit = event.formData;
delete dataToSubmit.isManualTask;
HttpService.makeCallToBackend({
path: `/tasks/${params.process_instance_id}/${params.task_id}`,
successCallback: processSubmitResult,
failureCallback: setErrorMessage,
failureCallback: setErrorObject,
httpMethod: 'PUT',
postBody: dataToSubmit,
});