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:
parent
b2cf0e4e6b
commit
a738be68b0
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user