spiff-arena/spiffworkflow-frontend/src/ContainerForExtensions.tsx
2024-02-16 12:05:16 -05:00

151 lines
4.6 KiB
TypeScript

import { Content } from '@carbon/react';
import { createBrowserRouter, RouterProvider, Outlet } 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 BackendIsDown from './routes/BackendIsDown';
import Login from './routes/Login';
import NavigationBar from './components/NavigationBar';
export default function ContainerForExtensions() {
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
);
// 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.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 [
{
path: '*',
element: <BaseRoutes extensionUxElements={extensionUxElements} />,
},
{ path: 'editor/*', element: <EditorRoutes /> },
{ path: 'extensions/:page_identifier', element: <Extension /> },
{ path: 'login', element: <Login /> },
];
};
const backendIsDownPage = () => {
return [<BackendIsDown />];
};
const innerComponents = () => {
if (backendIsUp === null) {
return [];
}
if (backendIsUp) {
return <Outlet />;
}
return backendIsDownPage();
};
const layout = () => {
return (
<>
<NavigationBar extensionUxElements={extensionUxElements} />
<Content className={contentClassName}>
<ScrollToTop />
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
{innerComponents()}
</ErrorBoundary>
</Content>
</>
);
};
const router = createBrowserRouter([
{
path: '*',
Component: layout,
children: routeComponents(),
},
]);
return <RouterProvider router={router} />;
}