mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-24 20:06:55 +01:00
refactor: simplify safeguard form management (#11013)
This commit is contained in:
parent
63e969821c
commit
97a20b0929
@ -66,7 +66,7 @@ export const EnvironmentAccordionBody = ({
|
|||||||
const [strategies, setStrategies] = useState(
|
const [strategies, setStrategies] = useState(
|
||||||
featureEnvironment?.strategies || [],
|
featureEnvironment?.strategies || [],
|
||||||
);
|
);
|
||||||
const { releasePlans } = useFeatureReleasePlans(
|
const { releasePlans, refetch } = useFeatureReleasePlans(
|
||||||
projectId,
|
projectId,
|
||||||
featureId,
|
featureId,
|
||||||
featureEnvironment?.name,
|
featureEnvironment?.name,
|
||||||
@ -229,6 +229,7 @@ export const EnvironmentAccordionBody = ({
|
|||||||
<ReleasePlan
|
<ReleasePlan
|
||||||
plan={plan}
|
plan={plan}
|
||||||
environmentIsDisabled={isDisabled}
|
environmentIsDisabled={isDisabled}
|
||||||
|
onAutomationChange={refetch}
|
||||||
/>
|
/>
|
||||||
</StrategyListItem>
|
</StrategyListItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import PlayCircle from '@mui/icons-material/PlayCircle';
|
|||||||
import { DELETE_FEATURE_STRATEGY } from '@server/types/permissions';
|
import { DELETE_FEATURE_STRATEGY } from '@server/types/permissions';
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
import { useReleasePlansApi } from 'hooks/api/actions/useReleasePlansApi/useReleasePlansApi';
|
import { useReleasePlansApi } from 'hooks/api/actions/useReleasePlansApi/useReleasePlansApi';
|
||||||
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import type {
|
import type {
|
||||||
@ -32,7 +31,10 @@ import { ReleasePlanMilestoneItem } from './ReleasePlanMilestoneItem/ReleasePlan
|
|||||||
import Add from '@mui/icons-material/Add';
|
import Add from '@mui/icons-material/Add';
|
||||||
|
|
||||||
import { StyledActionButton } from './ReleasePlanMilestoneItem/StyledActionButton.tsx';
|
import { StyledActionButton } from './ReleasePlanMilestoneItem/StyledActionButton.tsx';
|
||||||
import { SafeguardForm } from './SafeguardForm/SafeguardForm.tsx';
|
import {
|
||||||
|
SafeguardForm,
|
||||||
|
useSafeguardForm,
|
||||||
|
} from './SafeguardForm/SafeguardForm.tsx';
|
||||||
import { useSafeguardsApi } from 'hooks/api/actions/useSafeguardsApi/useSafeguardsApi';
|
import { useSafeguardsApi } from 'hooks/api/actions/useSafeguardsApi/useSafeguardsApi';
|
||||||
import type { CreateSafeguardSchema } from 'openapi/models/createSafeguardSchema';
|
import type { CreateSafeguardSchema } from 'openapi/models/createSafeguardSchema';
|
||||||
import { DeleteSafeguardDialog } from './DeleteSafeguardDialog.tsx';
|
import { DeleteSafeguardDialog } from './DeleteSafeguardDialog.tsx';
|
||||||
@ -120,12 +122,14 @@ interface IReleasePlanProps {
|
|||||||
plan: IReleasePlan;
|
plan: IReleasePlan;
|
||||||
environmentIsDisabled?: boolean;
|
environmentIsDisabled?: boolean;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
onAutomationChange?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReleasePlan = ({
|
export const ReleasePlan = ({
|
||||||
plan,
|
plan,
|
||||||
environmentIsDisabled,
|
environmentIsDisabled,
|
||||||
readonly,
|
readonly,
|
||||||
|
onAutomationChange,
|
||||||
}: IReleasePlanProps) => {
|
}: IReleasePlanProps) => {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
@ -139,8 +143,6 @@ export const ReleasePlan = ({
|
|||||||
} = plan;
|
} = plan;
|
||||||
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const { refetch, loading: featureReleasePlansLoading } =
|
|
||||||
useFeatureReleasePlans(projectId, featureName, environment);
|
|
||||||
const { removeReleasePlanFromFeature, startReleasePlanMilestone } =
|
const { removeReleasePlanFromFeature, startReleasePlanMilestone } =
|
||||||
useReleasePlansApi();
|
useReleasePlansApi();
|
||||||
const {
|
const {
|
||||||
@ -221,9 +223,11 @@ export const ReleasePlan = ({
|
|||||||
>(null);
|
>(null);
|
||||||
const [milestoneToDeleteProgression, setMilestoneToDeleteProgression] =
|
const [milestoneToDeleteProgression, setMilestoneToDeleteProgression] =
|
||||||
useState<IReleasePlanMilestone | null>(null);
|
useState<IReleasePlanMilestone | null>(null);
|
||||||
const [safeguardFormOpen, setSafeguardFormOpen] = useState(false);
|
|
||||||
const [safeguardDeleteDialogOpen, setSafeguardDeleteDialogOpen] =
|
const [safeguardDeleteDialogOpen, setSafeguardDeleteDialogOpen] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const { safeguardFormOpen, setSafeguardFormOpen } =
|
||||||
|
useSafeguardForm(safeguards);
|
||||||
|
|
||||||
const onChangeRequestConfirm = async () => {
|
const onChangeRequestConfirm = async () => {
|
||||||
if (!changeRequestAction) return;
|
if (!changeRequestAction) return;
|
||||||
@ -311,7 +315,7 @@ export const ReleasePlan = ({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
|
|
||||||
refetch();
|
onAutomationChange?.();
|
||||||
setRemoveOpen(false);
|
setRemoveOpen(false);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
@ -337,7 +341,7 @@ export const ReleasePlan = ({
|
|||||||
text: `Milestone "${milestone.name}" has started`,
|
text: `Milestone "${milestone.name}" has started`,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
refetch();
|
onAutomationChange?.();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
@ -387,7 +391,7 @@ export const ReleasePlan = ({
|
|||||||
featureName,
|
featureName,
|
||||||
sourceMilestoneId: milestoneToDeleteProgression.id,
|
sourceMilestoneId: milestoneToDeleteProgression.id,
|
||||||
});
|
});
|
||||||
await refetch();
|
onAutomationChange?.();
|
||||||
setMilestoneToDeleteProgression(null);
|
setMilestoneToDeleteProgression(null);
|
||||||
setToastData({
|
setToastData({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
@ -411,7 +415,7 @@ export const ReleasePlan = ({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: 'Automation resumed successfully',
|
text: 'Automation resumed successfully',
|
||||||
});
|
});
|
||||||
refetch();
|
onAutomationChange?.();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
@ -434,11 +438,9 @@ export const ReleasePlan = ({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: 'Safeguard added successfully',
|
text: 'Safeguard added successfully',
|
||||||
});
|
});
|
||||||
refetch();
|
onAutomationChange?.();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
} finally {
|
|
||||||
setSafeguardFormOpen(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -461,7 +463,7 @@ export const ReleasePlan = ({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: 'Safeguard deleted successfully',
|
text: 'Safeguard deleted successfully',
|
||||||
});
|
});
|
||||||
refetch();
|
onAutomationChange?.();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
} finally {
|
} finally {
|
||||||
@ -529,20 +531,15 @@ export const ReleasePlan = ({
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<StyledBody border={safeguardBorder}>
|
<StyledBody border={safeguardBorder}>
|
||||||
{safeguardsEnabled ? (
|
{onAutomationChange && safeguardsEnabled ? (
|
||||||
<StyledAddSafeguard border={safeguardBorder}>
|
<StyledAddSafeguard border={safeguardBorder}>
|
||||||
{safeguards.length > 0 ? (
|
{safeguardFormOpen ? (
|
||||||
<SafeguardForm
|
<SafeguardForm
|
||||||
safeguard={safeguards[0]}
|
safeguard={safeguards?.[0]}
|
||||||
onSubmit={handleSafeguardSubmit}
|
onSubmit={handleSafeguardSubmit}
|
||||||
onCancel={() => setSafeguardFormOpen(false)}
|
onCancel={() => setSafeguardFormOpen(false)}
|
||||||
onDelete={handleSafeguardDelete}
|
onDelete={handleSafeguardDelete}
|
||||||
/>
|
/>
|
||||||
) : safeguardFormOpen || featureReleasePlansLoading ? (
|
|
||||||
<SafeguardForm
|
|
||||||
onSubmit={handleSafeguardSubmit}
|
|
||||||
onCancel={() => setSafeguardFormOpen(false)}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<StyledActionButton
|
<StyledActionButton
|
||||||
onClick={() => setSafeguardFormOpen(true)}
|
onClick={() => setSafeguardFormOpen(true)}
|
||||||
@ -582,7 +579,7 @@ export const ReleasePlan = ({
|
|||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
environment={environment}
|
environment={environment}
|
||||||
featureName={featureName}
|
featureName={featureName}
|
||||||
onUpdate={refetch}
|
onUpdate={onAutomationChange}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StyledMilestones>
|
</StyledMilestones>
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export interface IReleasePlanMilestoneItemProps {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
featureName: string;
|
featureName: string;
|
||||||
onUpdate: () => void | Promise<void>;
|
onUpdate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTimeUnit = (intervalMinutes: number): 'minutes' | 'hours' | 'days' => {
|
const getTimeUnit = (intervalMinutes: number): 'minutes' | 'hours' | 'days' => {
|
||||||
@ -134,7 +134,7 @@ export const ReleasePlanMilestoneItem = ({
|
|||||||
text: 'Automation configured successfully',
|
text: 'Automation configured successfully',
|
||||||
});
|
});
|
||||||
handleCloseProgressionForm();
|
handleCloseProgressionForm();
|
||||||
await onUpdate();
|
onUpdate?.();
|
||||||
return {};
|
return {};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
|
|||||||
@ -26,6 +26,20 @@ import type { ISafeguard } from 'interfaces/releasePlans.ts';
|
|||||||
|
|
||||||
const StyledIcon = createStyledIcon(ShieldIcon);
|
const StyledIcon = createStyledIcon(ShieldIcon);
|
||||||
|
|
||||||
|
export const useSafeguardForm = (safeguards: ISafeguard[] | undefined) => {
|
||||||
|
const [safeguardFormOpen, setSafeguardFormOpen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (safeguards && safeguards.length > 0) {
|
||||||
|
setSafeguardFormOpen(true);
|
||||||
|
} else {
|
||||||
|
setSafeguardFormOpen(false);
|
||||||
|
}
|
||||||
|
}, [JSON.stringify(safeguards)]);
|
||||||
|
|
||||||
|
return { safeguardFormOpen, setSafeguardFormOpen };
|
||||||
|
};
|
||||||
|
|
||||||
interface ISafeguardFormProps {
|
interface ISafeguardFormProps {
|
||||||
onSubmit: (data: CreateSafeguardSchema) => void;
|
onSubmit: (data: CreateSafeguardSchema) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
@ -182,7 +196,7 @@ export const SafeguardForm = ({
|
|||||||
threshold: Number(threshold),
|
threshold: Number(threshold),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mode === 'edit') {
|
if (mode === 'edit' || mode === 'create') {
|
||||||
setMode('display');
|
setMode('display');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user