mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-06 01:15:28 +02:00
Maintenance mode UI (#2704)
This commit is contained in:
parent
5bef9bbfdd
commit
d42e90544f
@ -19,6 +19,7 @@ import { useStyles } from './App.styles';
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import useProjects from '../hooks/api/getters/useProjects/useProjects';
|
import useProjects from '../hooks/api/getters/useProjects/useProjects';
|
||||||
import { useLastViewedProject } from '../hooks/useLastViewedProject';
|
import { useLastViewedProject } from '../hooks/useLastViewedProject';
|
||||||
|
import Maintenance from './maintenance/Maintenance';
|
||||||
|
|
||||||
const InitialRedirect = () => {
|
const InitialRedirect = () => {
|
||||||
const { lastViewed } = useLastViewedProject();
|
const { lastViewed } = useLastViewedProject();
|
||||||
@ -57,7 +58,7 @@ export const App = () => {
|
|||||||
const hasFetchedAuth = Boolean(authDetails || user);
|
const hasFetchedAuth = Boolean(authDetails || user);
|
||||||
|
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const { isOss } = useUiConfig();
|
const { isOss, uiConfig } = useUiConfig();
|
||||||
|
|
||||||
const availableRoutes = isOss()
|
const availableRoutes = isOss()
|
||||||
? routes.filter(route => !route.enterprise)
|
? routes.filter(route => !route.enterprise)
|
||||||
@ -73,6 +74,12 @@ export const App = () => {
|
|||||||
show={<Loader />}
|
show={<Loader />}
|
||||||
elseShow={
|
elseShow={
|
||||||
<>
|
<>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(
|
||||||
|
uiConfig?.flags?.maintenance
|
||||||
|
)}
|
||||||
|
show={<Maintenance />}
|
||||||
|
/>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<ToastRenderer />
|
<ToastRenderer />
|
||||||
<Routes>
|
<Routes>
|
||||||
|
35
frontend/src/component/maintenance/Maintenance.tsx
Normal file
35
frontend/src/component/maintenance/Maintenance.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { styled } from '@mui/material';
|
||||||
|
import { ErrorOutlineRounded } from '@mui/icons-material';
|
||||||
|
|
||||||
|
const StyledErrorRoundedIcon = styled(ErrorOutlineRounded)(({ theme }) => ({
|
||||||
|
height: '20px',
|
||||||
|
width: '20px',
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledDiv = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: theme.palette.error.main,
|
||||||
|
backgroundColor: theme.palette.error.light,
|
||||||
|
height: '65px',
|
||||||
|
borderBottom: `1px solid ${theme.palette.error.border}`,
|
||||||
|
whiteSpace: 'pre-wrap',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Maintenance = () => {
|
||||||
|
return (
|
||||||
|
<StyledDiv>
|
||||||
|
<StyledErrorRoundedIcon />
|
||||||
|
<b>Maintenance Mode! </b>
|
||||||
|
<p>
|
||||||
|
Any changes you make during maintenance mode will not be saved.
|
||||||
|
We apologize for any inconvenience this may cause.
|
||||||
|
</p>
|
||||||
|
</StyledDiv>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Maintenance;
|
@ -42,7 +42,7 @@ export interface IAuthSplash {
|
|||||||
[key: string]: boolean;
|
[key: string]: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IUseAuthEndpointOutput {
|
export interface IUseAuthEndpointOutput {
|
||||||
data?: AuthEndpointResponse;
|
data?: AuthEndpointResponse;
|
||||||
refetchAuth: () => void;
|
refetchAuth: () => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { IPermission } from 'interfaces/user';
|
import { IPermission } from 'interfaces/user';
|
||||||
import { useAuthEndpoint } from './useAuthEndpoint';
|
import { IUseAuthEndpointOutput, useAuthEndpoint } from './useAuthEndpoint';
|
||||||
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import { IUiConfig } from 'interfaces/uiConfig';
|
||||||
|
|
||||||
interface IUseAuthPermissionsOutput {
|
interface IUseAuthPermissionsOutput {
|
||||||
permissions?: IPermission[];
|
permissions?: IPermission[];
|
||||||
@ -8,13 +10,23 @@ interface IUseAuthPermissionsOutput {
|
|||||||
error?: Error;
|
error?: Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAuthPermissions = (): IUseAuthPermissionsOutput => {
|
const getPermissions = (
|
||||||
const auth = useAuthEndpoint();
|
auth: IUseAuthEndpointOutput,
|
||||||
const permissions =
|
uiConfig: IUiConfig
|
||||||
auth.data && 'permissions' in auth.data
|
): IPermission[] | undefined => {
|
||||||
|
let permissions =
|
||||||
|
auth.data && 'permissions' in auth.data && !uiConfig?.flags?.maintenance
|
||||||
? auth.data.permissions
|
? auth.data.permissions
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAuthPermissions = (): IUseAuthPermissionsOutput => {
|
||||||
|
const auth = useAuthEndpoint();
|
||||||
|
const { uiConfig } = useUiConfig();
|
||||||
|
const permissions = getPermissions(auth, uiConfig);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
permissions,
|
permissions,
|
||||||
refetchPermissions: auth.refetchAuth,
|
refetchPermissions: auth.refetchAuth,
|
||||||
|
@ -44,6 +44,7 @@ export interface IFlags {
|
|||||||
variantsPerEnvironment?: boolean;
|
variantsPerEnvironment?: boolean;
|
||||||
favorites?: boolean;
|
favorites?: boolean;
|
||||||
networkView?: boolean;
|
networkView?: boolean;
|
||||||
|
maintenance?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
|
@ -74,6 +74,7 @@ exports[`should create default config 1`] = `
|
|||||||
"embedProxy": true,
|
"embedProxy": true,
|
||||||
"embedProxyFrontend": true,
|
"embedProxyFrontend": true,
|
||||||
"favorites": false,
|
"favorites": false,
|
||||||
|
"maintenance": false,
|
||||||
"networkView": false,
|
"networkView": false,
|
||||||
"proxyReturnAllToggles": false,
|
"proxyReturnAllToggles": false,
|
||||||
"responseTimeWithAppName": false,
|
"responseTimeWithAppName": false,
|
||||||
@ -89,6 +90,7 @@ exports[`should create default config 1`] = `
|
|||||||
"embedProxy": true,
|
"embedProxy": true,
|
||||||
"embedProxyFrontend": true,
|
"embedProxyFrontend": true,
|
||||||
"favorites": false,
|
"favorites": false,
|
||||||
|
"maintenance": false,
|
||||||
"networkView": false,
|
"networkView": false,
|
||||||
"proxyReturnAllToggles": false,
|
"proxyReturnAllToggles": false,
|
||||||
"responseTimeWithAppName": false,
|
"responseTimeWithAppName": false,
|
||||||
|
@ -38,6 +38,10 @@ export const defaultExperimentalOptions = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_FAVORITES,
|
process.env.UNLEASH_EXPERIMENTAL_FAVORITES,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
maintenance: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_MAINTENANCE,
|
||||||
|
false,
|
||||||
|
),
|
||||||
networkView: parseEnvVarBoolean(
|
networkView: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_NETWORK_VIEW,
|
process.env.UNLEASH_EXPERIMENTAL_NETWORK_VIEW,
|
||||||
false,
|
false,
|
||||||
@ -59,6 +63,7 @@ export interface IExperimentalOptions {
|
|||||||
variantsPerEnvironment?: boolean;
|
variantsPerEnvironment?: boolean;
|
||||||
favorites?: boolean;
|
favorites?: boolean;
|
||||||
networkView?: boolean;
|
networkView?: boolean;
|
||||||
|
maintenance?: boolean;
|
||||||
};
|
};
|
||||||
externalResolver: IExternalFlagResolver;
|
externalResolver: IExternalFlagResolver;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ process.nextTick(async () => {
|
|||||||
changeRequests: true,
|
changeRequests: true,
|
||||||
favorites: true,
|
favorites: true,
|
||||||
variantsPerEnvironment: true,
|
variantsPerEnvironment: true,
|
||||||
|
maintenance: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authentication: {
|
authentication: {
|
||||||
|
Loading…
Reference in New Issue
Block a user