Skip to content

Commit

Permalink
Update Existing Navigation
Browse files Browse the repository at this point in the history
- Added global config
- Created Navigation Component to consume config

Features:
- Configuration and future shared pages will use server navigation if only one server is active
- Canonicalized showing navigation based on authorization level and export type. Easy to add future updates.
  • Loading branch information
CannonLock committed Dec 9, 2024
1 parent 1f190a1 commit 0ae9ead
Show file tree
Hide file tree
Showing 22 changed files with 621 additions and 303 deletions.
20 changes: 4 additions & 16 deletions web_ui/frontend/app/cache/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@
*
***************************************************************/

import { Box, Tooltip } from '@mui/material';
import { Box } from '@mui/material';

import { ButtonLink, Sidebar } from '@/components/layout/Sidebar';
import Link from 'next/link';
import Image from 'next/image';
import PelicanLogo from '@/public/static/images/PelicanPlatformLogo_Icon.png';
import IconButton from '@mui/material/IconButton';
import BuildIcon from '@mui/icons-material/Build';
import Main from '@/components/layout/Main';
import { PaddedContent } from '@/components/layout';
import { Dashboard, MapOutlined } from '@mui/icons-material';
import { Navigation } from '@/components/layout/Navigation';
import NavigationConfiguration from '@/app/navigation';

