1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00

feat: add safeguard button and borders (#10943)

This commit is contained in:
Mateusz Kwasniewski 2025-11-07 13:51:14 +01:00 committed by GitHub
parent eea76d7131
commit 0bcdf82e37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 100 additions and 61 deletions

View File

@ -28,6 +28,9 @@ import { useMilestoneProgressionsApi } from 'hooks/api/actions/useMilestoneProgr
import { DeleteProgressionDialog } from './DeleteProgressionDialog.tsx'; import { DeleteProgressionDialog } from './DeleteProgressionDialog.tsx';
import type { ChangeMilestoneProgressionSchema } from 'openapi'; import type { ChangeMilestoneProgressionSchema } from 'openapi';
import { ReleasePlanMilestoneItem } from './ReleasePlanMilestoneItem/ReleasePlanMilestoneItem.tsx'; import { ReleasePlanMilestoneItem } from './ReleasePlanMilestoneItem/ReleasePlanMilestoneItem.tsx';
import Add from '@mui/icons-material/Add';
import { StyledActionButton } from './ReleasePlanMilestoneItem/StyledActionButton.tsx';
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')(({ theme }) => ({
padding: theme.spacing(2), padding: theme.spacing(2),
@ -69,9 +72,30 @@ const StyledHeaderDescription = styled('p')(({ theme }) => ({
color: theme.palette.text.secondary, color: theme.palette.text.secondary,
})); }));
const StyledBody = styled('div')(({ theme }) => ({ const StyledBody = styled('div', {
shouldForwardProp: (prop) => prop !== 'safeguards',
})<{ safeguards: boolean }>(({ theme, safeguards }) => ({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
...(safeguards && {
border: `1px dashed ${theme.palette.neutral.border}`,
borderRadius: theme.shape.borderRadiusMedium,
padding: theme.spacing(0.5, 0),
}),
}));
const StyledAddSafeguard = styled('div')(({ theme }) => ({
display: 'flex',
borderBottom: `1px dashed ${theme.palette.neutral.border}`,
padding: theme.spacing(1.5, 2),
}));
const StyledMilestones = styled('div', {
shouldForwardProp: (prop) => prop !== 'safeguards',
})<{ safeguards: boolean }>(({ theme, safeguards }) => ({
...(safeguards && {
padding: theme.spacing(1.5, 1.5),
}),
})); }));
interface IReleasePlanProps { interface IReleasePlanProps {
@ -163,6 +187,7 @@ export const ReleasePlan = ({
return null; return null;
}; };
const milestoneProgressionsEnabled = useUiFlag('milestoneProgression'); const milestoneProgressionsEnabled = useUiFlag('milestoneProgression');
const safeguardsEnabled = useUiFlag('safeguards');
const [progressionFormOpenIndex, setProgressionFormOpenIndex] = useState< const [progressionFormOpenIndex, setProgressionFormOpenIndex] = useState<
number | null number | null
>(null); >(null);
@ -378,36 +403,49 @@ export const ReleasePlan = ({
</PermissionIconButton> </PermissionIconButton>
)} )}
</StyledHeader> </StyledHeader>
<StyledBody> <StyledBody safeguards={safeguardsEnabled}>
{milestones.map((milestone, index) => ( {safeguardsEnabled ? (
<ReleasePlanMilestoneItem <StyledAddSafeguard>
key={milestone.id} <StyledActionButton
milestone={milestone} onClick={() => {}}
index={index} color='primary'
milestones={milestones} startIcon={<Add />}
activeMilestoneId={activeMilestoneId} >
activeIndex={activeIndex} Add safeguard
environmentIsDisabled={environmentIsDisabled} </StyledActionButton>
readonly={readonly} </StyledAddSafeguard>
milestoneProgressionsEnabled={ ) : null}
milestoneProgressionsEnabled <StyledMilestones safeguards={safeguardsEnabled}>
} {milestones.map((milestone, index) => (
progressionFormOpenIndex={progressionFormOpenIndex} <ReleasePlanMilestoneItem
onSetProgressionFormOpenIndex={ key={milestone.id}
setProgressionFormOpenIndex milestone={milestone}
} index={index}
onStartMilestone={onStartMilestone} milestones={milestones}
onDeleteProgression={handleDeleteProgression} activeMilestoneId={activeMilestoneId}
onAddToChangeRequest={handleAddToChangeRequest} activeIndex={activeIndex}
getPendingProgressionChange={ environmentIsDisabled={environmentIsDisabled}
getPendingProgressionChange readonly={readonly}
} milestoneProgressionsEnabled={
projectId={projectId} milestoneProgressionsEnabled
environment={environment} }
featureName={featureName} progressionFormOpenIndex={progressionFormOpenIndex}
onUpdate={refetch} onSetProgressionFormOpenIndex={
/> setProgressionFormOpenIndex
))} }
onStartMilestone={onStartMilestone}
onDeleteProgression={handleDeleteProgression}
onAddToChangeRequest={handleAddToChangeRequest}
getPendingProgressionChange={
getPendingProgressionChange
}
projectId={projectId}
environment={environment}
featureName={featureName}
onUpdate={refetch}
/>
))}
</StyledMilestones>
</StyledBody> </StyledBody>
<ReleasePlanRemoveDialog <ReleasePlanRemoveDialog
plan={plan} plan={plan}

