1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-24 20:06:55 +01:00

fix: lint

This commit is contained in:
FredrikOseberg 2025-10-21 14:07:57 +02:00
parent 5869c7e04f
commit 19b04e8223
No known key found for this signature in database
GPG Key ID: 282FD8A6D8F9BCF0
6 changed files with 259 additions and 136 deletions

View File

@ -327,30 +327,50 @@ const CreateMilestoneProgression: FC<{
</ChangeItemWrapper> </ChangeItemWrapper>
<TabPanel> <TabPanel>
{modifiedPlan.milestones.map((milestone, index) => { {modifiedPlan.milestones.map((milestone, index) => {
const isNotLastMilestone = index < modifiedPlan.milestones.length - 1; const isNotLastMilestone =
const isTargetMilestone = milestone.id === change.payload.sourceMilestone; index < modifiedPlan.milestones.length - 1;
const hasProgression = Boolean(milestone.transitionCondition); const isTargetMilestone =
const showAutomation = isTargetMilestone && isNotLastMilestone && hasProgression; milestone.id === change.payload.sourceMilestone;
const hasProgression = Boolean(
milestone.transitionCondition,
);
const showAutomation =
isTargetMilestone &&
isNotLastMilestone &&
hasProgression;
const readonly = changeRequestState === 'Applied' || changeRequestState === 'Cancelled'; const readonly =
changeRequestState === 'Applied' ||
changeRequestState === 'Cancelled';
const status: MilestoneStatus = 'not-started'; // In change request view, always not-started const status: MilestoneStatus = 'not-started'; // In change request view, always not-started
// Build automation section for this milestone // Build automation section for this milestone
const automationSection = showAutomation && milestone.transitionCondition ? ( const automationSection =
<MilestoneAutomationSection status={status}> showAutomation && milestone.transitionCondition ? (
<MilestoneTransitionDisplay <MilestoneAutomationSection status={status}>
intervalMinutes={milestone.transitionCondition.intervalMinutes} <MilestoneTransitionDisplay
onSave={async (payload) => { intervalMinutes={
onUpdateChangeRequestSubmit?.(milestone.id, payload); milestone.transitionCondition
}} .intervalMinutes
onDelete={() => onDeleteChangeRequestSubmit?.(milestone.id)} }
milestoneName={milestone.name} onSave={async (payload) => {
status={status} onUpdateChangeRequestSubmit?.(
hasPendingUpdate={false} milestone.id,
hasPendingDelete={false} payload,
/> );
</MilestoneAutomationSection> }}
) : undefined; onDelete={() =>
onDeleteChangeRequestSubmit?.(
milestone.id,
)
}
milestoneName={milestone.name}
status={status}
hasPendingUpdate={false}
hasPendingDelete={false}
/>
</MilestoneAutomationSection>
) : undefined;
return ( return (
<div key={milestone.id}> <div key={milestone.id}>
@ -359,7 +379,9 @@ const CreateMilestoneProgression: FC<{
milestone={milestone} milestone={milestone}
automationSection={automationSection} automationSection={automationSection}
allMilestones={modifiedPlan.milestones} allMilestones={modifiedPlan.milestones}
activeMilestoneId={modifiedPlan.activeMilestoneId} activeMilestoneId={
modifiedPlan.activeMilestoneId
}
/> />
{isNotLastMilestone && <StyledConnection />} {isNotLastMilestone && <StyledConnection />}
</div> </div>
@ -408,7 +430,8 @@ const UpdateMilestoneProgression: FC<{
const basePlan = change.payload.snapshot || currentReleasePlan; const basePlan = change.payload.snapshot || currentReleasePlan;
if (!basePlan) return null; if (!basePlan) return null;
const sourceId = change.payload.sourceMilestoneId || change.payload.sourceMilestone; const sourceId =
change.payload.sourceMilestoneId || change.payload.sourceMilestone;
const sourceMilestone = basePlan.milestones.find( const sourceMilestone = basePlan.milestones.find(
(milestone) => milestone.id === sourceId, (milestone) => milestone.id === sourceId,
); );
@ -453,28 +476,45 @@ const UpdateMilestoneProgression: FC<{
</ChangeItemWrapper> </ChangeItemWrapper>
<TabPanel> <TabPanel>
{modifiedPlan.milestones.map((milestone, index) => { {modifiedPlan.milestones.map((milestone, index) => {
const isNotLastMilestone = index < modifiedPlan.milestones.length - 1; const isNotLastMilestone =
const showAutomation = milestone.id === sourceId && isNotLastMilestone && Boolean(milestone.transitionCondition); index < modifiedPlan.milestones.length - 1;
const showAutomation =
milestone.id === sourceId &&
isNotLastMilestone &&
Boolean(milestone.transitionCondition);
const readonly = changeRequestState === 'Applied' || changeRequestState === 'Cancelled'; const readonly =
changeRequestState === 'Applied' ||
changeRequestState === 'Cancelled';
const status: MilestoneStatus = 'not-started'; const status: MilestoneStatus = 'not-started';
// Build automation section for this milestone // Build automation section for this milestone
const automationSection = showAutomation && milestone.transitionCondition ? ( const automationSection =
<MilestoneAutomationSection status={status}> showAutomation && milestone.transitionCondition ? (
<MilestoneTransitionDisplay <MilestoneAutomationSection status={status}>
intervalMinutes={milestone.transitionCondition.intervalMinutes} <MilestoneTransitionDisplay
onSave={async (payload) => { intervalMinutes={
onUpdateChangeRequestSubmit?.(milestone.id, payload); milestone.transitionCondition
}} .intervalMinutes
onDelete={() => onDeleteChangeRequestSubmit?.(milestone.id)} }
milestoneName={milestone.name} onSave={async (payload) => {
status={status} onUpdateChangeRequestSubmit?.(
hasPendingUpdate={false} milestone.id,
hasPendingDelete={false} payload,
/> );
</MilestoneAutomationSection> }}
) : undefined; onDelete={() =>
onDeleteChangeRequestSubmit?.(
milestone.id,
)
}
milestoneName={milestone.name}
status={status}
hasPendingUpdate={false}
hasPendingDelete={false}
/>
</MilestoneAutomationSection>
) : undefined;
return ( return (
<div key={milestone.id}> <div key={milestone.id}>
@ -483,7 +523,9 @@ const UpdateMilestoneProgression: FC<{
milestone={milestone} milestone={milestone}
automationSection={automationSection} automationSection={automationSection}
allMilestones={modifiedPlan.milestones} allMilestones={modifiedPlan.milestones}
activeMilestoneId={modifiedPlan.activeMilestoneId} activeMilestoneId={
modifiedPlan.activeMilestoneId
}
/> />
{isNotLastMilestone && <StyledConnection />} {isNotLastMilestone && <StyledConnection />}
</div> </div>
@ -528,7 +570,12 @@ const ConsolidatedProgressionChanges: FC<{
}) => { }) => {
// Get all progression changes for this feature // Get all progression changes for this feature
const progressionChanges = feature.changes.filter( const progressionChanges = feature.changes.filter(
(change): change is IChangeRequestCreateMilestoneProgression | IChangeRequestUpdateMilestoneProgression | IChangeRequestDeleteMilestoneProgression => (
change,
): change is
| IChangeRequestCreateMilestoneProgression
| IChangeRequestUpdateMilestoneProgression
| IChangeRequestDeleteMilestoneProgression =>
change.action === 'createMilestoneProgression' || change.action === 'createMilestoneProgression' ||
change.action === 'updateMilestoneProgression' || change.action === 'updateMilestoneProgression' ||
change.action === 'deleteMilestoneProgression', change.action === 'deleteMilestoneProgression',
@ -538,19 +585,27 @@ const ConsolidatedProgressionChanges: FC<{
// Use snapshot from first change if available, otherwise use current release plan // Use snapshot from first change if available, otherwise use current release plan
// Prioritize create/update changes over delete changes for snapshot selection // Prioritize create/update changes over delete changes for snapshot selection
const firstChangeWithSnapshot = progressionChanges.find((change) => const firstChangeWithSnapshot =
change.payload?.snapshot && (change.action === 'createMilestoneProgression' || change.action === 'updateMilestoneProgression') progressionChanges.find(
) || progressionChanges.find((change) => change.payload?.snapshot); (change) =>
const basePlan = firstChangeWithSnapshot?.payload?.snapshot || currentReleasePlan; change.payload?.snapshot &&
(change.action === 'createMilestoneProgression' ||
change.action === 'updateMilestoneProgression'),
) || progressionChanges.find((change) => change.payload?.snapshot);
const basePlan =
firstChangeWithSnapshot?.payload?.snapshot || currentReleasePlan;
if (!basePlan) { if (!basePlan) {
console.error('[ConsolidatedProgressionChanges] No release plan data available', { console.error(
hasSnapshot: !!firstChangeWithSnapshot, '[ConsolidatedProgressionChanges] No release plan data available',
hasCurrentPlan: !!currentReleasePlan, {
progressionChanges hasSnapshot: !!firstChangeWithSnapshot,
}); hasCurrentPlan: !!currentReleasePlan,
progressionChanges,
},
);
return ( return (
<Alert severity="error"> <Alert severity='error'>
Unable to load release plan data. Please refresh the page. Unable to load release plan data. Please refresh the page.
</Alert> </Alert>
); );
@ -569,22 +624,27 @@ const ConsolidatedProgressionChanges: FC<{
const updateChange = progressionChanges.find( const updateChange = progressionChanges.find(
(change): change is IChangeRequestUpdateMilestoneProgression => (change): change is IChangeRequestUpdateMilestoneProgression =>
change.action === 'updateMilestoneProgression' && change.action === 'updateMilestoneProgression' &&
(change.payload.sourceMilestoneId === milestone.id || change.payload.sourceMilestone === milestone.id), (change.payload.sourceMilestoneId === milestone.id ||
change.payload.sourceMilestone === milestone.id),
); );
const deleteChange = progressionChanges.find( const deleteChange = progressionChanges.find(
(change): change is IChangeRequestDeleteMilestoneProgression => (change): change is IChangeRequestDeleteMilestoneProgression =>
change.action === 'deleteMilestoneProgression' && change.action === 'deleteMilestoneProgression' &&
(change.payload.sourceMilestoneId === milestone.id || change.payload.sourceMilestone === milestone.id), (change.payload.sourceMilestoneId === milestone.id ||
change.payload.sourceMilestone === milestone.id),
); );
// Check for conflicting changes (delete + create/update for same milestone) // Check for conflicting changes (delete + create/update for same milestone)
if (deleteChange && (createChange || updateChange)) { if (deleteChange && (createChange || updateChange)) {
console.warn('[ConsolidatedProgressionChanges] Conflicting changes detected for milestone:', { console.warn(
milestone: milestone.name, '[ConsolidatedProgressionChanges] Conflicting changes detected for milestone:',
hasCreate: !!createChange, {
hasUpdate: !!updateChange, milestone: milestone.name,
hasDelete: !!deleteChange hasCreate: !!createChange,
}); hasUpdate: !!updateChange,
hasDelete: !!deleteChange,
},
);
} }
// If there's a delete change, remove the transition condition // If there's a delete change, remove the transition condition
@ -611,7 +671,8 @@ const ConsolidatedProgressionChanges: FC<{
const sourceId = const sourceId =
change.action === 'createMilestoneProgression' change.action === 'createMilestoneProgression'
? change.payload.sourceMilestone ? change.payload.sourceMilestone
: (change.payload.sourceMilestoneId || change.payload.sourceMilestone); : change.payload.sourceMilestoneId ||
change.payload.sourceMilestone;
const sourceName = const sourceName =
basePlan.milestones.find((milestone) => milestone.id === sourceId) basePlan.milestones.find((milestone) => milestone.id === sourceId)
?.name || sourceId; ?.name || sourceId;
@ -629,7 +690,10 @@ const ConsolidatedProgressionChanges: FC<{
<ChangeItemWrapper> <ChangeItemWrapper>
<ChangeItemInfo> <ChangeItemInfo>
{progressionChanges.map((change, index) => { {progressionChanges.map((change, index) => {
const Component = change.action === 'deleteMilestoneProgression' ? Deleted : Added; const Component =
change.action === 'deleteMilestoneProgression'
? Deleted
: Added;
return ( return (
<Component key={index}> <Component key={index}>
{changeDescriptions[index]} {changeDescriptions[index]}
@ -651,42 +715,70 @@ const ConsolidatedProgressionChanges: FC<{
// Check if there's a delete change for this milestone // Check if there's a delete change for this milestone
const deleteChange = progressionChanges.find( const deleteChange = progressionChanges.find(
(change): change is IChangeRequestDeleteMilestoneProgression => (
change,
): change is IChangeRequestDeleteMilestoneProgression =>
change.action === 'deleteMilestoneProgression' && change.action === 'deleteMilestoneProgression' &&
(change.payload.sourceMilestoneId === milestone.id || change.payload.sourceMilestone === milestone.id), (change.payload.sourceMilestoneId ===
milestone.id ||
change.payload.sourceMilestone ===
milestone.id),
); );
// If there's a delete change, use the original milestone from basePlan // If there's a delete change, use the original milestone from basePlan
const originalMilestone = deleteChange const originalMilestone = deleteChange
? basePlan.milestones.find(baseMilestone => baseMilestone.id === milestone.id) ? basePlan.milestones.find(
(baseMilestone) =>
baseMilestone.id === milestone.id,
)
: null; : null;
const displayMilestone = deleteChange && originalMilestone ? originalMilestone : milestone; const displayMilestone =
deleteChange && originalMilestone
? originalMilestone
: milestone;
// Show automation section for any milestone that has a transition condition // Show automation section for any milestone that has a transition condition
// or if there's a delete change (to show what's being deleted) // or if there's a delete change (to show what's being deleted)
const shouldShowAutomationSection = Boolean(displayMilestone.transitionCondition) || Boolean(deleteChange); const shouldShowAutomationSection =
const showAutomation = isNotLastMilestone && shouldShowAutomationSection; Boolean(displayMilestone.transitionCondition) ||
Boolean(deleteChange);
const showAutomation =
isNotLastMilestone && shouldShowAutomationSection;
const readonly = changeRequestState === 'Applied' || changeRequestState === 'Cancelled'; const readonly =
changeRequestState === 'Applied' ||
changeRequestState === 'Cancelled';
const status: MilestoneStatus = 'not-started'; const status: MilestoneStatus = 'not-started';
// Build automation section for this milestone // Build automation section for this milestone
const automationSection = showAutomation && displayMilestone.transitionCondition ? ( const automationSection =
<MilestoneAutomationSection status={status}> showAutomation &&
<MilestoneTransitionDisplay displayMilestone.transitionCondition ? (
intervalMinutes={displayMilestone.transitionCondition.intervalMinutes} <MilestoneAutomationSection status={status}>
onSave={async (payload) => { <MilestoneTransitionDisplay
onUpdateChangeRequestSubmit?.(displayMilestone.id, payload); intervalMinutes={
}} displayMilestone.transitionCondition
onDelete={() => onDeleteChangeRequestSubmit?.(displayMilestone.id)} .intervalMinutes
milestoneName={displayMilestone.name} }
status={status} onSave={async (payload) => {
hasPendingUpdate={false} onUpdateChangeRequestSubmit?.(
hasPendingDelete={Boolean(deleteChange)} displayMilestone.id,
/> payload,
</MilestoneAutomationSection> );
) : undefined; }}
onDelete={() =>
onDeleteChangeRequestSubmit?.(
displayMilestone.id,
)
}
milestoneName={displayMilestone.name}
status={status}
hasPendingUpdate={false}
hasPendingDelete={Boolean(deleteChange)}
/>
</MilestoneAutomationSection>
) : undefined;
return ( return (
<div key={milestone.id}> <div key={milestone.id}>
@ -695,7 +787,9 @@ const ConsolidatedProgressionChanges: FC<{
milestone={displayMilestone} milestone={displayMilestone}
automationSection={automationSection} automationSection={automationSection}
allMilestones={modifiedPlan.milestones} allMilestones={modifiedPlan.milestones}
activeMilestoneId={modifiedPlan.activeMilestoneId} activeMilestoneId={
modifiedPlan.activeMilestoneId
}
/> />
{isNotLastMilestone && <StyledConnection />} {isNotLastMilestone && <StyledConnection />}
</div> </div>
@ -746,7 +840,8 @@ export const ReleasePlanChange: FC<{
); );
const currentReleasePlan = releasePlans[0]; const currentReleasePlan = releasePlans[0];
const { addChange } = useChangeRequestApi(); const { addChange } = useChangeRequestApi();
const { refetch: refetchChangeRequests } = usePendingChangeRequests(projectId); const { refetch: refetchChangeRequests } =
usePendingChangeRequests(projectId);
const { setToastData } = useToast(); const { setToastData } = useToast();
const handleUpdate = async () => { const handleUpdate = async () => {
@ -778,7 +873,9 @@ export const ReleasePlanChange: FC<{
} }
}; };
const handleDeleteChangeRequestSubmit = async (sourceMilestoneId: string) => { const handleDeleteChangeRequestSubmit = async (
sourceMilestoneId: string,
) => {
await addChange(projectId, environmentName, { await addChange(projectId, environmentName, {
feature: featureName, feature: featureName,
action: 'deleteMilestoneProgression', action: 'deleteMilestoneProgression',
@ -805,7 +902,12 @@ export const ReleasePlanChange: FC<{
change.action === 'deleteMilestoneProgression') change.action === 'deleteMilestoneProgression')
) { ) {
const progressionChanges = feature.changes.filter( const progressionChanges = feature.changes.filter(
(change): change is IChangeRequestCreateMilestoneProgression | IChangeRequestUpdateMilestoneProgression | IChangeRequestDeleteMilestoneProgression => (
change,
): change is
| IChangeRequestCreateMilestoneProgression
| IChangeRequestUpdateMilestoneProgression
| IChangeRequestDeleteMilestoneProgression =>
change.action === 'createMilestoneProgression' || change.action === 'createMilestoneProgression' ||
change.action === 'updateMilestoneProgression' || change.action === 'updateMilestoneProgression' ||
change.action === 'deleteMilestoneProgression', change.action === 'deleteMilestoneProgression',
@ -870,8 +972,12 @@ export const ReleasePlanChange: FC<{
featureName={featureName} featureName={featureName}
changeRequestState={changeRequestState} changeRequestState={changeRequestState}
onUpdate={handleUpdate} onUpdate={handleUpdate}
onUpdateChangeRequestSubmit={handleUpdateChangeRequestSubmit} onUpdateChangeRequestSubmit={
onDeleteChangeRequestSubmit={handleDeleteChangeRequestSubmit} handleUpdateChangeRequestSubmit
}
onDeleteChangeRequestSubmit={
handleDeleteChangeRequestSubmit
}
/> />
)} )}
{change.action === 'updateMilestoneProgression' && ( {change.action === 'updateMilestoneProgression' && (
@ -884,8 +990,12 @@ export const ReleasePlanChange: FC<{
featureName={featureName} featureName={featureName}
changeRequestState={changeRequestState} changeRequestState={changeRequestState}
onUpdate={handleUpdate} onUpdate={handleUpdate}
onUpdateChangeRequestSubmit={handleUpdateChangeRequestSubmit} onUpdateChangeRequestSubmit={
onDeleteChangeRequestSubmit={handleDeleteChangeRequestSubmit} handleUpdateChangeRequestSubmit
}
onDeleteChangeRequestSubmit={
handleDeleteChangeRequestSubmit
}
/> />
)} )}
</> </>

View File

@ -296,9 +296,10 @@ type ChangeRequestStartMilestone = {
snapshot?: IReleasePlan; snapshot?: IReleasePlan;
}; };
type ChangeRequestCreateMilestoneProgression = CreateMilestoneProgressionSchema & { type ChangeRequestCreateMilestoneProgression =
snapshot?: IReleasePlan; CreateMilestoneProgressionSchema & {
}; snapshot?: IReleasePlan;
};
type ChangeRequestUpdateMilestoneProgression = type ChangeRequestUpdateMilestoneProgression =
UpdateMilestoneProgressionSchema & { UpdateMilestoneProgressionSchema & {

View File

@ -104,11 +104,7 @@ export const MilestoneProgressionForm = ({
{form.errors.time && ( {form.errors.time && (
<StyledErrorMessage>{form.errors.time}</StyledErrorMessage> <StyledErrorMessage>{form.errors.time}</StyledErrorMessage>
)} )}
<Button <Button variant='outlined' onClick={onCancel} size='small'>
variant='outlined'
onClick={onCancel}
size='small'
>
Cancel Cancel
</Button> </Button>
<Button <Button

View File

@ -381,33 +381,33 @@ export const ReleasePlan = ({
return ( return (
<StyledContainer> <StyledContainer>
<StyledHeader> <StyledHeader>
<StyledHeaderGroup> <StyledHeaderGroup>
<StyledHeaderTitleLabel> <StyledHeaderTitleLabel>
Release plan:{' '} Release plan:{' '}
</StyledHeaderTitleLabel> </StyledHeaderTitleLabel>
<StyledHeaderTitle>{name}</StyledHeaderTitle> <StyledHeaderTitle>{name}</StyledHeaderTitle>
<StyledHeaderDescription> <StyledHeaderDescription>
<Truncator lines={2} title={description}> <Truncator lines={2} title={description}>
{description} {description}
</Truncator> </Truncator>
</StyledHeaderDescription> </StyledHeaderDescription>
</StyledHeaderGroup> </StyledHeaderGroup>
{!readonly && ( {!readonly && (
<PermissionIconButton <PermissionIconButton
onClick={confirmRemoveReleasePlan} onClick={confirmRemoveReleasePlan}
permission={DELETE_FEATURE_STRATEGY} permission={DELETE_FEATURE_STRATEGY}
environmentId={environment} environmentId={environment}
projectId={projectId} projectId={projectId}
tooltipProps={{ tooltipProps={{
title: 'Remove release plan', title: 'Remove release plan',
}} }}
> >
<Delete /> <Delete />
</PermissionIconButton> </PermissionIconButton>
)} )}
</StyledHeader> </StyledHeader>
<StyledBody> <StyledBody>
{milestones.map((milestone, index) => ( {milestones.map((milestone, index) => (
<ReleasePlanMilestoneItem <ReleasePlanMilestoneItem
key={milestone.id} key={milestone.id}
@ -418,15 +418,25 @@ export const ReleasePlan = ({
activeIndex={activeIndex} activeIndex={activeIndex}
environmentIsDisabled={environmentIsDisabled} environmentIsDisabled={environmentIsDisabled}
readonly={readonly} readonly={readonly}
milestoneProgressionsEnabled={milestoneProgressionsEnabled} milestoneProgressionsEnabled={
milestoneProgressionsEnabled
}
progressionFormOpenIndex={progressionFormOpenIndex} progressionFormOpenIndex={progressionFormOpenIndex}
onSetProgressionFormOpenIndex={setProgressionFormOpenIndex} onSetProgressionFormOpenIndex={
setProgressionFormOpenIndex
}
onStartMilestone={onStartMilestone} onStartMilestone={onStartMilestone}
onDeleteProgression={handleDeleteProgression} onDeleteProgression={handleDeleteProgression}
onProgressionSave={handleProgressionSave} onProgressionSave={handleProgressionSave}
onProgressionChangeRequestSubmit={handleProgressionChangeRequestSubmit} onProgressionChangeRequestSubmit={
onUpdateProgressionChangeRequestSubmit={handleUpdateProgressionChangeRequestSubmit} handleProgressionChangeRequestSubmit
getPendingProgressionChange={getPendingProgressionChange} }
onUpdateProgressionChangeRequestSubmit={
handleUpdateProgressionChangeRequestSubmit
}
getPendingProgressionChange={
getPendingProgressionChange
}
projectId={projectId} projectId={projectId}
environment={environment} environment={environment}
featureName={featureName} featureName={featureName}

View File

@ -146,7 +146,9 @@ export const MilestoneTransitionDisplay = ({
)} )}
{showDraftBadge && ( {showDraftBadge && (
<Badge color={hasPendingDelete ? 'error' : 'warning'}> <Badge color={hasPendingDelete ? 'error' : 'warning'}>
{hasPendingDelete ? 'Deleted in draft' : 'Modified in draft'} {hasPendingDelete
? 'Deleted in draft'
: 'Modified in draft'}
</Badge> </Badge>
)} )}
<IconButton <IconButton

View File

@ -136,8 +136,10 @@ export const ReleasePlanMilestoneItem = ({
const isNotLastMilestone = index < milestones.length - 1; const isNotLastMilestone = index < milestones.length - 1;
const isProgressionFormOpen = progressionFormOpenIndex === index; const isProgressionFormOpen = progressionFormOpenIndex === index;
const nextMilestoneId = milestones[index + 1]?.id || ''; const nextMilestoneId = milestones[index + 1]?.id || '';
const handleOpenProgressionForm = () => onSetProgressionFormOpenIndex(index); const handleOpenProgressionForm = () =>
const handleCloseProgressionForm = () => onSetProgressionFormOpenIndex(null); onSetProgressionFormOpenIndex(index);
const handleCloseProgressionForm = () =>
onSetProgressionFormOpenIndex(null);
// Unified handler for creating progression // Unified handler for creating progression
const handleCreateProgression = async ( const handleCreateProgression = async (
@ -236,7 +238,9 @@ export const ReleasePlanMilestoneItem = ({
/> />
) : effectiveTransitionCondition ? ( ) : effectiveTransitionCondition ? (
<MilestoneTransitionDisplay <MilestoneTransitionDisplay
intervalMinutes={effectiveTransitionCondition.intervalMinutes} intervalMinutes={
effectiveTransitionCondition.intervalMinutes
}
onSave={handleUpdateProgression} onSave={handleUpdateProgression}
onDelete={() => onDeleteProgression(milestone)} onDelete={() => onDeleteProgression(milestone)}
milestoneName={milestone.name} milestoneName={milestone.name}