diff --git a/frontend/src/component/common/HelpIcon/HelpIcon.tsx b/frontend/src/component/common/HelpIcon/HelpIcon.tsx index 1c54473b76..70177f828a 100644 --- a/frontend/src/component/common/HelpIcon/HelpIcon.tsx +++ b/frontend/src/component/common/HelpIcon/HelpIcon.tsx @@ -1,6 +1,9 @@ import { styled, Tooltip, type TooltipProps } from '@mui/material'; import HelpOutline from '@mui/icons-material/HelpOutline'; -import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip'; +import { + HtmlTooltip, + type IHtmlTooltipProps, +} from 'component/common/HtmlTooltip/HtmlTooltip'; const StyledContainer = styled('span')<{ size: string | undefined }>( ({ theme, size }) => ({ @@ -24,13 +27,18 @@ const StyledContainer = styled('span')<{ size: string | undefined }>( }), ); -interface IHelpIconProps { +type IHelpIconProps = { tooltip: React.ReactNode; - htmlTooltip?: boolean; placement?: TooltipProps['placement']; children?: React.ReactNode; size?: string; -} +} & ( + | { + htmlTooltip: true; + htmlTooltipMaxWidth?: IHtmlTooltipProps['maxWidth']; + } + | { htmlTooltip?: false } +); export const HelpIcon = ({ tooltip, @@ -38,10 +46,20 @@ export const HelpIcon = ({ placement, children, size, + ...props }: IHelpIconProps) => { if (htmlTooltip) { + const { htmlTooltipMaxWidth } = props as { + htmlTooltipMaxWidth?: IHtmlTooltipProps['maxWidth']; + }; + return ( - + {children ?? } diff --git a/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx b/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx index ecf58ea9b1..89a122a053 100644 --- a/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx +++ b/frontend/src/component/project/Project/ProjectStatus/ProjectLifecycleSummary.tsx @@ -6,6 +6,24 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import type { FC } from 'react'; import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber'; import type { ProjectStatusSchemaLifecycleSummary } from 'openapi'; +import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; +import { HelpIcon } from 'component/common/HelpIcon/HelpIcon'; + +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 LifecycleBox = styled('li')(({ theme }) => ({ padding: theme.spacing(2), borderRadius: theme.shape.borderRadiusExtraLarge, @@ -16,13 +34,14 @@ const LifecycleBox = styled('li')(({ theme }) => ({ justifyContent: 'space-between', })); -const Wrapper = styled('ul')(({ theme }) => ({ +const LifecycleList = styled('ul')(({ theme }) => ({ display: 'grid', listStyle: 'none', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: theme.spacing(1), justifyContent: 'center', padding: 0, + flex: 'auto', })); const Counter = styled('span')({ @@ -83,9 +102,47 @@ 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); + const { isEnterprise } = useUiConfig(); const loadingRef = useLoading( loading, @@ -99,103 +156,118 @@ 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 -
-
-
-
+