1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-19 00:15:43 +01:00

fix: template edit UI issues (#8974)

This commit is contained in:
David Leek 2024-12-13 11:25:57 +01:00 committed by GitHub
parent b2cf0e4e6b
commit a738be68b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 72 additions and 11 deletions

View File

@ -97,7 +97,9 @@ export const CreateReleasePlanTemplate = () => {
<CreateButton <CreateButton
name='template' name='template'
permission={RELEASE_PLAN_TEMPLATE_CREATE} permission={RELEASE_PLAN_TEMPLATE_CREATE}
/> >
Save template
</CreateButton>
<StyledCancelButton onClick={handleCancel}> <StyledCancelButton onClick={handleCancel}>
Cancel Cancel
</StyledCancelButton> </StyledCancelButton>

View File

@ -105,7 +105,9 @@ export const EditReleasePlanTemplate = () => {
<UpdateButton <UpdateButton
name='template' name='template'
permission={RELEASE_PLAN_TEMPLATE_UPDATE} permission={RELEASE_PLAN_TEMPLATE_UPDATE}
/> >
Save changes
</UpdateButton>
<StyledCancelButton onClick={handleCancel}> <StyledCancelButton onClick={handleCancel}>
Cancel Cancel
</StyledCancelButton> </StyledCancelButton>

View File

@ -9,8 +9,11 @@ import {
Accordion, Accordion,
AccordionSummary, AccordionSummary,
AccordionDetails, AccordionDetails,
IconButton,
useTheme,
} from '@mui/material'; } from '@mui/material';
import Edit from '@mui/icons-material/Edit'; import Edit from '@mui/icons-material/Edit';
import Delete from '@mui/icons-material/DeleteOutlined';
import type { import type {
IReleasePlanMilestonePayload, IReleasePlanMilestonePayload,
IReleasePlanMilestoneStrategy, IReleasePlanMilestoneStrategy,
@ -81,9 +84,10 @@ const StyledAccordion = styled(Accordion)(({ theme }) => ({
}, },
transition: 'background-color 0.2s ease-in-out', transition: 'background-color 0.2s ease-in-out',
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
'&.Mui-expanded': { '&:before': {
marginTop: theme.spacing(3), opacity: '0 !important',
}, },
'&.Mui-expanded': { marginTop: `${theme.spacing(2)} !important` },
})); }));
const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({ const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
@ -111,15 +115,27 @@ const StyledAccordionFooter = styled(Grid)(({ theme }) => ({
borderRadius: theme.shape.borderRadiusMedium, borderRadius: theme.shape.borderRadiusMedium,
})); }));
const StyledMilestoneActionGrid = styled(Grid)(({ theme }) => ({
display: 'flex',
justifyContent: 'flex-end',
}));
const StyledIconButton = styled(IconButton)(({ theme }) => ({
marginLeft: theme.spacing(1),
color: theme.palette.primary.main,
}));
interface IMilestoneCardProps { interface IMilestoneCardProps {
milestone: IReleasePlanMilestonePayload; milestone: IReleasePlanMilestonePayload;
milestoneChanged: (milestone: IReleasePlanMilestonePayload) => void; milestoneChanged: (milestone: IReleasePlanMilestonePayload) => void;
showAddStrategyDialog: ( showAddStrategyDialog: (
milestoneId: string, milestoneId: string,
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>, strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
editing: boolean,
) => void; ) => void;
errors: { [key: string]: string }; errors: { [key: string]: string };
clearErrors: () => void; clearErrors: () => void;
onDeleteMilestone: () => void;
} }
export const MilestoneCard = ({ export const MilestoneCard = ({
@ -128,6 +144,7 @@ export const MilestoneCard = ({
showAddStrategyDialog, showAddStrategyDialog,
errors, errors,
clearErrors, clearErrors,
onDeleteMilestone,
}: IMilestoneCardProps) => { }: IMilestoneCardProps) => {
const [editMode, setEditMode] = useState(false); const [editMode, setEditMode] = useState(false);
const [anchor, setAnchor] = useState<Element>(); const [anchor, setAnchor] = useState<Element>();
@ -136,6 +153,7 @@ export const MilestoneCard = ({
index: number; index: number;
height: number; height: number;
} | null>(null); } | null>(null);
const theme = useTheme();
const isPopoverOpen = Boolean(anchor); const isPopoverOpen = Boolean(anchor);
const popoverId = isPopoverOpen const popoverId = isPopoverOpen
? 'MilestoneStrategyMenuPopover' ? 'MilestoneStrategyMenuPopover'
@ -145,10 +163,16 @@ export const MilestoneCard = ({
setAnchor(undefined); setAnchor(undefined);
}; };
const onSelectEditStrategy = (
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
) => {
showAddStrategyDialog(milestone.id, strategy, true);
};
const onSelectStrategy = ( const onSelectStrategy = (
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>, strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
) => { ) => {
showAddStrategyDialog(milestone.id, strategy); showAddStrategyDialog(milestone.id, strategy, false);
}; };
const onDragOver = const onDragOver =
@ -244,7 +268,7 @@ export const MilestoneCard = ({
<StyledMilestoneCard> <StyledMilestoneCard>
<StyledMilestoneCardBody> <StyledMilestoneCardBody>
<Grid container> <Grid container>
<StyledGridItem item xs={10} md={10}> <StyledGridItem item xs={8} md={9}>
{editMode && ( {editMode && (
<StyledInput <StyledInput
label='' label=''
@ -279,7 +303,7 @@ export const MilestoneCard = ({
</> </>
)} )}
</StyledGridItem> </StyledGridItem>
<Grid item xs={2} md={2}> <StyledMilestoneActionGrid item xs={4} md={3}>
<Button <Button
variant='outlined' variant='outlined'
color='primary' color='primary'
@ -287,6 +311,13 @@ export const MilestoneCard = ({
> >
Add strategy Add strategy
</Button> </Button>
<StyledIconButton
title='Remove milestone'
onClick={onDeleteMilestone}
>
<Delete />
</StyledIconButton>
<Popover <Popover
id={popoverId} id={popoverId}
open={isPopoverOpen} open={isPopoverOpen}
@ -303,7 +334,7 @@ export const MilestoneCard = ({
openEditAddStrategy={onSelectStrategy} openEditAddStrategy={onSelectStrategy}
/> />
</Popover> </Popover>
</Grid> </StyledMilestoneActionGrid>
</Grid> </Grid>
</StyledMilestoneCardBody> </StyledMilestoneCardBody>
</StyledMilestoneCard> </StyledMilestoneCard>
@ -357,7 +388,7 @@ export const MilestoneCard = ({
milestoneStrategyDeleted(strg.id) milestoneStrategyDeleted(strg.id)
} }
onEditClick={() => { onEditClick={() => {
onSelectStrategy(strg); onSelectEditStrategy(strg);
}} }}
isDragging={false} isDragging={false}
strategy={strg} strategy={strg}
@ -372,6 +403,13 @@ export const MilestoneCard = ({
> >
Add strategy Add strategy
</StyledAddStrategyButton> </StyledAddStrategyButton>
<Button
variant='text'
color='primary'
onClick={onDeleteMilestone}
>
<Delete /> Remove milestone
</Button>
<Popover <Popover
id={popoverId} id={popoverId}
open={isPopoverOpen} open={isPopoverOpen}

View File

@ -15,6 +15,7 @@ interface IMilestoneListProps {
openAddStrategyForm: ( openAddStrategyForm: (
milestoneId: string, milestoneId: string,
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>, strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
editing: boolean,
) => void; ) => void;
errors: { [key: string]: string }; errors: { [key: string]: string };
clearErrors: () => void; clearErrors: () => void;
@ -34,6 +35,14 @@ export const MilestoneList = ({
clearErrors, clearErrors,
milestoneChanged, milestoneChanged,
}: IMilestoneListProps) => { }: IMilestoneListProps) => {
const onDeleteMilestone = (milestoneId: string) => () => {
setMilestones((prev) =>
prev
.filter((m) => m.id !== milestoneId)
.map((m, i) => ({ ...m, sortOrder: i })),
);
};
return ( return (
<> <>
{milestones.map((milestone) => ( {milestones.map((milestone) => (
@ -44,6 +53,7 @@ export const MilestoneList = ({
showAddStrategyDialog={openAddStrategyForm} showAddStrategyDialog={openAddStrategyForm}
errors={errors} errors={errors}
clearErrors={clearErrors} clearErrors={clearErrors}
onDeleteMilestone={onDeleteMilestone(milestone.id)}
/> />
))} ))}
<StyledAddMilestoneButton <StyledAddMilestoneButton

View File

@ -126,6 +126,7 @@ interface IReleasePlanTemplateAddStrategyFormProps {
milestoneId: string, milestoneId: string,
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>, strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
) => void; ) => void;
editMode: boolean;
} }
export const ReleasePlanTemplateAddStrategyForm = ({ export const ReleasePlanTemplateAddStrategyForm = ({
@ -133,6 +134,7 @@ export const ReleasePlanTemplateAddStrategyForm = ({
onCancel, onCancel,
strategy, strategy,
onAddUpdateStrategy, onAddUpdateStrategy,
editMode,
}: IReleasePlanTemplateAddStrategyFormProps) => { }: IReleasePlanTemplateAddStrategyFormProps) => {
const [currentStrategy, setCurrentStrategy] = useState(strategy); const [currentStrategy, setCurrentStrategy] = useState(strategy);
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);
@ -346,7 +348,7 @@ export const ReleasePlanTemplateAddStrategyForm = ({
disabled={!hasValidConstraints || errors.hasFormErrors()} disabled={!hasValidConstraints || errors.hasFormErrors()}
onClick={AddUpdateMilestoneStrategy} onClick={AddUpdateMilestoneStrategy}
> >
Save strategy {editMode ? 'Add changes' : 'Add strategy'}
</Button> </Button>
<StyledCancelButton onClick={onCancel}> <StyledCancelButton onClick={onCancel}>
Cancel Cancel

View File

@ -62,6 +62,7 @@ export const TemplateForm: React.FC<ITemplateFormProps> = ({
const [activeMilestoneId, setActiveMilestoneId] = useState< const [activeMilestoneId, setActiveMilestoneId] = useState<
string | undefined string | undefined
>(); >();
const [strategyModeEdit, setStrategyModeEdit] = useState(false);
const [strategy, setStrategy] = useState< const [strategy, setStrategy] = useState<
Omit<IReleasePlanMilestoneStrategy, 'milestoneId'> Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>
>({ >({
@ -74,7 +75,9 @@ export const TemplateForm: React.FC<ITemplateFormProps> = ({
const openAddUpdateStrategyForm = ( const openAddUpdateStrategyForm = (
milestoneId: string, milestoneId: string,
strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>, strategy: Omit<IReleasePlanMilestoneStrategy, 'milestoneId'>,
editing: boolean,
) => { ) => {
setStrategyModeEdit(editing);
setActiveMilestoneId(milestoneId); setActiveMilestoneId(milestoneId);
setStrategy(strategy); setStrategy(strategy);
setAddUpdateStrategyOpen(true); setAddUpdateStrategyOpen(true);
@ -114,6 +117,7 @@ export const TemplateForm: React.FC<ITemplateFormProps> = ({
); );
} }
setAddUpdateStrategyOpen(false); setAddUpdateStrategyOpen(false);
setStrategyModeEdit(false);
setActiveMilestoneId(undefined); setActiveMilestoneId(undefined);
setStrategy({ setStrategy({
name: 'flexibleRollout', name: 'flexibleRollout',
@ -190,7 +194,9 @@ export const TemplateForm: React.FC<ITemplateFormProps> = ({
<SidebarModal <SidebarModal
label='Add strategy to template milestone' label='Add strategy to template milestone'
onClose={() => {}} onClose={() => {
setStrategyModeEdit(false);
}}
open={addUpdateStrategyOpen} open={addUpdateStrategyOpen}
> >
<ReleasePlanTemplateAddStrategyForm <ReleasePlanTemplateAddStrategyForm
@ -200,6 +206,7 @@ export const TemplateForm: React.FC<ITemplateFormProps> = ({
onCancel={() => { onCancel={() => {
setAddUpdateStrategyOpen(false); setAddUpdateStrategyOpen(false);
}} }}
editMode={strategyModeEdit}
/> />
</SidebarModal> </SidebarModal>
</StyledForm> </StyledForm>