mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-02 01:17:58 +02:00
chore: prepare for lifecycle comments (#8733)
This PR is a preparation for adding lifecycle comments. It turns the Lifecycle boxes into buttons, using MUI's [`CardActionArea`](https://mui.com/material-ui/api/card-action-area/) component, and allows you to select one at a time. I'm not convinced about the a11y of this approach, but it appears to be in line with what MUI suggests, so ... I'll add the speech bubbles in a follow-up. <img width="1059" alt="image" src="https://github.com/user-attachments/assets/ad3f649f-10de-4418-a780-10321e90d001">
This commit is contained in:
parent
61e297dd22
commit
bc7511abd4
@ -0,0 +1,16 @@
|
|||||||
|
import type { ProjectStatusSchemaLifecycleSummary } from 'openapi';
|
||||||
|
|
||||||
|
export const lifecycleMessages: Record<
|
||||||
|
keyof ProjectStatusSchemaLifecycleSummary,
|
||||||
|
string
|
||||||
|
> = {
|
||||||
|
initial:
|
||||||
|
'Feature flags in the initial phase indicate you have created flags that is not detected in any environments which mean either integration issues or unused flags',
|
||||||
|
preLive:
|
||||||
|
'In the pre-live phase the feature is being developed and tested in controlled environments. Once the feature is ready the flag can be enabled in production.',
|
||||||
|
live: 'The feature is being rolled out in production according to the decided strategy targeting user segments and/or using percentage rollout. ',
|
||||||
|
completed:
|
||||||
|
'Flags that are in cleanup are potentially stale flags. View the flags to evaluate whether you should archive them in Unleash and clean up your codebase to reduce technical debt',
|
||||||
|
archived:
|
||||||
|
'Flags that have been archived and are no longer in use, but kept for future reference.',
|
||||||
|
};
|
@ -1,9 +1,9 @@
|
|||||||
import { styled } from '@mui/material';
|
import { CardActionArea, styled } from '@mui/material';
|
||||||
import { FeatureLifecycleStageIcon } from 'component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon';
|
import { FeatureLifecycleStageIcon } from 'component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon';
|
||||||
import { useProjectStatus } from 'hooks/api/getters/useProjectStatus/useProjectStatus';
|
import { useProjectStatus } from 'hooks/api/getters/useProjectStatus/useProjectStatus';
|
||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import type { FC } from 'react';
|
import { useState, type FC } from 'react';
|
||||||
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
||||||
import type { ProjectStatusSchemaLifecycleSummary } from 'openapi';
|
import type { ProjectStatusSchemaLifecycleSummary } from 'openapi';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
@ -24,16 +24,45 @@ const HeaderRow = styled('div')(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const LifecycleBox = styled('li')(({ theme }) => ({
|
const LifecycleBoxContent = styled('div')(({ theme }) => ({
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
|
||||||
border: `2px solid ${theme.palette.divider}`,
|
|
||||||
gap: theme.spacing(4),
|
gap: theme.spacing(4),
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexFlow: 'column',
|
flexFlow: 'column',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
transition: 'border-color 200ms',
|
||||||
|
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||||
|
border: `2px solid ${theme.palette.divider}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const StyledCardActionArea = styled(CardActionArea)(({ theme }) => ({
|
||||||
|
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||||
|
'&[aria-pressed="true"] > *': {
|
||||||
|
borderColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const LifecycleBox = ({
|
||||||
|
children,
|
||||||
|
isActive,
|
||||||
|
onClick,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
isActive?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<StyledCardActionArea
|
||||||
|
onClick={onClick}
|
||||||
|
aria-pressed={isActive ? 'true' : 'false'}
|
||||||
|
>
|
||||||
|
<LifecycleBoxContent>{children}</LifecycleBoxContent>
|
||||||
|
</StyledCardActionArea>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const LifecycleList = styled('ul')(({ theme }) => ({
|
const LifecycleList = styled('ul')(({ theme }) => ({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
listStyle: 'none',
|
listStyle: 'none',
|
||||||
@ -144,6 +173,9 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
const { data, loading } = useProjectStatus(projectId);
|
const { data, loading } = useProjectStatus(projectId);
|
||||||
const { isEnterprise } = useUiConfig();
|
const { isEnterprise } = useUiConfig();
|
||||||
|
|
||||||
|
const [activeLifecycleStage, setActiveLifecycleStage] = useState<
|
||||||
|
keyof ProjectStatusSchemaLifecycleSummary | null
|
||||||
|
>(null);
|
||||||
const loadingRef = useLoading<HTMLUListElement>(
|
const loadingRef = useLoading<HTMLUListElement>(
|
||||||
loading,
|
loading,
|
||||||
'[data-loading-project-lifecycle-summary=true]',
|
'[data-loading-project-lifecycle-summary=true]',
|
||||||
@ -162,7 +194,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
<LifecycleTooltip />
|
<LifecycleTooltip />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
<LifecycleList ref={loadingRef}>
|
<LifecycleList ref={loadingRef}>
|
||||||
<LifecycleBox>
|
<LifecycleBox
|
||||||
|
onClick={() => setActiveLifecycleStage('initial')}
|
||||||
|
isActive={activeLifecycleStage === 'initial'}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<Counter>
|
<Counter>
|
||||||
<BigNumber
|
<BigNumber
|
||||||
@ -182,7 +217,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
averageDays={data?.lifecycleSummary.initial.averageDays}
|
averageDays={data?.lifecycleSummary.initial.averageDays}
|
||||||
/>
|
/>
|
||||||
</LifecycleBox>
|
</LifecycleBox>
|
||||||
<LifecycleBox>
|
<LifecycleBox
|
||||||
|
onClick={() => setActiveLifecycleStage('preLive')}
|
||||||
|
isActive={activeLifecycleStage === 'preLive'}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<Counter>
|
<Counter>
|
||||||
<BigNumber
|
<BigNumber
|
||||||
@ -202,7 +240,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
averageDays={data?.lifecycleSummary.preLive.averageDays}
|
averageDays={data?.lifecycleSummary.preLive.averageDays}
|
||||||
/>
|
/>
|
||||||
</LifecycleBox>
|
</LifecycleBox>
|
||||||
<LifecycleBox>
|
<LifecycleBox
|
||||||
|
onClick={() => setActiveLifecycleStage('live')}
|
||||||
|
isActive={activeLifecycleStage === 'live'}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<Counter>
|
<Counter>
|
||||||
<BigNumber
|
<BigNumber
|
||||||
@ -220,7 +261,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
averageDays={data?.lifecycleSummary.live.averageDays}
|
averageDays={data?.lifecycleSummary.live.averageDays}
|
||||||
/>
|
/>
|
||||||
</LifecycleBox>
|
</LifecycleBox>
|
||||||
<LifecycleBox>
|
<LifecycleBox
|
||||||
|
onClick={() => setActiveLifecycleStage('completed')}
|
||||||
|
isActive={activeLifecycleStage === 'completed'}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<Counter>
|
<Counter>
|
||||||
<BigNumber
|
<BigNumber
|
||||||
@ -243,7 +287,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</LifecycleBox>
|
</LifecycleBox>
|
||||||
<LifecycleBox>
|
<LifecycleBox
|
||||||
|
onClick={() => setActiveLifecycleStage('archived')}
|
||||||
|
isActive={activeLifecycleStage === 'archived'}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<Counter>
|
<Counter>
|
||||||
<BigNumber
|
<BigNumber
|
||||||
|
Loading…
Reference in New Issue
Block a user