diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx index d3c90457a3..742374bfbb 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx @@ -14,6 +14,7 @@ import { EnvironmentStrategyExecutionOrder } from './EnvironmentStrategyExecutio import { ArchiveFeatureChange } from './ArchiveFeatureChange.tsx'; import { DependencyChange } from './DependencyChange.tsx'; import { Link } from 'react-router-dom'; +import { LegacyReleasePlanChange } from './LegacyReleasePlanChange.tsx'; import { ReleasePlanChange } from './ReleasePlanChange.tsx'; import { StrategyChange } from './StrategyChange.tsx'; import { useUiFlag } from 'hooks/useUiFlag.ts'; @@ -94,6 +95,10 @@ export const FeatureChange: FC<{ ? StrategyChange : LegacyStrategyChange; + const ReleasePlanChangeComponent = useDiffableChangeComponent + ? ReleasePlanChange + : LegacyReleasePlanChange; + return ( ({ + display: 'grid', + gridTemplateColumns: 'auto auto', + justifyContent: 'space-between', + gap: theme.spacing(1), + alignItems: 'center', + marginBottom: theme.spacing(2), + width: '100%', +})); + +const ChangeItemInfo: FC<{ children?: React.ReactNode }> = styled(Box)( + ({ theme }) => ({ + display: 'flex', + gap: theme.spacing(1), + }), +); + +const ViewDiff = styled('span')(({ theme }) => ({ + color: theme.palette.primary.main, + marginLeft: theme.spacing(1), +})); + +const StyledCodeSection = styled('div')(({ theme }) => ({ + overflowX: 'auto', + '& code': { + wordWrap: 'break-word', + whiteSpace: 'pre-wrap', + fontFamily: 'monospace', + lineHeight: 1.5, + fontSize: theme.fontSizes.smallBody, + }, +})); + +const DeleteReleasePlan: FC<{ + change: IChangeRequestDeleteReleasePlan; + currentReleasePlan?: IReleasePlan; + changeRequestState: ChangeRequestState; + actions?: ReactNode; +}> = ({ change, currentReleasePlan, changeRequestState, actions }) => { + const releasePlan = + changeRequestState === 'Applied' && change.payload.snapshot + ? change.payload.snapshot + : currentReleasePlan; + + if (!releasePlan) return; + + return ( + <> + + + ({ + color: theme.palette.error.main, + })} + > + - Deleting release plan: + + {releasePlan.name} + +
{actions}
+
+ + + ); +}; + +const StartMilestone: FC<{ + change: IChangeRequestStartMilestone; + currentReleasePlan?: IReleasePlan; + changeRequestState: ChangeRequestState; + actions?: ReactNode; +}> = ({ change, currentReleasePlan, changeRequestState, actions }) => { + const releasePlan = + changeRequestState === 'Applied' && change.payload.snapshot + ? change.payload.snapshot + : currentReleasePlan; + + if (!releasePlan) return; + + const previousMilestone = releasePlan.milestones.find( + (milestone) => milestone.id === releasePlan.activeMilestoneId, + ); + + const newMilestone = releasePlan.milestones.find( + (milestone) => milestone.id === change.payload.milestoneId, + ); + + if (!newMilestone) return; + + return ( + <> + + + + + Start milestone: + + {newMilestone.name} + + + + } + tooltipProps={{ + maxWidth: 500, + maxHeight: 600, + }} + > + View Diff + + +
{actions}
+
+ + + ); +}; + +const AddReleasePlan: FC<{ + change: IChangeRequestAddReleasePlan; + currentReleasePlan?: IReleasePlan; + environmentName: string; + featureName: string; + actions?: ReactNode; +}> = ({ + change, + currentReleasePlan, + environmentName, + featureName, + actions, +}) => { + const [currentTooltipOpen, setCurrentTooltipOpen] = useState(false); + const currentTooltipCloseTimeoutRef = useRef(); + const openCurrentTooltip = () => { + if (currentTooltipCloseTimeoutRef.current) { + clearTimeout(currentTooltipCloseTimeoutRef.current); + } + setCurrentTooltipOpen(true); + }; + const closeCurrentTooltip = () => { + currentTooltipCloseTimeoutRef.current = setTimeout(() => { + setCurrentTooltipOpen(false); + }, 100); + }; + + const planPreview = useReleasePlanPreview( + change.payload.templateId, + featureName, + environmentName, + ); + + const planPreviewDiff = { + ...planPreview, + discriminator: 'plan', + releasePlanTemplateId: change.payload.templateId, + }; + + return ( + <> + + + {currentReleasePlan ? ( + + Replacing{' '} + + openCurrentTooltip() + } + onMouseLeave={() => + closeCurrentTooltip() + } + > + + + } + tooltipProps={{ + open: currentTooltipOpen, + maxWidth: 500, + maxHeight: 600, + }} + > + openCurrentTooltip()} + onMouseLeave={() => closeCurrentTooltip()} + > + current + + {' '} + release plan with: + + ) : ( + + + Adding release plan: + + )} + {planPreview.name} + {currentReleasePlan && ( + + + + } + tooltipProps={{ + maxWidth: 500, + maxHeight: 600, + }} + > + View Diff + + )} + +
{actions}
+
+ + + ); +}; + +/** + * Deprecated: use ReleasePlanChange instead. Remove file with flag crDiffView + * @deprecated + */ +export const LegacyReleasePlanChange: FC<{ + actions?: ReactNode; + change: + | IChangeRequestAddReleasePlan + | IChangeRequestDeleteReleasePlan + | IChangeRequestStartMilestone; + environmentName: string; + featureName: string; + projectId: string; + changeRequestState: ChangeRequestState; +}> = ({ + actions, + change, + featureName, + environmentName, + projectId, + changeRequestState, +}) => { + const { releasePlans } = useReleasePlans( + projectId, + featureName, + environmentName, + ); + const currentReleasePlan = releasePlans[0]; + + return ( + <> + {change.action === 'addReleasePlan' && ( + + )} + {change.action === 'deleteReleasePlan' && ( + + )} + {change.action === 'startMilestone' && ( + + )} + + ); +}; diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ReleasePlanChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ReleasePlanChange.tsx index 7511884a7d..7cabd17f99 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ReleasePlanChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ReleasePlanChange.tsx @@ -10,10 +10,11 @@ import type { import { useReleasePlanPreview } from 'hooks/useReleasePlanPreview'; import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans'; import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; -import EventDiff from 'component/events/EventDiff/EventDiff'; +import { EventDiff } from 'component/events/EventDiff/EventDiff'; import { ReleasePlan } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan'; import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone'; import type { IReleasePlan } from 'interfaces/releasePlans'; +import { Tab, TabList, TabPanel, Tabs } from './ChangeTabComponents.tsx'; export const ChangeItemWrapper = styled(Box)({ display: 'flex', @@ -111,36 +112,34 @@ const StartMilestone: FC<{ if (!newMilestone) return; return ( - <> + + Start milestone: {newMilestone.name} - - - - } - tooltipProps={{ - maxWidth: 500, - maxHeight: 600, - }} - > - View Diff - -
{actions}
+
+ + Change + View diff + + {actions} +
- - + + + + + + +
); }; @@ -183,75 +182,78 @@ const AddReleasePlan: FC<{ releasePlanTemplateId: change.payload.templateId, }; - return ( - <> - - - {currentReleasePlan ? ( - - Replacing{' '} - - openCurrentTooltip() - } - onMouseLeave={() => - closeCurrentTooltip() - } - > - - - } - tooltipProps={{ - open: currentTooltipOpen, - maxWidth: 500, - maxHeight: 600, - }} - > - openCurrentTooltip()} - onMouseLeave={() => closeCurrentTooltip()} - > - current - - {' '} - release plan with: - - ) : ( + if (!currentReleasePlan) { + return ( + <> + + + Adding release plan: - )} - {planPreview.name} - {currentReleasePlan && ( + {planPreview.name} + +
{actions}
+
+ + + ); + } + + return ( + + + + + Replacing{' '} - openCurrentTooltip()} + onMouseLeave={() => closeCurrentTooltip()} + > + - + } tooltipProps={{ + open: currentTooltipOpen, maxWidth: 500, maxHeight: 600, }} > - View Diff - - )} + openCurrentTooltip()} + onMouseLeave={() => closeCurrentTooltip()} + > + current + + {' '} + release plan with: + + {planPreview.name} -
{actions}
+
+ + Changes + View diff + + {actions} +
- - + + + + + + +
); };