Skip to content

Commit 795b674

Browse files
feat: add change request support for updating milestone progressions (#10819)
1 parent 022226d commit 795b674

File tree

7 files changed

+123
-11
lines changed

7 files changed

+123
-11
lines changed

frontend/src/component/changeRequest/changeRequest.types.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { IUser } from '../../interfaces/user.js';
55
import type {
66
SetStrategySortOrderSchema,
77
CreateMilestoneProgressionSchema,
8+
UpdateMilestoneProgressionSchema,
89
} from 'openapi';
910
import type { IReleasePlan } from 'interfaces/releasePlans';
1011

@@ -135,7 +136,8 @@ type ChangeRequestPayload =
135136
| ChangeRequestAddReleasePlan
136137
| ChangeRequestDeleteReleasePlan
137138
| ChangeRequestStartMilestone
138-
| ChangeRequestCreateMilestoneProgression;
139+
| ChangeRequestCreateMilestoneProgression
140+
| ChangeRequestUpdateMilestoneProgression;
139141

140142
export interface IChangeRequestAddStrategy extends IChangeRequestChangeBase {
141143
action: 'addStrategy';
@@ -198,6 +200,12 @@ export interface IChangeRequestCreateMilestoneProgression
198200
payload: ChangeRequestCreateMilestoneProgression;
199201
}
200202

203+
export interface IChangeRequestUpdateMilestoneProgression
204+
extends IChangeRequestChangeBase {
205+
action: 'updateMilestoneProgression';
206+
payload: ChangeRequestUpdateMilestoneProgression;
207+
}
208+
201209
export interface IChangeRequestReorderStrategy
202210
extends IChangeRequestChangeBase {
203211
action: 'reorderStrategy';
@@ -246,7 +254,8 @@ export type IFeatureChange =
246254
| IChangeRequestAddReleasePlan
247255
| IChangeRequestDeleteReleasePlan
248256
| IChangeRequestStartMilestone
249-
| IChangeRequestCreateMilestoneProgression;
257+
| IChangeRequestCreateMilestoneProgression
258+
| IChangeRequestUpdateMilestoneProgression;
250259

251260
export type ISegmentChange =
252261
| IChangeRequestUpdateSegment
@@ -281,6 +290,11 @@ type ChangeRequestStartMilestone = {
281290

282291
type ChangeRequestCreateMilestoneProgression = CreateMilestoneProgressionSchema;
283292

293+
type ChangeRequestUpdateMilestoneProgression =
294+
UpdateMilestoneProgressionSchema & {
295+
sourceMilestoneId: string;
296+
};
297+
284298
export type ChangeRequestAddStrategy = Pick<
285299
IFeatureStrategy,
286300
| 'parameters'
@@ -319,4 +333,5 @@ export type ChangeRequestAction =
319333
| 'addReleasePlan'
320334
| 'deleteReleasePlan'
321335
| 'startMilestone'
322-
| 'createMilestoneProgression';
336+
| 'createMilestoneProgression'
337+
| 'updateMilestoneProgression';

frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ChangeRequest/ReleasePlanChangeRequestDialog.tsx

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import type {
44
IReleasePlan,
55
IReleasePlanMilestone,
66
} from 'interfaces/releasePlans';
7-
import type { CreateMilestoneProgressionSchema } from 'openapi';
7+
import type {
8+
CreateMilestoneProgressionSchema,
9+
UpdateMilestoneProgressionSchema,
10+
} from 'openapi';
811
import { getTimeValueAndUnitFromMinutes } from '../hooks/useMilestoneProgressionForm.js';
912

1013
const StyledBoldSpan = styled('span')(({ theme }) => ({
@@ -23,6 +26,11 @@ type ChangeRequestAction =
2326
| {
2427
type: 'createMilestoneProgression';
2528
payload: CreateMilestoneProgressionSchema;
29+
}
30+
| {
31+
type: 'updateMilestoneProgression';
32+
sourceMilestoneId: string;
33+
payload: UpdateMilestoneProgressionSchema;
2634
};
2735

2836
interface IReleasePlanChangeRequestDialogProps {
@@ -105,6 +113,27 @@ export const ReleasePlanChangeRequestDialog = ({
105113
</p>
106114
);
107115
}
116+
117+
case 'updateMilestoneProgression': {
118+
const milestone = releasePlan.milestones.find(
119+
(milestone) => milestone.id === action.sourceMilestoneId,
120+
);
121+
122+
const { value, unit } = getTimeValueAndUnitFromMinutes(
123+
action.payload.transitionCondition.intervalMinutes,
124+
);
125+
const timeInterval = `${value} ${unit}`;
126+
127+
return (
128+
<p>
129+
Update automation for{' '}
130+
<StyledBoldSpan>{milestone?.name}</StyledBoldSpan> to
131+
proceed after{' '}
132+
<StyledBoldSpan>{timeInterval}</StyledBoldSpan> in{' '}
133+
{environmentId}
134+
</p>
135+
);
136+
}
108137
}
109138
};
110139

frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import { useUiFlag } from 'hooks/useUiFlag';
2525
import { MilestoneProgressionForm } from './MilestoneProgressionForm/MilestoneProgressionForm.tsx';
2626
import { useMilestoneProgressionsApi } from 'hooks/api/actions/useMilestoneProgressionsApi/useMilestoneProgressionsApi';
2727
import { DeleteProgressionDialog } from './DeleteProgressionDialog.tsx';
28-
import type { CreateMilestoneProgressionSchema } from 'openapi';
28+
import type {
29+
CreateMilestoneProgressionSchema,
30+
UpdateMilestoneProgressionSchema,
31+
} from 'openapi';
2932

3033
const StyledContainer = styled('div')(({ theme }) => ({
3134
padding: theme.spacing(2),
@@ -124,6 +127,11 @@ export const ReleasePlan = ({
124127
type: 'createMilestoneProgression';
125128
payload: CreateMilestoneProgressionSchema;
126129
}
130+
| {
131+
type: 'updateMilestoneProgression';
132+
sourceMilestoneId: string;
133+
payload: UpdateMilestoneProgressionSchema;
134+
}
127135
| null
128136
>(null);
129137
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
@@ -171,6 +179,17 @@ export const ReleasePlan = ({
171179
});
172180
setProgressionFormOpenIndex(null);
173181
break;
182+
183+
case 'updateMilestoneProgression':
184+
await addChange(projectId, environment, {
185+
feature: featureName,
186+
action: 'updateMilestoneProgression',
187+
payload: {
188+
sourceMilestone: changeRequestAction.sourceMilestoneId,
189+
...changeRequestAction.payload,
190+
},
191+
});
192+
break;
174193
}
175194

176195
await refetchChangeRequests();
@@ -273,6 +292,17 @@ export const ReleasePlan = ({
273292
});
274293
};
275294

295+
const handleUpdateProgressionChangeRequestSubmit = (
296+
sourceMilestoneId: string,
297+
payload: UpdateMilestoneProgressionSchema,
298+
) => {
299+
setChangeRequestAction({
300+
type: 'updateMilestoneProgression',
301+
sourceMilestoneId,
302+
payload,
303+
});
304+
};
305+
276306
const handleDeleteProgression = (milestone: IReleasePlanMilestone) => {
277307
setMilestoneToDeleteProgression(milestone);
278308
};
@@ -398,6 +428,9 @@ export const ReleasePlan = ({
398428
environment={environment}
399429
featureName={featureName}
400430
onUpdate={refetch}
431+
onUpdateChangeRequestSubmit={
432+
handleUpdateProgressionChangeRequestSubmit
433+
}
401434
allMilestones={milestones}
402435
activeMilestoneId={activeMilestoneId}
403436
/>

frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneAutomationSection.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Add from '@mui/icons-material/Add';
22
import { Button, styled } from '@mui/material';
33
import type { MilestoneStatus } from './ReleasePlanMilestoneStatus.tsx';
44
import { MilestoneTransitionDisplay } from './MilestoneTransitionDisplay.tsx';
5+
import type { UpdateMilestoneProgressionSchema } from 'openapi';
56

67
const StyledAutomationContainer = styled('div', {
78
shouldForwardProp: (prop) => prop !== 'status',
@@ -65,6 +66,10 @@ interface IMilestoneAutomationSectionProps {
6566
featureName: string;
6667
sourceMilestoneId: string;
6768
onUpdate: () => void;
69+
onUpdateChangeRequestSubmit?: (
70+
sourceMilestoneId: string,
71+
payload: UpdateMilestoneProgressionSchema,
72+
) => void;
6873
}
6974

7075
export const MilestoneAutomationSection = ({
@@ -80,6 +85,7 @@ export const MilestoneAutomationSection = ({
8085
featureName,
8186
sourceMilestoneId,
8287
onUpdate,
88+
onUpdateChangeRequestSubmit,
8389
}: IMilestoneAutomationSectionProps) => {
8490
if (!showAutomation) return null;
8591

@@ -98,6 +104,7 @@ export const MilestoneAutomationSection = ({
98104
featureName={featureName}
99105
sourceMilestoneId={sourceMilestoneId}
100106
onUpdate={onUpdate}
107+
onChangeRequestSubmit={onUpdateChangeRequestSubmit}
101108
/>
102109
) : (
103110
<StyledAddAutomationButton

frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneTransitionDisplay.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
useMilestoneProgressionForm,
1212
getTimeValueAndUnitFromMinutes,
1313
} from '../hooks/useMilestoneProgressionForm.js';
14+
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
15+
import type { UpdateMilestoneProgressionSchema } from 'openapi';
1416

1517
const StyledDisplayContainer = styled('div')(({ theme }) => ({
1618
display: 'flex',
@@ -67,6 +69,10 @@ interface IMilestoneTransitionDisplayProps {
6769
featureName: string;
6870
sourceMilestoneId: string;
6971
onUpdate: () => void;
72+
onChangeRequestSubmit?: (
73+
sourceMilestoneId: string,
74+
payload: UpdateMilestoneProgressionSchema,
75+
) => void;
7076
}
7177

7278
export const MilestoneTransitionDisplay = ({
@@ -79,9 +85,11 @@ export const MilestoneTransitionDisplay = ({
7985
featureName,
8086
sourceMilestoneId,
8187
onUpdate,
88+
onChangeRequestSubmit,
8289
}: IMilestoneTransitionDisplayProps) => {
8390
const { updateMilestoneProgression } = useMilestoneProgressionsApi();
8491
const { setToastData, setToastApiError } = useToast();
92+
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
8593

8694
const initial = getTimeValueAndUnitFromMinutes(intervalMinutes);
8795
const form = useMilestoneProgressionForm(
@@ -100,18 +108,25 @@ export const MilestoneTransitionDisplay = ({
100108
const handleSave = async () => {
101109
if (isSubmitting || !hasChanged) return;
102110

111+
const payload: UpdateMilestoneProgressionSchema = {
112+
transitionCondition: {
113+
intervalMinutes: currentIntervalMinutes,
114+
},
115+
};
116+
117+
if (isChangeRequestConfigured(environment) && onChangeRequestSubmit) {
118+
onChangeRequestSubmit(sourceMilestoneId, payload);
119+
return;
120+
}
121+
103122
setIsSubmitting(true);
104123
try {
105124
await updateMilestoneProgression(
106125
projectId,
107126
environment,
108127
featureName,
109128
sourceMilestoneId,
110-
{
111-
transitionCondition: {
112-
intervalMinutes: currentIntervalMinutes,
113-
},
114-
},
129+
payload,
115130
);
116131
setToastData({
117132
type: 'success',

frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { StrategyList } from 'component/common/StrategyList/StrategyList';
1919
import { StrategyListItem } from 'component/common/StrategyList/StrategyListItem';
2020
import { MilestoneAutomationSection } from './MilestoneAutomationSection.tsx';
2121
import { formatDateYMDHMS } from 'utils/formatDate';
22+
import type { UpdateMilestoneProgressionSchema } from 'openapi';
2223

2324
const StyledAccordion = styled(Accordion, {
2425
shouldForwardProp: (prop) => prop !== 'status' && prop !== 'hasAutomation',
@@ -107,6 +108,10 @@ interface IReleasePlanMilestoneProps {
107108
environment?: string;
108109
featureName?: string;
109110
onUpdate?: () => void;
111+
onUpdateChangeRequestSubmit?: (
112+
sourceMilestoneId: string,
113+
payload: UpdateMilestoneProgressionSchema,
114+
) => void;
110115
allMilestones: IReleasePlanMilestone[];
111116
activeMilestoneId?: string;
112117
}
@@ -124,6 +129,7 @@ export const ReleasePlanMilestone = ({
124129
environment,
125130
featureName,
126131
onUpdate,
132+
onUpdateChangeRequestSubmit,
127133
allMilestones,
128134
activeMilestoneId,
129135
}: IReleasePlanMilestoneProps) => {
@@ -193,6 +199,9 @@ export const ReleasePlanMilestone = ({
193199
featureName={featureName}
194200
sourceMilestoneId={milestone.id}
195201
onUpdate={onUpdate}
202+
onUpdateChangeRequestSubmit={
203+
onUpdateChangeRequestSubmit
204+
}
196205
/>
197206
)}
198207
</StyledMilestoneContainer>
@@ -283,6 +292,9 @@ export const ReleasePlanMilestone = ({
283292
featureName={featureName}
284293
sourceMilestoneId={milestone.id}
285294
onUpdate={onUpdate}
295+
onUpdateChangeRequestSubmit={
296+
onUpdateChangeRequestSubmit
297+
}
286298
/>
287299
)}
288300
</StyledMilestoneContainer>

frontend/src/hooks/api/actions/useChangeRequestApi/useChangeRequestApi.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export interface IChangeSchema {
2222
| 'addReleasePlan'
2323
| 'deleteReleasePlan'
2424
| 'startMilestone'
25-
| 'createMilestoneProgression';
25+
| 'createMilestoneProgression'
26+
| 'updateMilestoneProgression';
2627
payload: string | boolean | object | number | undefined;
2728
}
2829

0 commit comments

Comments
 (0)