1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-22 01:16:07 +02:00

feat: Project meta widget (#2995)

This commit is contained in:
Tymoteusz Czech 2023-01-27 13:00:23 +01:00 committed by GitHub
parent a482ccff63
commit b27ca26770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 62 deletions

View File

@ -17,7 +17,8 @@ export const StyledColumn = styled('div')(() => ({
flexDirection: 'column', flexDirection: 'column',
})); }));
export const StyledName = styled('div')(() => ({ export const StyledName = styled('h1')(({ theme }) => ({
fontSize: theme.typography.h1.fontSize,
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',

View File

@ -186,33 +186,41 @@ export const Project = () => {
</PermissionIconButton> </PermissionIconButton>
</StyledDiv> </StyledDiv>
</StyledTopRow> </StyledTopRow>
<StyledColumn> <ConditionallyRender
<StyledProjectTitle> condition={!uiConfig?.flags?.newProjectOverview}
<div> // TODO: !!! Remove entire block when removing feature flag!
<ConditionallyRender show={
condition={Boolean(project.description)} <StyledColumn>
show={ <StyledProjectTitle>
<div>
<ConditionallyRender
condition={Boolean(
project.description
)}
show={
<StyledDiv>
<StyledTitle data-loading>
Description:{' '}
</StyledTitle>
<StyledText data-loading>
{project.description}
</StyledText>
</StyledDiv>
}
/>
<StyledDiv> <StyledDiv>
<StyledTitle data-loading> <StyledTitle data-loading>
Description:&nbsp; projectId:{' '}
</StyledTitle> </StyledTitle>
<StyledText data-loading> <StyledText data-loading>
{project.description} {projectId}
</StyledText> </StyledText>
</StyledDiv> </StyledDiv>
} </div>
/> </StyledProjectTitle>
<StyledDiv> </StyledColumn>
<StyledTitle data-loading> }
projectId:&nbsp; />
</StyledTitle>
<StyledText data-loading>
{projectId}
</StyledText>
</StyledDiv>
</div>
</StyledProjectTitle>
</StyledColumn>
</StyledInnerContainer> </StyledInnerContainer>
<StyledSeparator /> <StyledSeparator />

View File

@ -1,11 +1,11 @@
import { import {
StyledArrowIcon, StyledArrowIcon,
StyledCount, StyledCount,
StyledDivInfoContainer, StyledProjectInfoWidgetContainer,
StyledDivPercentageContainer, StyledDivPercentageContainer,
StyledLink, StyledLink,
StyledParagraphEmphasizedText, StyledParagraphEmphasizedText,
StyledParagraphSubtitle, StyledWidgetTitle,
StyledSpanLinkText, StyledSpanLinkText,
} from './ProjectInfo.styles'; } from './ProjectInfo.styles';
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle'; import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
@ -35,10 +35,10 @@ export const HealthWidget = ({
if (uiConfig?.flags?.newProjectOverview) { if (uiConfig?.flags?.newProjectOverview) {
return ( return (
<StyledDivInfoContainer> <StyledProjectInfoWidgetContainer>
<StyledParagraphSubtitle data-loading> <StyledWidgetTitle data-loading>
Project health Project health
</StyledParagraphSubtitle> </StyledWidgetTitle>
<StyledDivPercentageContainer> <StyledDivPercentageContainer>
<PercentageCircle percentage={health} /> <PercentageCircle percentage={health} />
</StyledDivPercentageContainer> </StyledDivPercentageContainer>
@ -63,18 +63,18 @@ export const HealthWidget = ({
View project health View project health
</StyledSpanLinkText> </StyledSpanLinkText>
</StyledLink> </StyledLink>
</StyledDivInfoContainer> </StyledProjectInfoWidgetContainer>
); );
} }
return ( return (
<StyledDivInfoContainer> <StyledProjectInfoWidgetContainer>
<StyledDivPercentageContainer> <StyledDivPercentageContainer>
<PercentageCircle percentage={health} /> <PercentageCircle percentage={health} />
</StyledDivPercentageContainer> </StyledDivPercentageContainer>
<StyledParagraphSubtitle data-loading> <StyledWidgetTitle data-loading>
Overall health rating Overall health rating
</StyledParagraphSubtitle> </StyledWidgetTitle>
<StyledParagraphEmphasizedText data-loading> <StyledParagraphEmphasizedText data-loading>
{health}% {health}%
</StyledParagraphEmphasizedText> </StyledParagraphEmphasizedText>
@ -82,6 +82,6 @@ export const HealthWidget = ({
<StyledSpanLinkText data-loading>view more </StyledSpanLinkText> <StyledSpanLinkText data-loading>view more </StyledSpanLinkText>
<StyledArrowIcon data-loading /> <StyledArrowIcon data-loading />
</StyledLink> </StyledLink>
</StyledDivInfoContainer> </StyledProjectInfoWidgetContainer>
); );
}; };

View File

@ -0,0 +1,69 @@
import { FC } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { Box, styled, Typography, Link } from '@mui/material';
import {
StyledProjectInfoWidgetContainer,
StyledWidgetTitle,
} from './ProjectInfo.styles';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
interface IMetaWidgetProps {
id?: string;
description?: string;
}
const StyledIDContainer = styled('div')(({ theme }) => ({
textAlign: 'left',
borderRadius: `${theme.shape.borderRadius}px`,
backgroundColor: `${theme.palette.secondaryContainer}`,
padding: theme.spacing(0.5, 2),
fontSize: theme.typography.body2.fontSize,
}));
export const MetaWidget: FC<IMetaWidgetProps> = ({ id, description }) => {
return (
<StyledProjectInfoWidgetContainer>
<StyledWidgetTitle>Project Meta</StyledWidgetTitle>
<StyledIDContainer>
<Typography
component="span"
variant="body2"
color="text.secondary"
>
ID:
</Typography>{' '}
<code data-loading>{id || '__________'}</code>
</StyledIDContainer>
<Typography mt={1.5} textAlign="left">
<ConditionallyRender
condition={Boolean(description)}
show={
<>
<Typography
component="span"
variant="body2"
color="text.secondary"
>
Description:{' '}
</Typography>
<Typography component="span" variant="body2">
{description}
</Typography>
</>
}
elseShow={
<Typography variant="body2" textAlign="center">
<Link
component={RouterLink}
to={`/projects/${id}/edit`}
>
Add description
</Link>
</Typography>
}
/>
</Typography>
</StyledProjectInfoWidgetContainer>
);
};

View File

@ -3,10 +3,11 @@ import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { flexRow } from 'themes/themeStyles'; import { flexRow } from 'themes/themeStyles';
import { styled } from '@mui/material'; import { styled } from '@mui/material';
export const StyledDivContainer = styled('div')(({ theme }) => ({ export const StyledProjectInfoSidebarContainer = styled('div')(({ theme }) => ({
...flexRow, ...flexRow,
width: '225px', width: '225px',
flexDirection: 'column', flexDirection: 'column',
gap: theme.spacing(2),
boxShadow: 'none', boxShadow: 'none',
[theme.breakpoints.down('md')]: { [theme.breakpoints.down('md')]: {
flexDirection: 'row', flexDirection: 'row',
@ -22,10 +23,9 @@ export const StyledDivPercentageContainer = styled('div')(({ theme }) => ({
margin: theme.spacing(2, 0), margin: theme.spacing(2, 0),
})); }));
export const StyledDivInfoContainer = styled('div')(({ theme }) => ({ export const StyledProjectInfoWidgetContainer = styled('div')(({ theme }) => ({
margin: '0', margin: '0',
textAlign: 'center', textAlign: 'center',
marginBottom: theme.spacing(2),
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadiusLarge, borderRadius: theme.shape.borderRadiusLarge,
width: '100%', width: '100%',
@ -47,7 +47,7 @@ export const StyledDivInfoContainer = styled('div')(({ theme }) => ({
}, },
})); }));
export const StyledParagraphSubtitle = styled('p')(({ theme }) => ({ export const StyledWidgetTitle = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
})); }));

View File

@ -1,10 +1,10 @@
import type { IFeatureToggleListItem } from 'interfaces/featureToggle';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { DEFAULT_PROJECT_ID } from 'hooks/api/getters/useDefaultProject/useDefaultProjectId'; import { DEFAULT_PROJECT_ID } from 'hooks/api/getters/useDefaultProject/useDefaultProjectId';
import { StyledDivContainer } from './ProjectInfo.styles'; import { StyledProjectInfoSidebarContainer } from './ProjectInfo.styles';
import { IFeatureToggleListItem } from '../../../../interfaces/featureToggle';
import { HealthWidget } from './HealthWidget'; import { HealthWidget } from './HealthWidget';
import { ToggleTypesWidget } from './ToggleTypesWidget'; import { ToggleTypesWidget } from './ToggleTypesWidget';
import { MetaWidget } from './MetaWidget';
import { ProjectMembersWidget } from './ProjectMembersWidget'; import { ProjectMembersWidget } from './ProjectMembersWidget';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
@ -18,6 +18,7 @@ interface IProjectInfoProps {
const ProjectInfo = ({ const ProjectInfo = ({
id, id,
description,
memberCount, memberCount,
health, health,
features, features,
@ -25,7 +26,11 @@ const ProjectInfo = ({
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
return ( return (
<aside> <aside>
<StyledDivContainer> <StyledProjectInfoSidebarContainer>
<ConditionallyRender
condition={Boolean(uiConfig?.flags.newProjectOverview)}
show={<MetaWidget id={id} description={description} />}
/>
<HealthWidget <HealthWidget
projectId={id} projectId={id}
health={health} health={health}
@ -41,11 +46,8 @@ const ProjectInfo = ({
/> />
} }
/> />
<ConditionallyRender <ToggleTypesWidget features={features} />
condition={Boolean(uiConfig?.flags.newProjectOverview)} </StyledProjectInfoSidebarContainer>
show={<ToggleTypesWidget features={features} />}
/>
</StyledDivContainer>
</aside> </aside>
); );
}; };

View File

@ -1,9 +1,9 @@
import { import {
StyledArrowIcon, StyledArrowIcon,
StyledDivInfoContainer, StyledProjectInfoWidgetContainer,
StyledLink, StyledLink,
StyledParagraphEmphasizedText, StyledParagraphEmphasizedText,
StyledParagraphSubtitle, StyledWidgetTitle,
StyledSpanLinkText, StyledSpanLinkText,
} from './ProjectInfo.styles'; } from './ProjectInfo.styles';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
@ -26,10 +26,8 @@ export const ProjectMembersWidget = ({
} }
return ( return (
<StyledDivInfoContainer> <StyledProjectInfoWidgetContainer>
<StyledParagraphSubtitle data-loading> <StyledWidgetTitle data-loading>Project members</StyledWidgetTitle>
Project members
</StyledParagraphSubtitle>
<StyledParagraphEmphasizedText data-loading> <StyledParagraphEmphasizedText data-loading>
{memberCount} {memberCount}
</StyledParagraphEmphasizedText> </StyledParagraphEmphasizedText>
@ -37,6 +35,6 @@ export const ProjectMembersWidget = ({
<StyledSpanLinkText data-loading>view more </StyledSpanLinkText> <StyledSpanLinkText data-loading>view more </StyledSpanLinkText>
<StyledArrowIcon data-loading /> <StyledArrowIcon data-loading />
</StyledLink> </StyledLink>
</StyledDivInfoContainer> </StyledProjectInfoWidgetContainer>
); );
}; };

View File

@ -1,19 +1,19 @@
import { IFeatureToggleListItem } from '../../../../interfaces/featureToggle';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { styled } from '@mui/material';
import type { IFeatureToggleListItem } from 'interfaces/featureToggle';
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
import { import {
StyledCount, StyledCount,
StyledDivInfoContainer, StyledProjectInfoWidgetContainer,
StyledParagraphGridRow, StyledParagraphGridRow,
StyledParagraphSubtitle, StyledWidgetTitle,
} from './ProjectInfo.styles'; } from './ProjectInfo.styles';
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
import { styled } from '@mui/material';
export interface IToggleTypesWidgetProps { export interface IToggleTypesWidgetProps {
features: IFeatureToggleListItem[]; features: IFeatureToggleListItem[];
} }
const StyledTypeCount = styled(StyledCount)(({ theme }) => ({ const StyledTypeCount = styled(StyledCount)(() => ({
marginLeft: 'auto', marginLeft: 'auto',
})); }));
@ -52,10 +52,10 @@ export const ToggleTypesWidget = ({ features }: IToggleTypesWidgetProps) => {
const PermissionToggleIcon = getFeatureTypeIcons('permission'); const PermissionToggleIcon = getFeatureTypeIcons('permission');
return ( return (
<StyledDivInfoContainer> <StyledProjectInfoWidgetContainer>
<StyledParagraphSubtitle data-loading> <StyledWidgetTitle data-loading>
Toggle types used Toggle types used
</StyledParagraphSubtitle> </StyledWidgetTitle>
<StyledParagraphGridRow data-loading> <StyledParagraphGridRow data-loading>
<ReleaseToggleIcon fontSize="small" data-loading /> <ReleaseToggleIcon fontSize="small" data-loading />
<div>Release</div> <div>Release</div>
@ -81,6 +81,6 @@ export const ToggleTypesWidget = ({ features }: IToggleTypesWidgetProps) => {
<div>Permission</div> <div>Permission</div>
<StyledTypeCount>{permission}</StyledTypeCount> <StyledTypeCount>{permission}</StyledTypeCount>
</StyledParagraphGridRow> </StyledParagraphGridRow>
</StyledDivInfoContainer> </StyledProjectInfoWidgetContainer>
); );
}; };