1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00
unleash.unleash/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ConsolidatedProgressionChanges.tsx

177 lines
5.9 KiB
TypeScript

import type { FC } from 'react';
import { styled } from '@mui/material';
import type {
ChangeRequestState,
IChangeRequestChangeMilestoneProgression,
IChangeRequestDeleteMilestoneProgression,
IChangeRequestFeature,
} from 'component/changeRequest/changeRequest.types';
import type { IReleasePlan } from 'interfaces/releasePlans';
import { Tab, TabList, TabPanel, Tabs } from './ChangeTabComponents.tsx';
import {
Added,
ChangeItemInfo,
ChangeItemWrapper,
Deleted,
} from './Change.styles.tsx';
import type { ChangeMilestoneProgressionSchema } from 'openapi';
import { MilestoneListRenderer } from './MilestoneListRenderer.tsx';
import { applyProgressionChanges } from './applyProgressionChanges.js';
import { EventDiff } from 'component/events/EventDiff/EventDiff';
const StyledTabs = styled(Tabs)(({ theme }) => ({
display: 'flex',
flexFlow: 'column',
gap: theme.spacing(1),
}));
type ProgressionChange =
| IChangeRequestChangeMilestoneProgression
| IChangeRequestDeleteMilestoneProgression;
const getFirstChangeWithSnapshot = (
progressionChanges: ProgressionChange[],
) => {
return (
progressionChanges.find(
(change) =>
change.payload?.snapshot &&
change.action === 'changeMilestoneProgression',
) || progressionChanges.find((change) => change.payload?.snapshot)
);
};
const getMilestonesWithAutomation = (
progressionChanges: ProgressionChange[],
): Set<string> => {
return new Set(
progressionChanges
.filter((change) => change.action === 'changeMilestoneProgression')
.map((change) => change.payload.sourceMilestone)
.filter((id): id is string => Boolean(id)),
);
};
const getMilestonesWithDeletedAutomation = (
progressionChanges: ProgressionChange[],
): Set<string> => {
return new Set(
progressionChanges
.filter((change) => change.action === 'deleteMilestoneProgression')
.map((change) => change.payload.sourceMilestone)
.filter((id): id is string => Boolean(id)),
);
};
const getChangeDescriptions = (
progressionChanges: ProgressionChange[],
basePlan: IReleasePlan,
): string[] => {
return progressionChanges.map((change) => {
const sourceId = change.payload.sourceMilestone;
const sourceName =
basePlan.milestones.find((milestone) => milestone.id === sourceId)
?.name || sourceId;
const action =
change.action === 'changeMilestoneProgression'
? 'Changing'
: 'Deleting';
return `${action} automation for ${sourceName}`;
});
};
export const ConsolidatedProgressionChanges: FC<{
feature: IChangeRequestFeature;
currentReleasePlan?: IReleasePlan;
changeRequestState: ChangeRequestState;
onUpdateChangeRequestSubmit?: (
sourceMilestoneId: string,
payload: ChangeMilestoneProgressionSchema,
) => Promise<void>;
onDeleteChangeRequestSubmit?: (sourceMilestoneId: string) => Promise<void>;
}> = ({
feature,
currentReleasePlan,
changeRequestState,
onUpdateChangeRequestSubmit,
onDeleteChangeRequestSubmit,
}) => {
// Get all progression changes for this feature
const progressionChanges = feature.changes.filter(
(
change,
): change is
| IChangeRequestChangeMilestoneProgression
| IChangeRequestDeleteMilestoneProgression =>
change.action === 'changeMilestoneProgression' ||
change.action === 'deleteMilestoneProgression',
);
if (progressionChanges.length === 0) return null;
const firstChangeWithSnapshot =
getFirstChangeWithSnapshot(progressionChanges);
const basePlan =
firstChangeWithSnapshot?.payload?.snapshot || currentReleasePlan;
if (!basePlan) {
return null;
}
const modifiedPlan = applyProgressionChanges(basePlan, progressionChanges);
const milestonesWithAutomation =
getMilestonesWithAutomation(progressionChanges);
const milestonesWithDeletedAutomation =
getMilestonesWithDeletedAutomation(progressionChanges);
const changeDescriptions = getChangeDescriptions(
progressionChanges,
basePlan,
);
return (
<StyledTabs>
<ChangeItemWrapper>
<ChangeItemInfo>
{progressionChanges.map((change, index) => {
const Component =
change.action === 'deleteMilestoneProgression'
? Deleted
: Added;
return (
<Component key={index}>
{changeDescriptions[index]}
</Component>
);
})}
</ChangeItemInfo>
<div>
<TabList>
<Tab>View change</Tab>
<Tab>View diff</Tab>
</TabList>
</div>
</ChangeItemWrapper>
<TabPanel>
<MilestoneListRenderer
plan={modifiedPlan}
changeRequestState={changeRequestState}
milestonesWithAutomation={milestonesWithAutomation}
milestonesWithDeletedAutomation={
milestonesWithDeletedAutomation
}
onUpdateAutomation={onUpdateChangeRequestSubmit}
onDeleteAutomation={onDeleteChangeRequestSubmit}
/>
</TabPanel>
<TabPanel variant='diff'>
<EventDiff
entry={{
preData: basePlan,
data: modifiedPlan,
}}
/>
</TabPanel>
</StyledTabs>
);
};