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:
parent
a482ccff63
commit
b27ca26770
@ -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',
|
||||||
|
@ -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:
|
projectId:{' '}
|
||||||
</StyledTitle>
|
</StyledTitle>
|
||||||
<StyledText data-loading>
|
<StyledText data-loading>
|
||||||
{project.description}
|
{projectId}
|
||||||
</StyledText>
|
</StyledText>
|
||||||
</StyledDiv>
|
</StyledDiv>
|
||||||
}
|
</div>
|
||||||
/>
|
</StyledProjectTitle>
|
||||||
<StyledDiv>
|
</StyledColumn>
|
||||||
<StyledTitle data-loading>
|
}
|
||||||
projectId:
|
/>
|
||||||
</StyledTitle>
|
|
||||||
<StyledText data-loading>
|
|
||||||
{projectId}
|
|
||||||
</StyledText>
|
|
||||||
</StyledDiv>
|
|
||||||
</div>
|
|
||||||
</StyledProjectTitle>
|
|
||||||
</StyledColumn>
|
|
||||||
</StyledInnerContainer>
|
</StyledInnerContainer>
|
||||||
|
|
||||||
<StyledSeparator />
|
<StyledSeparator />
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -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),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user