export const metadata = {
title: 'Pelican Cache',
Expand All @@ -40,14 +35,7 @@ export default function RootLayout({
}) {
return (
<Box display={'flex'} flexDirection={'row'}>
<Sidebar>
<ButtonLink title={'Cache'} href={'/cache/'}>
<Dashboard />
</ButtonLink>
<ButtonLink title={'Config'} href={'/config/'}>
<BuildIcon />
</ButtonLink>
</Sidebar>
<Navigation config={NavigationConfiguration['cache']} />
<Main>
<PaddedContent>{children}</PaddedContent>
</Main>
Expand Down
198 changes: 77 additions & 121 deletions web_ui/frontend/app/config/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import {
import useSWR from 'swr';
import { merge, isMatch, isEqual } from 'lodash';
import * as yaml from 'js-yaml';
import { ButtonLink, Sidebar } from '@/components/layout/Sidebar';
import { Main } from '@/components/layout/Main';
import { submitConfigChange } from '@/components/configuration/util';
import {
Expand Down Expand Up @@ -79,13 +78,6 @@ function Config({ metadata }: { metadata: ParameterMetadataRecord }) {
async () =>
await alertOnError(getConfigJson, 'Could not get config', dispatch)
);
const { data: enabledServers } = useSWR<ServerType[]>(
'getEnabledServers',
getEnabledServers,
{
fallbackData: ['origin', 'registry', 'director', 'cache'],
}
);

const serverConfig = useMemo(() => {
return flattenObject(data || {});
Expand All @@ -107,121 +99,85 @@ function Config({ metadata }: { metadata: ParameterMetadataRecord }) {
}, [serverConfig, patch]);

return (
<>
<Sidebar>
{enabledServers && enabledServers.includes('origin') && (
<ButtonLink title={'Origin'} href={'/origin/'}>
<TripOrigin />
</ButtonLink>
)}
{enabledServers && enabledServers.includes('director') && (
<ButtonLink title={'Director'} href={'/director/'}>
<AssistantDirection />
</ButtonLink>
)}
{enabledServers && enabledServers.includes('registry') && (
<ButtonLink title={'Registry'} href={'/registry/'}>
<AppRegistration />
</ButtonLink>
)}
{enabledServers && enabledServers.includes('cache') && (
<ButtonLink title={'Cache'} href={'/cache/'}>
<Cached />
</ButtonLink>
)}
</Sidebar>
<Main>
<PaddedContent>
<AuthenticatedContent redirect={true} trustThenValidate={true}>
<Box display={'flex'} flexDirection={'row'}>
<Typography variant={'h4'} component={'h2'} mb={1}>
Configuration
{serverConfig && (
<Box ml={2} display={'inline'}>
<DownloadButton
Button={IconButton}
mimeType={'text/yaml'}
data={yaml.dump(stripNulls(structuredClone(data)))}
>
<Download />
</DownloadButton>
</Box>
)}
</Typography>
<AuthenticatedContent redirect={true} trustThenValidate={true}>
<Box display={'flex'} flexDirection={'row'}>
<Typography variant={'h4'} component={'h2'} mb={1}>
Configuration
{serverConfig && (
<Box ml={2} display={'inline'}>
<DownloadButton
Button={IconButton}
mimeType={'text/yaml'}
data={yaml.dump(stripNulls(structuredClone(data)))}
>
<Download />
</DownloadButton>
</Box>
<Grid container spacing={2}>
<Grid item xs={12} md={8} lg={6}>
<Box>
{error && (
<Alert severity={'warning'}>
{(error as Error).message}
</Alert>
)}
</Box>
<ConfigDisplay
config={serverConfig}
patch={patch}
metadata={metadata}
onChange={setPatch}
/>
<Snackbar
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
open={updatesPending}
message='Save Changes'
action={
<Box>
<Button
onClick={async () => {
try {
await submitConfigChange(patch);
setStatus({
message: 'Changes Saved, Restarting Server',
});
)}
</Typography>
</Box>
<Grid container spacing={2}>
<Grid item xs={12} md={8} lg={6}>
<Box>
{error && (
<Alert severity={'warning'}>{(error as Error).message}</Alert>
)}
</Box>
<ConfigDisplay
config={serverConfig}
patch={patch}
metadata={metadata}
onChange={setPatch}
/>
<Snackbar
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
open={updatesPending}
message='Save Changes'
action={
<Box>
<Button
onClick={async () => {
try {
await submitConfigChange(patch);
setStatus({
message: 'Changes Saved, Restarting Server',
});

// Refresh the page after 3 seconds
setTimeout(() => {
mutate();
setStatus(undefined);
_setPatch({});
}, 3000);
} catch (e) {
setStatus({
severity: 'error',
message: (e as string).toString(),
});
}
}}
>
Save
</Button>
<Button
onClick={() => {
_setPatch({});
}}
>
Clear
</Button>
</Box>
}
/>
{status && <StatusSnackBar key={status.message} {...status} />}
</Grid>
<Grid
item
xs={12}
md={4}
lg={3}
display={{ xs: 'none', md: 'block' }}
>
<Box pt={2}>
<TableOfContents metadata={metadata} />
</Box>
</Grid>
</Grid>
</AuthenticatedContent>
</PaddedContent>
</Main>
</>
// Refresh the page after 3 seconds
setTimeout(() => {
mutate();
setStatus(undefined);
_setPatch({});
}, 3000);
} catch (e) {
setStatus({
severity: 'error',
message: (e as string).toString(),
});
}
}}
>
Save
</Button>
<Button
onClick={() => {
_setPatch({});
}}
>
Clear
</Button>
</Box>
}
/>
{status && <StatusSnackBar key={status.message} {...status} />}
</Grid>
<Grid item xs={12} md={4} lg={3} display={{ xs: 'none', md: 'block' }}>
<Box pt={2}>
<TableOfContents metadata={metadata} />
</Box>
</Grid>
</Grid>
</AuthenticatedContent>
);
}

Expand Down
7 changes: 6 additions & 1 deletion web_ui/frontend/app/config/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
***************************************************************/

import { Box } from '@mui/material';
import { PaddedContent, Main } from '@/components/layout';
import { Navigation } from '@/components/layout/Navigation';

export const metadata = {
title: 'Pelican Configuration',
Expand All @@ -30,7 +32,10 @@ export default function RootLayout({
}) {
return (
<Box display={'flex'} flexDirection={'row'}>
{children}
<Navigation sharedPage={true} />
<Main>
<PaddedContent>{children}</PaddedContent>
</Main>
</Box>
);
}
20 changes: 3 additions & 17 deletions web_ui/frontend/app/director/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
***************************************************************/

import { Box } from '@mui/material';
import { ButtonLink, Sidebar } from '@/components/layout/Sidebar';
import BuildIcon from '@mui/icons-material/Build';
import Main from '@/components/layout/Main';
import { Dashboard, Equalizer, MapOutlined } from '@mui/icons-material';
import { Navigation } from '@/components/layout/Navigation';
import NavigationConfiguration from '@/app/navigation';

export const metadata = {
title: 'Pelican Director',
Expand All @@ -34,20 +33,7 @@ export default function RootLayout({
}) {
return (
<Box display={'flex'} flexDirection={'row'}>
<Sidebar>
<ButtonLink title={'Dashboard'} href={'/director/'}>
<Dashboard />
</ButtonLink>
<ButtonLink title={'Metrics'} href={'/director/metrics/'}>
<Equalizer />
</ButtonLink>
<ButtonLink title={'Map'} href={'/director/map/'}>
<MapOutlined />
</ButtonLink>
<ButtonLink title={'Config'} href={'/config/'}>
<BuildIcon />
</ButtonLink>
</Sidebar>
<Navigation config={NavigationConfiguration['director']} />
<Main>{children}</Main>
</Box>
);
Expand Down
1 change: 0 additions & 1 deletion web_ui/frontend/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { LocalizationProvider } from '@/clientComponents';
import { ThemeProviderClient } from '@/components/ThemeProvider';
import { AlertProvider } from '@/components/AlertProvider';
import './globals.css';

export const metadata = {
title: 'Pelican Platform',
description: 'Software designed to make data distribution easy',
Expand Down
Loading

0 comments on commit 0ae9ead

Please sign in to comment.