From b4e2d5d270ea5a49565a4ff175d264e4572d318b Mon Sep 17 00:00:00 2001
From: Thomas Heartman
Date: Thu, 14 Nov 2024 15:00:32 +0100
Subject: [PATCH] Add close button, fix layout, refactor (#8755)
This PR consists of cleanup for the project status modal as well as
adding the missing button.
I've added inline comments to explain the different steps.
It now looks like this:

---
frontend/src/assets/icons/projectStatus.svg | 2 +-
.../Project/ProjectStatus/ProjectActivity.tsx | 8 -
.../Project/ProjectStatus/ProjectHealth.tsx | 13 +-
.../ProjectHealthGrid.styles.tsx | 7 +
.../ProjectStatus/ProjectHealthGrid.tsx | 57 ++++
.../ProjectStatus/ProjectLifecycleSummary.tsx | 257 +++++++-----------
.../ProjectStatus/ProjectResources.tsx | 13 +-
.../ProjectStatus/ProjectStatusModal.tsx | 143 +++++++---
.../Project/ProjectStatus/StaleFlags.tsx | 8 +-
9 files changed, 275 insertions(+), 233 deletions(-)
create mode 100644 frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.styles.tsx
create mode 100644 frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.tsx
diff --git a/frontend/src/assets/icons/projectStatus.svg b/frontend/src/assets/icons/projectStatus.svg
index 713e29eb62..8872e15086 100644
--- a/frontend/src/assets/icons/projectStatus.svg
+++ b/frontend/src/assets/icons/projectStatus.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectActivity.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectActivity.tsx
index 79145f662d..4b8bb253b4 100644
--- a/frontend/src/component/project/Project/ProjectStatus/ProjectActivity.tsx
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectActivity.tsx
@@ -7,16 +7,9 @@ import { styled, Tooltip } from '@mui/material';
const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
- justifyContent: 'center',
alignItems: 'center',
- gap: theme.spacing(2),
}));
-const TitleContainer = styled('h4')({
- margin: 0,
- width: '100%',
-});
-
type Output = { date: string; count: number; level: number };
const ensureFullYearData = (data: Output[]): Output[] => {
@@ -93,7 +86,6 @@ export const ProjectActivity = () => {
<>
{data.activityCountByDate.length > 0 ? (
- Activity in project
({
- backgroundColor: theme.palette.envAccordion.expanded,
- padding: theme.spacing(3),
- borderRadius: theme.shape.borderRadiusExtraLarge,
- minWidth: '300px',
- gridArea: 'health',
-}));
+import { HealthGridTile } from './ProjectHealthGrid.styles';
const TextContainer = styled('div')(({ theme }) => ({
display: 'flex',
@@ -63,7 +56,7 @@ export const ProjectHealth = () => {
: theme.palette.success.border;
return (
-
+
@@ -111,6 +104,6 @@ export const ProjectHealth = () => {
)}
-
+
);
};
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.styles.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.styles.tsx
new file mode 100644
index 0000000000..2102a9ebb5
--- /dev/null
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.styles.tsx
@@ -0,0 +1,7 @@
+import { styled } from '@mui/material';
+
+export const HealthGridTile = styled('article')(({ theme }) => ({
+ backgroundColor: theme.palette.envAccordion.expanded,
+ padding: theme.spacing(3),
+ borderRadius: theme.shape.borderRadiusExtraLarge,
+}));
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.tsx
new file mode 100644
index 0000000000..bc6517a306
--- /dev/null
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectHealthGrid.tsx
@@ -0,0 +1,57 @@
+import { ProjectHealth } from './ProjectHealth';
+import { styled } from '@mui/material';
+import { StaleFlags } from './StaleFlags';
+import { ProjectResources } from './ProjectResources';
+
+const onNarrowGrid = (css: object) => ({
+ '@container (max-width: 650px)': css,
+ '@supports not (container-type: inline-size)': {
+ '@media (max-width: 712px)': css,
+ },
+});
+
+const HealthContainer = styled('div')({
+ containerType: 'inline-size',
+});
+
+const HealthGrid = styled('div')(({ theme }) => ({
+ display: 'grid',
+ gridTemplateAreas: `
+ "health resources"
+ "stale resources"
+ `,
+ gridTemplateColumns: 'repeat(2, minmax(300px, 1fr))',
+ gap: theme.spacing(1, 2),
+ ...onNarrowGrid({
+ display: 'flex',
+ flexDirection: 'column',
+ gap: theme.spacing(1),
+ }),
+}));
+
+const Tile = styled('div', {
+ shouldForwardProp: (prop) => prop !== 'gridArea',
+})<{ gridArea: string }>(({ theme, gridArea }) => ({
+ gridArea,
+ '&>*': {
+ height: '100%',
+ },
+}));
+
+export const ProjectHealthGrid = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx
index b59a48111d..ba90284837 100644
--- a/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx
@@ -6,26 +6,10 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import type { FC } from 'react';
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
import type { ProjectStatusSchemaLifecycleSummary } from 'openapi';
-import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
import { lifecycleMessages } from './LifecycleMessages';
import InfoIcon from '@mui/icons-material/Info';
-const LifecycleRow = styled('div')(({ theme }) => ({
- display: 'flex',
- flexFlow: 'column',
- gap: theme.spacing(1),
-}));
-
-const HeaderRow = styled('div')(({ theme }) => ({
- display: 'flex',
- flex: 'auto',
- '& > *': {
- marginBlock: 0,
- fontWeight: 'normal',
- },
-}));
-
const LifecycleBoxContent = styled('div')(({ theme }) => ({
padding: theme.spacing(2),
gap: theme.spacing(4),
@@ -87,6 +71,7 @@ const LifecycleList = styled('ul')(({ theme }) => ({
justifyContent: 'center',
padding: 0,
flex: 'auto',
+ margin: 0,
}));
const Counter = styled('span')({
@@ -146,44 +131,6 @@ const BigNumber: FC<{ value?: number }> = ({ value }) => {
);
};
-
-const TooltipContent = styled('div')(({ theme }) => ({
- padding: theme.spacing(0.5),
-}));
-
-const TooltipText = styled('p')(({ theme }) => ({
- fontSize: theme.typography.body1.fontSize,
- '& + p': {
- marginTop: theme.spacing(1),
- },
-}));
-
-const LifecycleTooltip: FC = () => {
- return (
-
-
- Based on usage metrics and interactions with Unleash,
- feature flags can go through five distinct lifecycle
- stages. These stages mirror the typical software
- development process and allow you to identify
- bottlenecks at any stage of the lifecycle.
-
-
-
-
- Read more in our documentation
-
-
-
- }
- />
- );
-};
-
export const ProjectLifecycleSummary = () => {
const projectId = useRequiredPathParam('projectId');
const { data, loading } = useProjectStatus(projectId);
@@ -200,119 +147,103 @@ export const ProjectLifecycleSummary = () => {
}
};
return (
-
-
- Flag lifecycle
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+ {flagWord('initial')} in initial
+
+
+
+
+
+
+
-
-
- {flagWord('initial')} in initial
-
-
-
-
-
-
-
+
+
+ {flagWord('preLive')} in pre-live
+
+
+
+
+
+
+
-
-
- {flagWord('preLive')} in pre-live
-
-
-
-
-
-
-
+
+
+ {flagWord('live')} in live
+
+
+
+
+
+
+
-
-
- {flagWord('live')} in live
-
-
-
-
-
-
-
+
+
+ {flagWord('completed')} in cleanup
+
+
+
+
+
+
+
-
-
- {flagWord('completed')} in cleanup
-
-
-
-
-
-
-
-
-
-
- {flagWord('archived')} in archived
-
-
- This month
-
- {data?.lifecycleSummary.archived.currentFlags ?? 0}{' '}
- flags archived
-
-
-
-
-
+
+
+ {flagWord('archived')} in archived
+
+
+ This month
+
+ {data?.lifecycleSummary.archived.currentFlags ?? 0}{' '}
+ flags archived
+
+
+
+
);
};
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectResources.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectResources.tsx
index 9130458a07..d8b7bfdd17 100644
--- a/frontend/src/component/project/Project/ProjectStatus/ProjectResources.tsx
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectResources.tsx
@@ -8,14 +8,7 @@ import SegmentsIcon from '@mui/icons-material/DonutLarge';
import ConnectedIcon from '@mui/icons-material/Cable';
import { useProjectStatus } from 'hooks/api/getters/useProjectStatus/useProjectStatus';
import useLoading from 'hooks/useLoading';
-
-const Wrapper = styled('article')(({ theme }) => ({
- backgroundColor: theme.palette.envAccordion.expanded,
- padding: theme.spacing(3),
- borderRadius: theme.shape.borderRadiusExtraLarge,
- minWidth: '300px',
- gridArea: 'resources',
-}));
+import { HealthGridTile } from './ProjectHealthGrid.styles';
const ProjectResourcesInner = styled('div')(({ theme }) => ({
display: 'flex',
@@ -115,7 +108,7 @@ export const ProjectResources = () => {
const loadingRef = useLoading(loading, '[data-loading-resources=true]');
return (
-
+
Project resources
@@ -155,6 +148,6 @@ export const ProjectResources = () => {
-
+
);
};
diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectStatusModal.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectStatusModal.tsx
index 1d199c3c9f..b6e79c12b5 100644
--- a/frontend/src/component/project/Project/ProjectStatus/ProjectStatusModal.tsx
+++ b/frontend/src/component/project/Project/ProjectStatus/ProjectStatusModal.tsx
@@ -1,20 +1,28 @@
-import { styled } from '@mui/material';
+import { Button, styled } from '@mui/material';
import { DynamicSidebarModal } from 'component/common/SidebarModal/SidebarModal';
-import { ProjectResources } from './ProjectResources';
+import { ReactComponent as ProjectStatusSvg } from 'assets/icons/projectStatus.svg';
import { ProjectActivity } from './ProjectActivity';
-import { ProjectHealth } from './ProjectHealth';
import { ProjectLifecycleSummary } from './ProjectLifecycleSummary';
-import { StaleFlags } from './StaleFlags';
+import type { FC } from 'react';
+import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
+import { ProjectHealthGrid } from './ProjectHealthGrid';
const ModalContentContainer = styled('section')(({ theme }) => ({
minHeight: '100vh',
maxWidth: 1100,
width: '95vw',
backgroundColor: theme.palette.background.default,
- padding: theme.spacing(4),
display: 'flex',
flexFlow: 'column',
gap: theme.spacing(4),
+ paddingInline: theme.spacing(4),
+ paddingBlock: theme.spacing(10),
+}));
+
+const WidgetContainer = styled('div')(({ theme }) => ({
+ display: 'flex',
+ flexDirection: 'column',
+ gap: theme.spacing(9),
}));
type Props = {
@@ -22,47 +30,112 @@ type Props = {
close: () => void;
};
-const onNarrowGrid = (css: object) => ({
- '@container (max-width: 650px)': css,
- '@supports not (container-type: inline-size)': {
- '@media (max-width: 712px)': css,
+const LifecycleHeaderRow = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'end',
+}));
+
+const HeaderRow = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ gap: theme.spacing(1.5),
+}));
+
+const StyledProjectStatusSvg = styled(ProjectStatusSvg)(({ theme }) => ({
+ fill: theme.palette.primary.main,
+}));
+
+const ModalHeader = styled('h3')(({ theme }) => ({
+ fontSize: theme.typography.h2.fontSize,
+ margin: 0,
+}));
+
+const RowHeader = styled('h4')(({ theme }) => ({
+ margin: 0,
+ fontWeight: 'normal',
+}));
+
+const Row = styled('div')(({ theme }) => ({
+ display: 'flex',
+ flexDirection: 'column',
+ gap: theme.spacing(2),
+}));
+
+const TooltipContent = styled('div')(({ theme }) => ({
+ padding: theme.spacing(0.5),
+}));
+
+const TooltipText = styled('p')(({ theme }) => ({
+ fontSize: theme.typography.body1.fontSize,
+ '& + p': {
+ marginTop: theme.spacing(1),
},
-});
+}));
-const HealthContainer = styled('div')({
- containerType: 'inline-size',
-});
+const LifecycleTooltip: FC = () => {
+ return (
+
+
+ Based on usage metrics and interactions with Unleash,
+ feature flags can go through five distinct lifecycle
+ stages. These stages mirror the typical software
+ development process and allow you to identify
+ bottlenecks at any stage of the lifecycle.
+
-const HealthGrid = styled('div')(({ theme }) => ({
- display: 'grid',
- gridTemplateAreas: `
- "health resources"
- "stale resources"
- `,
- gridTemplateColumns: '1fr 1fr',
- gap: theme.spacing(1, 2),
- ...onNarrowGrid({
- display: 'flex',
- flexDirection: 'column',
- gap: theme.spacing(1),
- }),
+
+
+ Read more in our documentation
+
+
+
+ }
+ />
+ );
+};
+
+const CloseRow = styled('div')(({ theme }) => ({
+ display: 'flex',
+ justifyContent: 'flex-end',
+ marginBlockStart: 'auto',
}));
export const ProjectStatusModal = ({ open, close }: Props) => {
return (
-
-
-
-
-
-
-
+
+
+ Project status
+
+
+
+ Health
+
+
-
+
+ Activity in project
+
+
-
+
+
+ Flag lifecycle
+
+
+
+
+
+
+
+
);
diff --git a/frontend/src/component/project/Project/ProjectStatus/StaleFlags.tsx b/frontend/src/component/project/Project/ProjectStatus/StaleFlags.tsx
index ab91009567..a0e7c0ec30 100644
--- a/frontend/src/component/project/Project/ProjectStatus/StaleFlags.tsx
+++ b/frontend/src/component/project/Project/ProjectStatus/StaleFlags.tsx
@@ -4,13 +4,9 @@ import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/Pretti
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import type { FC } from 'react';
import { Link } from 'react-router-dom';
+import { HealthGridTile } from './ProjectHealthGrid.styles';
-const Wrapper = styled('article')(({ theme }) => ({
- backgroundColor: theme.palette.envAccordion.expanded,
- padding: theme.spacing(3),
- borderRadius: theme.shape.borderRadiusExtraLarge,
- minWidth: '300px',
- gridArea: 'stale',
+const Wrapper = styled(HealthGridTile)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),