View File

@ -1,5 +1,4 @@
import Add from '@mui/icons-material/Add'; import Add from '@mui/icons-material/Add';
import { Button, styled } from '@mui/material';
import { Badge } from 'component/common/Badge/Badge'; import { Badge } from 'component/common/Badge/Badge';
import type { IReleasePlanMilestone } from 'interfaces/releasePlans'; import type { IReleasePlanMilestone } from 'interfaces/releasePlans';
import type { ChangeMilestoneProgressionSchema } from 'openapi'; import type { ChangeMilestoneProgressionSchema } from 'openapi';
@ -8,33 +7,7 @@ import { MilestoneTransitionDisplay } from '../ReleasePlanMilestone/MilestoneTra
import type { MilestoneStatus } from '../ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx'; import type { MilestoneStatus } from '../ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx';
import { MilestoneProgressionForm } from '../MilestoneProgressionForm/MilestoneProgressionForm.tsx'; import { MilestoneProgressionForm } from '../MilestoneProgressionForm/MilestoneProgressionForm.tsx';
import type { PendingProgressionChange } from './ReleasePlanMilestoneItem.tsx'; import type { PendingProgressionChange } from './ReleasePlanMilestoneItem.tsx';
import { StyledActionButton } from './StyledActionButton.tsx';
const StyledAddAutomationButton = styled(Button)(({ theme }) => ({
textTransform: 'none',
fontWeight: theme.typography.fontWeightBold,
fontSize: theme.typography.body2.fontSize,
padding: 0,
minWidth: 'auto',
gap: theme.spacing(1),
'&:hover': {
backgroundColor: 'transparent',
},
'& .MuiButton-startIcon': {
margin: 0,
width: 20,
height: 20,
border: `1px solid ${theme.palette.primary.main}`,
backgroundColor: theme.palette.background.elevation2,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'& svg': {
fontSize: 14,
color: theme.palette.primary.main,
},
},
}));
interface MilestoneAutomationProps { interface MilestoneAutomationProps {
milestone: IReleasePlanMilestone; milestone: IReleasePlanMilestone;
@ -112,13 +85,13 @@ export const MilestoneAutomation = ({
badge={badge} badge={badge}
/> />
) : ( ) : (
<StyledAddAutomationButton <StyledActionButton
onClick={onOpenProgressionForm} onClick={onOpenProgressionForm}
color='primary' color='primary'
startIcon={<Add />} startIcon={<Add />}
> >
Add automation Add automation
</StyledAddAutomationButton> </StyledActionButton>
)} )}
</MilestoneAutomationSection> </MilestoneAutomationSection>
); );

View File

@ -0,0 +1,28 @@
import { Button, styled } from '@mui/material';
export const StyledActionButton = styled(Button)(({ theme }) => ({
textTransform: 'none',
fontWeight: theme.typography.fontWeightBold,
fontSize: theme.typography.body2.fontSize,
padding: 0,
minWidth: 'auto',
gap: theme.spacing(1),
'&:hover': {
backgroundColor: 'transparent',
},
'& .MuiButton-startIcon': {
margin: 0,
width: 20,
height: 20,
border: `1px solid ${theme.palette.primary.main}`,
backgroundColor: theme.palette.background.elevation2,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'& svg': {
fontSize: 14,
color: theme.palette.primary.main,
},
},
}));