diff --git a/spiffworkflow-frontend/src/App.tsx b/spiffworkflow-frontend/src/App.tsx index 73489083c..ecf9fc54c 100644 --- a/spiffworkflow-frontend/src/App.tsx +++ b/spiffworkflow-frontend/src/App.tsx @@ -14,7 +14,7 @@ import { ErrorForDisplay } from './interfaces'; import { AbilityContext } from './contexts/Can'; import UserService from './services/UserService'; -import { Notification } from './components/Notification'; +import ErrorDisplay from './components/ErrorDisplay'; export default function App() { const [errorObject, setErrorObject] = useState(null); @@ -31,52 +31,6 @@ export default function App() { const ability = defineAbility(() => {}); - let errorTag = null; - if (errorObject) { - let sentryLinkTag = null; - if (errorObject.sentry_link) { - sentryLinkTag = ( - - { - ': Find details about this error here (it may take a moment to become available): ' - } - - {errorObject.sentry_link} - - - ); - } - - let message =
{errorObject.message}
; - let title = 'Error:'; - if ('task_name' in errorObject && errorObject.task_name) { - title = `Error in python script:`; - message = ( - <> -
-
- Task: {errorObject.task_name} ({errorObject.task_id}) -
-
File name: {errorObject.file_name}
-
Line number in script task: {errorObject.line_number}
-
-
{errorObject.message}
- - ); - } - - errorTag = ( - setErrorObject(null)} - type="error" - > - {message} - {sentryLinkTag} - - ); - } - return (
{/* @ts-ignore */} @@ -85,7 +39,7 @@ export default function App() { - {errorTag} + } /> diff --git a/spiffworkflow-frontend/src/components/ErrorDisplay.tsx b/spiffworkflow-frontend/src/components/ErrorDisplay.tsx new file mode 100644 index 000000000..cdbed75a0 --- /dev/null +++ b/spiffworkflow-frontend/src/components/ErrorDisplay.tsx @@ -0,0 +1,55 @@ +import { useContext } from 'react'; +import ErrorContext from '../contexts/ErrorContext'; +import { Notification } from './Notification'; + +export default function ErrorDisplay() { + const [errorObject, setErrorObject] = (useContext as any)(ErrorContext); + + let errorTag = null; + if (errorObject) { + let sentryLinkTag = null; + if (errorObject.sentry_link) { + sentryLinkTag = ( + + { + ': Find details about this error here (it may take a moment to become available): ' + } + + {errorObject.sentry_link} + + + ); + } + + let message =
{errorObject.message}
; + let title = 'Error:'; + if ('task_name' in errorObject && errorObject.task_name) { + title = 'Error in python script:'; + message = ( + <> +
+
+ Task: {errorObject.task_name} ({errorObject.task_id}) +
+
File name: {errorObject.file_name}
+
Line number in script task: {errorObject.line_number}
+
+
{errorObject.message}
+ + ); + } + + errorTag = ( + setErrorObject(null)} + type="error" + > + {message} + {sentryLinkTag} + + ); + } + + return errorTag; +} diff --git a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx index adfa203b3..461c6d844 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx @@ -232,6 +232,15 @@ export default function ProcessModelShow() { isPrimaryBpmnFile: boolean ) => { const elements = []; + + // So there is a bug in here. Since we use a react context for error messages, and since + // its provider wraps the entire app, child components will re-render when there is an + // error displayed. This is normally fine, but it interacts badly with the casl ability.can + // functionality. We have observed that permissionsLoaded is never set to false. So when + // you run a process and it fails, for example, process model show will re-render, the ability + // will be cleared out and it will start fetching permissions from the server, but this + // component still thinks permissionsLoaded is telling the truth (it says true, but it's actually false). + // The only bad effect that we know of is that the Edit icon becomes an eye icon even for admins. let icon = View; let actionWord = 'View'; if (ability.can('PUT', targetUris.processModelFileCreatePath)) { @@ -327,11 +336,7 @@ export default function ProcessModelShow() { let fileLink = null; const fileUrl = profileModelFileEditUrl(processModelFile); if (fileUrl) { - if (ability.can('GET', targetUris.processModelFileCreatePath)) { - fileLink = {processModelFile.name}; - } else { - fileLink = {processModelFile.name}; - } + fileLink = {processModelFile.name}; } constructedTag = ( diff --git a/spiffworkflow-frontend/tsconfig.json b/spiffworkflow-frontend/tsconfig.json index f3d7e4a42..87997abad 100644 --- a/spiffworkflow-frontend/tsconfig.json +++ b/spiffworkflow-frontend/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "baseUrl": ".", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "jsx": "react-jsx",