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,23 +327,43 @@ 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 =
showAutomation && milestone.transitionCondition ? (
<MilestoneAutomationSection status={status}> <MilestoneAutomationSection status={status}>
<MilestoneTransitionDisplay <MilestoneTransitionDisplay
intervalMinutes={milestone.transitionCondition.intervalMinutes} intervalMinutes={
milestone.transitionCondition
.intervalMinutes
}
onSave={async (payload) => { onSave={async (payload) => {
onUpdateChangeRequestSubmit?.(milestone.id, payload); onUpdateChangeRequestSubmit?.(
milestone.id,
payload,
);
}} }}
onDelete={() => onDeleteChangeRequestSubmit?.(milestone.id)} onDelete={() =>
onDeleteChangeRequestSubmit?.(
milestone.id,
)
}
milestoneName={milestone.name} milestoneName={milestone.name}
status={status} status={status}
hasPendingUpdate={false} hasPendingUpdate={false}
@ -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,21 +476,38 @@ 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 =
showAutomation && milestone.transitionCondition ? (
<MilestoneAutomationSection status={status}> <MilestoneAutomationSection status={status}>
<MilestoneTransitionDisplay <MilestoneTransitionDisplay
intervalMinutes={milestone.transitionCondition.intervalMinutes} intervalMinutes={
milestone.transitionCondition
.intervalMinutes
}
onSave={async (payload) => { onSave={async (payload) => {
onUpdateChangeRequestSubmit?.(milestone.id, payload); onUpdateChangeRequestSubmit?.(
milestone.id,
payload,
);
}} }}
onDelete={() => onDeleteChangeRequestSubmit?.(milestone.id)} onDelete={() =>
onDeleteChangeRequestSubmit?.(
milestone.id,
)
}
milestoneName={milestone.name} milestoneName={milestone.name}
status={status} status={status}
hasPendingUpdate={false} hasPendingUpdate={false}
@ -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(
(change) =>
change.payload?.snapshot &&
(change.action === 'createMilestoneProgression' ||
change.action === 'updateMilestoneProgression'),
) || progressionChanges.find((change) => change.payload?.snapshot); ) || progressionChanges.find((change) => change.payload?.snapshot);
const basePlan = firstChangeWithSnapshot?.payload?.snapshot || currentReleasePlan; const basePlan =
firstChangeWithSnapshot?.payload?.snapshot || currentReleasePlan;
if (!basePlan) { if (!basePlan) {
console.error('[ConsolidatedProgressionChanges] No release plan data available', { console.error(
'[ConsolidatedProgressionChanges] No release plan data available',
{
hasSnapshot: !!firstChangeWithSnapshot, hasSnapshot: !!firstChangeWithSnapshot,
hasCurrentPlan: !!currentReleasePlan, hasCurrentPlan: !!currentReleasePlan,
progressionChanges 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(
'[ConsolidatedProgressionChanges] Conflicting changes detected for milestone:',
{
milestone: milestone.name, milestone: milestone.name,
hasCreate: !!createChange, hasCreate: !!createChange,
hasUpdate: !!updateChange, hasUpdate: !!updateChange,
hasDelete: !!deleteChange 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,35 +715,63 @@ 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 =
showAutomation &&
displayMilestone.transitionCondition ? (
<MilestoneAutomationSection status={status}> <MilestoneAutomationSection status={status}>
<MilestoneTransitionDisplay <MilestoneTransitionDisplay
intervalMinutes={displayMilestone.transitionCondition.intervalMinutes} intervalMinutes={
displayMilestone.transitionCondition
.intervalMinutes
}
onSave={async (payload) => { onSave={async (payload) => {
onUpdateChangeRequestSubmit?.(displayMilestone.id, payload); onUpdateChangeRequestSubmit?.(
displayMilestone.id,
payload,
);
}} }}
onDelete={() => onDeleteChangeRequestSubmit?.(displayMilestone.id)} onDelete={() =>
onDeleteChangeRequestSubmit?.(
displayMilestone.id,
)
}
milestoneName={displayMilestone.name} milestoneName={displayMilestone.name}
status={status} status={status}
hasPendingUpdate={false} hasPendingUpdate={false}
@ -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,7 +296,8 @@ type ChangeRequestStartMilestone = {
snapshot?: IReleasePlan; snapshot?: IReleasePlan;
}; };
type ChangeRequestCreateMilestoneProgression = CreateMilestoneProgressionSchema & { type ChangeRequestCreateMilestoneProgression =
CreateMilestoneProgressionSchema & {
snapshot?: IReleasePlan; snapshot?: IReleasePlan;
}; };

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

@ -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}