mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
feat: initial status box implementation (#2913)
First iteration of new status boxes
This commit is contained in:
parent
16bca1260c
commit
bf7ef62059
@ -1,13 +1,17 @@
|
||||
import useProject, {
|
||||
useProjectNameOrId,
|
||||
} from 'hooks/api/getters/useProject/useProject';
|
||||
import { styled } from '@mui/material';
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { ProjectFeatureToggles } from './ProjectFeatureToggles/ProjectFeatureToggles';
|
||||
import ProjectInfo from './ProjectInfo/ProjectInfo';
|
||||
import { usePageTitle } from 'hooks/usePageTitle';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { useLastViewedProject } from '../../../hooks/useLastViewedProject';
|
||||
import { useEffect } from 'react';
|
||||
import { StatusBox } from './ProjectStatus/StatusBox';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { ProjectStatus } from './ProjectStatus/ProjectStatus';
|
||||
|
||||
const refreshInterval = 15 * 1000;
|
||||
|
||||
@ -23,6 +27,12 @@ const StyledProjectToggles = styled('div')(() => ({
|
||||
minWidth: 0,
|
||||
}));
|
||||
|
||||
const StyledContentContainer = styled(Box)(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const ProjectOverview = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const projectName = useProjectNameOrId(projectId);
|
||||
@ -30,6 +40,7 @@ const ProjectOverview = () => {
|
||||
const { members, features, health, description, environments } = project;
|
||||
usePageTitle(`Project overview – ${projectName}`);
|
||||
const { setLastViewed } = useLastViewedProject();
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
useEffect(() => {
|
||||
setLastViewed(projectId);
|
||||
@ -44,13 +55,19 @@ const ProjectOverview = () => {
|
||||
health={health}
|
||||
featureCount={features?.length}
|
||||
/>
|
||||
<StyledProjectToggles>
|
||||
<ProjectFeatureToggles
|
||||
features={features}
|
||||
environments={environments}
|
||||
loading={loading}
|
||||
<StyledContentContainer>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(uiConfig?.flags.newProjectOverview)}
|
||||
show={<ProjectStatus />}
|
||||
/>
|
||||
</StyledProjectToggles>
|
||||
<StyledProjectToggles>
|
||||
<ProjectFeatureToggles
|
||||
features={features}
|
||||
environments={environments}
|
||||
loading={loading}
|
||||
/>
|
||||
</StyledProjectToggles>
|
||||
</StyledContentContainer>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { StatusBox } from './StatusBox';
|
||||
|
||||
const StyledBox = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(0, 0, 2, 2),
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
flexWrap: 'wrap',
|
||||
}));
|
||||
|
||||
export const ProjectStatus = () => {
|
||||
return (
|
||||
<StyledBox>
|
||||
<StatusBox title="Total changes" boxText={'86'} change={-24} />
|
||||
<StatusBox
|
||||
title="Total changes"
|
||||
boxText={'6 days'}
|
||||
change={-12}
|
||||
/>{' '}
|
||||
<StatusBox title="Total changes" boxText={'86'} change={-24} />
|
||||
<StatusBox title="Total changes" boxText={'86'} change={-24} />
|
||||
</StyledBox>
|
||||
);
|
||||
};
|
@ -0,0 +1,85 @@
|
||||
import { ArrowOutward, SouthEast } from '@mui/icons-material';
|
||||
import { Box, Typography, styled } from '@mui/material';
|
||||
import { flexRow } from 'themes/themeStyles';
|
||||
|
||||
const StyledBox = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(4, 2),
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
minWidth: '240px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
borderRadius: `${theme.shape.borderRadiusLarge}px`,
|
||||
}));
|
||||
|
||||
const StyledTypographyHeader = styled(Typography)(({ theme }) => ({
|
||||
marginBottom: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const StyledTypographyCount = styled(Typography)(({ theme }) => ({
|
||||
fontSize: theme.fontSizes.largeHeader,
|
||||
fontWeight: 'bold',
|
||||
}));
|
||||
|
||||
const StyledBoxChangeContainer = styled(Box)(({ theme }) => ({
|
||||
...flexRow,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
marginLeft: theme.spacing(1.5),
|
||||
}));
|
||||
|
||||
const StyledTypographySubtext = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.neutral.main,
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
}));
|
||||
|
||||
const StyledTypographyChange = styled(Typography)(({ theme }) => ({
|
||||
marginLeft: theme.spacing(1),
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
}));
|
||||
|
||||
interface IStatusBoxProps {
|
||||
title: string;
|
||||
boxText: string;
|
||||
change: number;
|
||||
}
|
||||
|
||||
const resolveIcon = (change: number) => {
|
||||
if (change > 0) {
|
||||
return (
|
||||
<ArrowOutward
|
||||
sx={{ color: 'success.main', height: 18, width: 18 }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <SouthEast sx={{ color: 'warning.dark', height: 18, width: 18 }} />;
|
||||
};
|
||||
|
||||
const resolveColor = (change: number) => {
|
||||
if (change > 0) {
|
||||
return 'success.main';
|
||||
}
|
||||
return 'error.main';
|
||||
};
|
||||
|
||||
export const StatusBox = ({ title, boxText, change }: IStatusBoxProps) => {
|
||||
return (
|
||||
<StyledBox>
|
||||
<StyledTypographyHeader>{title}</StyledTypographyHeader>
|
||||
<Box sx={{ ...flexRow }}>
|
||||
<StyledTypographyCount>{boxText}</StyledTypographyCount>
|
||||
<StyledBoxChangeContainer>
|
||||
<Box sx={{ ...flexRow }}>
|
||||
{resolveIcon(change)}
|
||||
<StyledTypographyChange color={resolveColor(change)}>
|
||||
{change}
|
||||
</StyledTypographyChange>
|
||||
</Box>
|
||||
<StyledTypographySubtext>
|
||||
this month
|
||||
</StyledTypographySubtext>
|
||||
</StyledBoxChangeContainer>
|
||||
</Box>
|
||||
</StyledBox>
|
||||
);
|
||||
};
|
@ -45,6 +45,7 @@ export interface IFlags {
|
||||
messageBanner?: boolean;
|
||||
serviceAccounts?: boolean;
|
||||
featuresExportImport?: boolean;
|
||||
newProjectOverview?: boolean;
|
||||
}
|
||||
|
||||
export interface IVersionInfo {
|
||||
|
@ -44,6 +44,7 @@ export default createTheme({
|
||||
},
|
||||
},
|
||||
fontSizes: {
|
||||
largeHeader: '2.25rem',
|
||||
mainHeader: '1.25rem',
|
||||
bodySize: '1rem',
|
||||
smallBody: `${14 / 16}rem`,
|
||||
|
@ -41,6 +41,7 @@ export default createTheme({
|
||||
},
|
||||
},
|
||||
fontSizes: {
|
||||
largeHeader: '2rem',
|
||||
mainHeader: '1.25rem',
|
||||
bodySize: '1rem',
|
||||
smallBody: `${14 / 16}rem`,
|
||||
|
@ -4,6 +4,7 @@ declare module '@mui/material/styles' {
|
||||
* @deprecated
|
||||
*/
|
||||
fontSizes: {
|
||||
largeHeader: string;
|
||||
mainHeader: string;
|
||||
bodySize: string;
|
||||
smallBody: string;
|
||||
|
@ -77,6 +77,7 @@ exports[`should create default config 1`] = `
|
||||
"maintenanceMode": false,
|
||||
"messageBanner": false,
|
||||
"networkView": false,
|
||||
"newProjectOverview": false,
|
||||
"proxyReturnAllToggles": false,
|
||||
"responseTimeWithAppName": false,
|
||||
"serviceAccounts": false,
|
||||
@ -95,6 +96,7 @@ exports[`should create default config 1`] = `
|
||||
"maintenanceMode": false,
|
||||
"messageBanner": false,
|
||||
"networkView": false,
|
||||
"newProjectOverview": false,
|
||||
"proxyReturnAllToggles": false,
|
||||
"responseTimeWithAppName": false,
|
||||
"serviceAccounts": false,
|
||||
|
@ -10,6 +10,10 @@ const flags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_EMBED_PROXY,
|
||||
true,
|
||||
),
|
||||
newProjectOverview: parseEnvVarBoolean(
|
||||
process.env.NEW_PROJECT_OVERVIEW,
|
||||
false,
|
||||
),
|
||||
embedProxyFrontend: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_EMBED_PROXY_FRONTEND,
|
||||
true,
|
||||
|
@ -42,6 +42,7 @@ process.nextTick(async () => {
|
||||
variantsPerEnvironment: true,
|
||||
maintenance: false,
|
||||
featuresExportImport: true,
|
||||
newProjectOverview: true,
|
||||
},
|
||||
},
|
||||
authentication: {
|
||||
|
Loading…
Reference in New Issue
Block a user