forked from sartography/spiff-arena
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
254e3e7
commit 678cc4f
Showing
13 changed files
with
483 additions
and
8 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { defineAbility } from '@casl/ability'; | ||
|
||
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom'; | ||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
import { AbilityContext } from './contexts/Can'; | ||
import APIErrorProvider from './contexts/APIErrorContext'; | ||
import ContainerForExtensionsMicro from './ContainerForExtensionsMicro'; | ||
import { BASENAME_URL } from './config'; | ||
|
||
const queryClient = new QueryClient(); | ||
|
||
export default function AppSpa() { | ||
const ability = defineAbility(() => {}); | ||
const routeComponents = () => { | ||
return [ | ||
{ | ||
path: '*', | ||
element: <ContainerForExtensionsMicro />, | ||
}, | ||
]; | ||
}; | ||
|
||
/** | ||
* Note that QueryClientProvider and ReactQueryDevTools | ||
* are React Qery, now branded under the Tanstack packages. | ||
* https://tanstack.com/query/latest | ||
*/ | ||
const layout = () => { | ||
return ( | ||
<div className="cds--white"> | ||
<QueryClientProvider client={queryClient}> | ||
<APIErrorProvider> | ||
<AbilityContext.Provider value={ability}> | ||
<Outlet /> | ||
<ReactQueryDevtools initialIsOpen={false} /> | ||
</AbilityContext.Provider> | ||
</APIErrorProvider> | ||
</QueryClientProvider> | ||
</div> | ||
); | ||
}; | ||
const router = createBrowserRouter([ | ||
{ | ||
path: '*', | ||
Component: layout, | ||
children: routeComponents(), | ||
}, | ||
], | ||
{ | ||
basename: BASENAME_URL | ||
} | ||
); | ||
return <RouterProvider router={router} />; | ||
} |
161 changes: 161 additions & 0 deletions
161
spiffworkflow-frontend/src/ContainerForExtensionsMicro.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import { Content } from '@carbon/react'; | ||
import { Routes, Route, useLocation } from 'react-router-dom'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { ErrorBoundary } from 'react-error-boundary'; | ||
|
||
import ScrollToTop from './components/ScrollToTop'; | ||
import EditorRoutes from './routes/EditorRoutes'; | ||
import Extension from './routes/Extension'; | ||
import { useUriListForPermissions } from './hooks/UriListForPermissions'; | ||
import { PermissionsToCheck, ProcessFile, ProcessModel } from './interfaces'; | ||
import { usePermissionFetcher } from './hooks/PermissionService'; | ||
import { | ||
ExtensionUiSchema, | ||
UiSchemaUxElement, | ||
} from './extension_ui_schema_interfaces'; | ||
import HttpService from './services/HttpService'; | ||
import { ErrorBoundaryFallback } from './ErrorBoundaryFallack'; | ||
import BaseRoutes from './routes/BaseRoutes'; | ||
import BaseRoutesMicro from './routes/BaseRoutesMicro'; | ||
import BackendIsDown from './routes/BackendIsDown'; | ||
import Login from './routes/Login'; | ||
import NavigationBar from './components/NavigationBar'; | ||
import useAPIError from './hooks/UseApiError'; | ||
|
||
export default function ContainerForExtensionsMicro() { | ||
const [backendIsUp, setBackendIsUp] = useState<boolean | null>(null); | ||
const [extensionUxElements, setExtensionUxElements] = useState< | ||
UiSchemaUxElement[] | null | ||
>(null); | ||
|
||
let contentClassName = 'main-site-body-centered'; | ||
if (window.location.pathname.startsWith('/editor/')) { | ||
contentClassName = 'no-center-stuff'; | ||
} | ||
const { targetUris } = useUriListForPermissions(); | ||
const permissionRequestData: PermissionsToCheck = { | ||
[targetUris.extensionListPath]: ['GET'], | ||
}; | ||
const { ability, permissionsLoaded } = usePermissionFetcher( | ||
permissionRequestData, | ||
); | ||
|
||
const { removeError } = useAPIError(); | ||
|
||
const location = useLocation(); | ||
|
||
// never carry an error message across to a different path | ||
useEffect(() => { | ||
removeError(); | ||
// if we include the removeError function to the dependency array of this useEffect, it causes | ||
// an infinite loop where the page with the error adds the error, | ||
// then this runs and it removes the error, etc. it is ok not to include it here, i think, because it never changes. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [location.pathname]); | ||
|
||
// eslint-disable-next-line sonarjs/cognitive-complexity | ||
useEffect(() => { | ||
const processExtensionResult = (processModels: ProcessModel[]) => { | ||
const eni: UiSchemaUxElement[] = processModels | ||
.map((processModel: ProcessModel) => { | ||
const extensionUiSchemaFile = processModel.files.find( | ||
(file: ProcessFile) => file.name === 'extension_uischema.json', | ||
); | ||
if (extensionUiSchemaFile && extensionUiSchemaFile.file_contents) { | ||
try { | ||
const extensionUiSchema: ExtensionUiSchema = JSON.parse( | ||
extensionUiSchemaFile.file_contents, | ||
); | ||
if ( | ||
extensionUiSchema && | ||
extensionUiSchema.ux_elements && | ||
!extensionUiSchema.disabled | ||
) { | ||
return extensionUiSchema.ux_elements; | ||
} | ||
} catch (jsonParseError: any) { | ||
console.error( | ||
`Unable to get navigation items for ${processModel.id}`, | ||
); | ||
} | ||
} | ||
return [] as UiSchemaUxElement[]; | ||
}) | ||
.flat(); | ||
if (eni) { | ||
setExtensionUxElements(eni); | ||
} | ||
}; | ||
|
||
const getExtensions = () => { | ||
setBackendIsUp(true); | ||
if (!permissionsLoaded) { | ||
return; | ||
} | ||
if (ability.can('GET', targetUris.extensionListPath)) { | ||
HttpService.makeCallToBackend({ | ||
path: targetUris.extensionListPath, | ||
successCallback: processExtensionResult, | ||
}); | ||
} else { | ||
// set to an empty array so we know that it loaded | ||
setExtensionUxElements([]); | ||
} | ||
}; | ||
|
||
HttpService.makeCallToBackend({ | ||
path: targetUris.statusPath, | ||
successCallback: getExtensions, | ||
failureCallback: () => setBackendIsUp(false), | ||
}); | ||
}, [ | ||
targetUris.extensionListPath, | ||
targetUris.statusPath, | ||
permissionsLoaded, | ||
ability, | ||
]); | ||
|
||
const routeComponents = () => { | ||
return ( | ||
<Routes> | ||
<Route | ||
path="*" | ||
element={<BaseRoutesMicro extensionUxElements={extensionUxElements} />} | ||
/> | ||
<Route path="editor/*" element={<EditorRoutes />} /> | ||
<Route path="extensions/:page_identifier" element={<Extension />} /> | ||
<Route path="login" element={<Login />} /> | ||
</Routes> | ||
); | ||
}; | ||
|
||
const backendIsDownPage = () => { | ||
return [<BackendIsDown />]; | ||
}; | ||
|
||
const innerComponents = () => { | ||
if (backendIsUp === null) { | ||
return []; | ||
} | ||
if (backendIsUp) { | ||
return routeComponents(); | ||
} | ||
return backendIsDownPage(); | ||
}; | ||
|
||
return ( | ||
<> | ||
{/* TODO : remove this NavigationBar when we have a new navigation system */} | ||
<div className="hidden"> | ||
<NavigationBar extensionUxElements={extensionUxElements} /> | ||
</div> | ||
|
||
<Content className={contentClassName}> | ||
<ScrollToTop /> | ||
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}> | ||
{innerComponents()} | ||
</ErrorBoundary> | ||
</Content> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.