From d2452b91f28309c86779a431d4f241a36f53cf76 Mon Sep 17 00:00:00 2001 From: "unleash-bot[bot]" <194219037+unleash-bot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 12:33:19 +0200 Subject: [PATCH] chore(AI): crDiffView flag cleanup (#10487) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR cleans up the crDiffView flag. These changes were automatically generated by AI and should be reviewed carefully. Fixes #10484 🧹 AI Flag Cleanup Summary This PR removes the crDiffView feature flag and its associated legacy components for displaying changes in a Change Request. The flag has been enabled and the new diff view is now permanent. This involved removing the feature flag from the configuration and code, deleting several legacy components, and updating the components that used them to only use the new versions. 🚮 Removed • Feature Flag Logic • All checks for the crDiffView flag. • The flag definition in uiConfig.ts, experimental.ts, and server-dev.ts. • Legacy Components • LegacyStrategyChange.tsx • StrategyTooltipLink.tsx • LegacyReleasePlanChange.tsx • SegmentTooltipLink.tsx • LegacySegmentChangeDetails.tsx • LegacyArchiveFeatureChange from ArchiveFeatureChange.tsx • LegacyDependencyChange from DependencyChange.tsx • LegacyToggleStatusChange from ToggleStatusChange.tsx 🛠 Kept • New Components • The new change request diff view components (StrategyChange, ReleasePlanChange, etc.) are now used directly. • The UI for displaying changes in a Change Request now consistently uses the improved diff view. 📝 Why The crDiffView feature flag was deemed complete and ready for permanent implementation. The cleanup follows standard procedure to remove the flag and associated dead code, simplifying the codebase and making it easier to maintain. This change makes the improved diff view for change requests the only available view. --------- Co-authored-by: unleash-bot <194219037+unleash-bot[bot]@users.noreply.github.com> Co-authored-by: Thomas Heartman --- .../ChangeRequest/ChangeRequest.test.tsx | 4 +- .../Changes/Change/ArchiveFeatureChange.tsx | 23 -- .../Changes/Change/ChangeActions.tsx | 8 +- .../Changes/Change/DependencyChange.tsx | 60 +-- .../EnvironmentStrategyExecutionOrder.tsx | 106 ++--- .../Changes/Change/FeatureChange.tsx | 53 +-- .../Change/LegacyReleasePlanChange.tsx | 316 --------------- .../Change/LegacySegmentChangeDetails.tsx | 129 ------ .../Changes/Change/LegacyStrategyChange.tsx | 371 ------------------ .../Changes/Change/SegmentChange.tsx | 8 +- .../Changes/Change/ToggleStatusChange.tsx | 28 +- .../ChangeRequest/SegmentTooltipLink.tsx | 91 ----- .../StrategyTooltipLink.test.tsx | 54 --- .../StrategyTooltipLink.tsx | 125 ------ frontend/src/interfaces/uiConfig.ts | 1 - src/lib/types/experimental.ts | 5 - src/server-dev.ts | 1 - 17 files changed, 48 insertions(+), 1335 deletions(-) delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacyReleasePlanChange.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacySegmentChangeDetails.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacyStrategyChange.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx diff --git a/frontend/src/component/changeRequest/ChangeRequest/ChangeRequest.test.tsx b/frontend/src/component/changeRequest/ChangeRequest/ChangeRequest.test.tsx index d1428770b9..03f4cfc36c 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/ChangeRequest.test.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/ChangeRequest.test.tsx @@ -203,9 +203,7 @@ test('Display default add strategy', async () => { expect(screen.getByText('feature1')).toBeInTheDocument(); expect(screen.getByText('Enabled')).toBeInTheDocument(); - expect( - screen.getByText('Default strategy will be added'), - ).toBeInTheDocument(); + expect(screen.getByText('Adding default strategy')).toBeInTheDocument(); }); test('Display default disable feature', async () => { diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ArchiveFeatureChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ArchiveFeatureChange.tsx index 1440fd0d7b..c740b05e2d 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ArchiveFeatureChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ArchiveFeatureChange.tsx @@ -1,33 +1,10 @@ import type { FC, ReactNode } from 'react'; import { Action, ChangeItemInfo, ChangeItemWrapper } from './Change.styles.tsx'; -import { styled } from '@mui/material'; -import { ChangeItemWrapper as LegacyChangeItemWrapper } from './LegacyStrategyChange.tsx'; type ArchiveFeatureChange = { actions?: ReactNode; }; -const ArchiveBox = styled('span')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - color: theme.palette.error.main, -})); - -/** - * Deprecated: use ArchiveFeatureChange instead; remove with flag crDiffView - * @deprecated - */ -export const LegacyArchiveFeatureChange: FC = ({ - actions, -}) => ( - - - Archiving flag - {actions} - - -); - export const ArchiveFeatureChange: FC = ({ actions }) => ( diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ChangeActions.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ChangeActions.tsx index 0b78ef0a3d..a32c55b6e8 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ChangeActions.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/ChangeActions.tsx @@ -28,7 +28,6 @@ import Delete from '@mui/icons-material/Delete'; import Edit from '@mui/icons-material/Edit'; import MoreVert from '@mui/icons-material/MoreVert'; import { EditChange } from './EditChange.tsx'; -import { useUiFlag } from 'hooks/useUiFlag.ts'; const useShowActions = (changeRequest: ChangeRequestType, change: IChange) => { const { isChangeRequestConfigured } = useChangeRequestsEnabled( @@ -74,9 +73,6 @@ export const ChangeActions: FC<{ const { showDiscard, showEdit } = useShowActions(changeRequest, change); const { discardChange } = useChangeRequestApi(); const { setToastData, setToastApiError } = useToast(); - const useNewCrView = useUiFlag('crDiffView'); - - const ButtonComponent = useNewCrView ? StyledIconButton : IconButton; const [editOpen, setEditOpen] = useState(false); @@ -121,7 +117,7 @@ export const ChangeActions: FC<{ show={ <> - - + ({ maxWidth: '100%', @@ -59,60 +58,3 @@ export const DependencyChange: FC<{ ); } }; - -const AddDependencyWrapper = styled(Box)(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - gap: theme.spacing(1), -})); - -/** - * @deprecated use DependencyChange instead; remove with flag crDiffView - */ -export const LegacyDependencyChange: FC<{ - actions?: ReactNode; - change: IChangeRequestAddDependency | IChangeRequestDeleteDependency; - projectId: string; - onNavigate?: () => void; -}> = ({ actions, change, projectId, onNavigate }) => { - return ( - <> - {change.action === 'addDependency' && ( - <> - - - - + Adding dependency - - - {change.payload.feature} - - {!change.payload.enabled ? ' (disabled)' : null} - {change.payload.variants?.length - ? `(${change.payload.variants?.join(', ')})` - : null} - - {actions} - - - )} - {change.action === 'deleteDependency' && ( - - - ({ - color: theme.palette.error.main, - })} - > - - Deleting dependencies - - - {actions} - - )} - - ); -}; diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EnvironmentStrategyExecutionOrder/EnvironmentStrategyExecutionOrder.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EnvironmentStrategyExecutionOrder/EnvironmentStrategyExecutionOrder.tsx index ea1b6de57d..8607e92014 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EnvironmentStrategyExecutionOrder/EnvironmentStrategyExecutionOrder.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EnvironmentStrategyExecutionOrder/EnvironmentStrategyExecutionOrder.tsx @@ -8,7 +8,6 @@ import { StrategyExecution } from 'component/feature/FeatureView/FeatureOverview import { formatStrategyName } from '../../../../../../utils/strategyNames.tsx'; import type { IFeatureStrategy } from 'interfaces/strategy.ts'; import { Tab, TabList, TabPanel, Tabs } from '../ChangeTabComponents.tsx'; -import { useUiFlag } from 'hooks/useUiFlag.ts'; import { ChangeItemInfo as NewChangeItemInfo, ChangeItemWrapper, @@ -63,7 +62,6 @@ export const EnvironmentStrategyExecutionOrder = ({ actions, }: IEnvironmentStrategyExecutionOrderProps) => { const { feature: featureData, loading } = useFeature(project, feature); - const useDiffableComponent = useUiFlag('crDiffView'); if (loading) return null; @@ -97,76 +95,40 @@ export const EnvironmentStrategyExecutionOrder = ({ strategyIds: updatedStrategies.map((strategy) => strategy.id), }; - if (useDiffableComponent) { - return ( - - - - - - Updating strategy execution order to - - -
- - View change - View diff - - {actions} -
-
- - - {updatedStrategies.map((strategy, index) => ( - - {`${index + 1}: `} - {formatStrategyName(strategy?.name || '')} - {strategy?.title && ` - ${strategy.title}`} - - - ))} - - - - - -
-
- ); - } - return ( - - - - } - tooltipProps={{ - maxWidth: 500, - maxHeight: 600, - }} - > - Updating strategy execution order to - - {actions} - - - {updatedStrategies.map((strategy, index) => ( - - {`${index + 1}: `} - {formatStrategyName(strategy?.name || '')} - {strategy?.title && ` - ${strategy.title}`} - - - ))} - - + + + + + Updating strategy execution order to + +
+ + View change + View diff + + {actions} +
+
+ + + {updatedStrategies.map((strategy, index) => ( + + {`${index + 1}: `} + {formatStrategyName(strategy?.name || '')} + {strategy?.title && ` - ${strategy.title}`} + + + ))} + + + + + +
+
); }; diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx index 6d3eecfe0e..d63c05ede5 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/FeatureChange.tsx @@ -7,26 +7,14 @@ import type { import { objectId } from 'utils/objectId'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { Alert, Box, styled } from '@mui/material'; -import { - LegacyToggleStatusChange, - ToggleStatusChange, -} from './ToggleStatusChange.tsx'; -import { LegacyStrategyChange } from './LegacyStrategyChange.tsx'; +import { ToggleStatusChange } from './ToggleStatusChange.tsx'; import { VariantPatch } from './VariantPatch/VariantPatch.tsx'; import { EnvironmentStrategyExecutionOrder } from './EnvironmentStrategyExecutionOrder/EnvironmentStrategyExecutionOrder.tsx'; -import { - ArchiveFeatureChange, - LegacyArchiveFeatureChange, -} from './ArchiveFeatureChange.tsx'; -import { - DependencyChange, - LegacyDependencyChange, -} from './DependencyChange.tsx'; +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'; const StyledSingleChangeBox = styled(Box, { shouldForwardProp: (prop: string) => !prop.startsWith('$'), @@ -82,10 +70,6 @@ const InlineList = styled('ul')(({ theme }) => ({ const ChangeInnerBox = styled(Box)(({ theme }) => ({ padding: theme.spacing(3), - // todo: remove with flag crDiffView - '&:has(.delete-strategy-information-wrapper)': { - backgroundColor: theme.palette.error.light, - }, })); export const FeatureChange: FC<{ @@ -109,27 +93,6 @@ export const FeatureChange: FC<{ ? feature.changes.length + 1 : feature.changes.length; - const useDiffableChangeComponent = useUiFlag('crDiffView'); - const StrategyChangeComponent = useDiffableChangeComponent - ? StrategyChange - : LegacyStrategyChange; - - const ReleasePlanChangeComponent = useDiffableChangeComponent - ? ReleasePlanChange - : LegacyReleasePlanChange; - - const ArchiveFlagComponent = useDiffableChangeComponent - ? ArchiveFeatureChange - : LegacyArchiveFeatureChange; - - const DependencyChangeComponent = useDiffableChangeComponent - ? DependencyChange - : LegacyDependencyChange; - - const StatusChangeComponent = useDiffableChangeComponent - ? ToggleStatusChange - : LegacyToggleStatusChange; - return ( {(change.action === 'addDependency' || change.action === 'deleteDependency') && ( - )} {change.action === 'updateEnabled' && ( - )} {change.action === 'archiveFeature' && ( - + )} {change.action === 'addStrategy' || change.action === 'deleteStrategy' || change.action === 'updateStrategy' ? ( - ({ - 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/LegacySegmentChangeDetails.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacySegmentChangeDetails.tsx deleted file mode 100644 index 11de3e5882..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacySegmentChangeDetails.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import type React from 'react'; -import type { FC, ReactNode } from 'react'; -import { Box, styled, Typography } from '@mui/material'; -import type { - ChangeRequestState, - IChangeRequestDeleteSegment, - IChangeRequestUpdateSegment, -} from 'component/changeRequest/changeRequest.types'; -import { useSegment } from 'hooks/api/getters/useSegment/useSegment'; -import { SegmentDiff, SegmentTooltipLink } from '../../SegmentTooltipLink.tsx'; - -import { ViewableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/ViewableConstraintsList'; - -import { ChangeOverwriteWarning } from './ChangeOverwriteWarning/ChangeOverwriteWarning.tsx'; - -const ChangeItemCreateEditWrapper = styled(Box)(({ theme }) => ({ - display: 'grid', - gridTemplateColumns: 'auto 40px', - gap: theme.spacing(1), - alignItems: 'center', - width: '100%', - margin: theme.spacing(0, 0, 1, 0), -})); - -export const ChangeItemWrapper = styled(Box)({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', -}); - -const ChangeItemInfo: FC<{ children?: React.ReactNode }> = styled(Box)( - ({ theme }) => ({ - display: 'grid', - gridTemplateColumns: '150px auto', - gridAutoFlow: 'column', - alignItems: 'center', - flexGrow: 1, - gap: theme.spacing(1), - }), -); - -const SegmentContainer = styled(Box, { - shouldForwardProp: (prop) => prop !== 'conflict', -})<{ conflict: string | undefined }>(({ theme, conflict }) => ({ - borderLeft: '1px solid', - borderRight: '1px solid', - borderTop: '1px solid', - borderBottom: '1px solid', - borderColor: conflict - ? theme.palette.warning.border - : theme.palette.divider, - borderTopColor: theme.palette.divider, - padding: theme.spacing(3), - borderRadius: `0 0 ${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px`, -})); - -/** - * Deprecated: use SegmentChangeDetails instead. Remove file with flag crDiffView - * @deprecated - */ -export const LegacySegmentChangeDetails: FC<{ - actions?: ReactNode; - change: IChangeRequestUpdateSegment | IChangeRequestDeleteSegment; - changeRequestState: ChangeRequestState; -}> = ({ actions, change, changeRequestState }) => { - const { segment: currentSegment } = useSegment(change.payload.id); - const snapshotSegment = change.payload.snapshot; - const previousName = - changeRequestState === 'Applied' - ? change.payload?.snapshot?.name - : currentSegment?.name; - const referenceSegment = - changeRequestState === 'Applied' ? snapshotSegment : currentSegment; - - return ( - - {change.action === 'deleteSegment' && ( - - - ({ - color: theme.palette.error.main, - })} - > - - Deleting segment - - - - - -
{actions}
-
- )} - {change.action === 'updateSegment' && ( - <> - - - - Editing segment - - - - -
{actions}
-
- - - )} -
- ); -}; diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacyStrategyChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacyStrategyChange.tsx deleted file mode 100644 index b9b7f92850..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/LegacyStrategyChange.tsx +++ /dev/null @@ -1,371 +0,0 @@ -import type React from 'react'; -import type { FC, ReactNode } from 'react'; -import { Box, styled, Tooltip, Typography } from '@mui/material'; -import BlockIcon from '@mui/icons-material/Block'; -import TrackChangesIcon from '@mui/icons-material/TrackChanges'; -import { - StrategyDiff, - StrategyTooltipLink, -} from '../../StrategyTooltipLink/StrategyTooltipLink.tsx'; -import { StrategyExecution } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution'; -import type { - ChangeRequestState, - IChangeRequestAddStrategy, - IChangeRequestDeleteStrategy, - IChangeRequestUpdateStrategy, -} from 'component/changeRequest/changeRequest.types'; -import { useCurrentStrategy } from './hooks/useCurrentStrategy.ts'; -import { Badge } from 'component/common/Badge/Badge'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; -import { flexRow } from 'themes/themeStyles'; -import { EnvironmentVariantsTable } from 'component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsCard/EnvironmentVariantsTable/EnvironmentVariantsTable'; -import { ChangeOverwriteWarning } from './ChangeOverwriteWarning/ChangeOverwriteWarning.tsx'; -import type { IFeatureStrategy } from 'interfaces/strategy'; - -export const ChangeItemWrapper = styled(Box)({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', -}); - -const ChangeItemCreateEditDeleteWrapper = styled(Box)(({ theme }) => ({ - 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: 'grid', - gridTemplateColumns: '150px auto', - gridAutoFlow: 'column', - alignItems: 'center', - flexGrow: 1, - gap: theme.spacing(1), - }), -); - -const StyledBox: FC<{ children?: React.ReactNode }> = styled(Box)( - ({ theme }) => ({ - marginTop: theme.spacing(2), - }), -); - -const StyledTypography: FC<{ children?: React.ReactNode }> = styled(Typography)( - ({ theme }) => ({ - margin: `${theme.spacing(1)} 0`, - }), -); - -const DisabledEnabledState: FC<{ show?: boolean; disabled: boolean }> = ({ - show = true, - disabled, -}) => { - if (!show) { - return null; - } - - if (disabled) { - return ( - - }> - Disabled - - - ); - } - - return ( - - }> - Enabled - - - ); -}; - -const EditHeader: FC<{ - wasDisabled?: boolean; - willBeDisabled?: boolean; -}> = ({ wasDisabled = false, willBeDisabled = false }) => { - if (wasDisabled && willBeDisabled) { - return ( - Editing strategy - ); - } - - if (!wasDisabled && willBeDisabled) { - return Editing strategy; - } - - if (wasDisabled && !willBeDisabled) { - return Editing strategy; - } - - return Editing strategy; -}; - -const hasDiff = (object: unknown, objectToCompare: unknown) => - JSON.stringify(object) !== JSON.stringify(objectToCompare); - -const DeleteStrategy: FC<{ - change: IChangeRequestDeleteStrategy; - changeRequestState: ChangeRequestState; - currentStrategy: IFeatureStrategy | undefined; - actions?: ReactNode; -}> = ({ change, changeRequestState, currentStrategy, actions }) => { - const name = - changeRequestState === 'Applied' - ? change.payload?.snapshot?.name - : currentStrategy?.name; - const title = - changeRequestState === 'Applied' - ? change.payload?.snapshot?.title - : currentStrategy?.title; - const referenceStrategy = - changeRequestState === 'Applied' - ? change.payload.snapshot - : currentStrategy; - - return ( - <> - - - ({ - color: theme.palette.error.main, - })} - > - - Deleting strategy - - - - - -
{actions}
-
- {referenceStrategy && ( - - )} - - ); -}; - -const UpdateStrategy: FC<{ - change: IChangeRequestUpdateStrategy; - changeRequestState: ChangeRequestState; - currentStrategy: IFeatureStrategy | undefined; - actions?: ReactNode; -}> = ({ change, changeRequestState, currentStrategy, actions }) => { - const previousTitle = - changeRequestState === 'Applied' - ? change.payload.snapshot?.title - : currentStrategy?.title; - const referenceStrategy = - changeRequestState === 'Applied' - ? change.payload.snapshot - : currentStrategy; - const hasVariantDiff = hasDiff( - referenceStrategy?.variants || [], - change.payload.variants || [], - ); - - return ( - <> - - - - - - - - -
{actions}
-
- theme.spacing(2), - marginBottom: (theme) => theme.spacing(2), - ...flexRow, - gap: (theme) => theme.spacing(1), - }} - > - This strategy will be{' '} - - - } - /> - - {hasVariantDiff ? ( - - {change.payload.variants?.length ? ( - <> - - {currentStrategy?.variants?.length - ? 'Updating strategy variants to:' - : 'Adding strategy variants:'} - - - - ) : ( - - Removed all strategy variants. - - )} - - ) : null} - - ); -}; - -const AddStrategy: FC<{ - change: IChangeRequestAddStrategy; - actions?: ReactNode; - isDefaultChange?: boolean; -}> = ({ change, actions, isDefaultChange }) => ( - <> - - - - + Adding strategy - - - - -
- -
-
-
- {isDefaultChange ? ( - - Default strategy will be added - - ) : null} - {actions} -
-
- - {change.payload.variants?.length ? ( - - Adding strategy variants: - - - ) : null} - -); - -/** - * Deprecated: use StrategyChange instead. Remove file with flag crDiffView - * @deprecated - */ -export const LegacyStrategyChange: FC<{ - actions?: ReactNode; - change: - | IChangeRequestAddStrategy - | IChangeRequestDeleteStrategy - | IChangeRequestUpdateStrategy; - environmentName: string; - featureName: string; - projectId: string; - changeRequestState: ChangeRequestState; - isDefaultChange?: boolean; -}> = ({ - actions, - change, - featureName, - environmentName, - projectId, - changeRequestState, - isDefaultChange, -}) => { - const currentStrategy = useCurrentStrategy( - change, - projectId, - featureName, - environmentName, - ); - - return ( - <> - {change.action === 'addStrategy' && ( - - )} - {change.action === 'deleteStrategy' && ( - - )} - {change.action === 'updateStrategy' && ( - - )} - - ); -}; diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/SegmentChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/SegmentChange.tsx index 3a9e5517c4..ad3bb088b0 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/SegmentChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/SegmentChange.tsx @@ -5,11 +5,9 @@ import type { ChangeRequestState, ISegmentChange, } from '../../../changeRequest.types'; -import { LegacySegmentChangeDetails } from './LegacySegmentChangeDetails.tsx'; import { SegmentChangeDetails } from './SegmentChangeDetails.tsx'; import { ConflictWarning } from './ConflictWarning.tsx'; import { useSegment } from 'hooks/api/getters/useSegment/useSegment.ts'; -import { useUiFlag } from 'hooks/useUiFlag.ts'; interface ISegmentChangeProps { segmentChange: ISegmentChange; @@ -26,10 +24,6 @@ export const SegmentChange: FC = ({ }) => { const { segment } = useSegment(segmentChange.payload.id); - const ChangeDetails = useUiFlag('crDiffView') - ? SegmentChangeDetails - : LegacySegmentChangeDetails; - return ( = ({ - ( ); -/** - * @deprecated use ToggleStatusChange instead; remove with flag crDiffView - */ -export const LegacyToggleStatusChange: FC = ({ - enabled, - actions, - isDefaultChange, -}) => { - return ( - - - New status - ({ marginLeft: theme.spacing(1) })} - color={enabled ? 'success' : 'error'} - > - {enabled ? ' Enabled' : 'Disabled'} - - - {isDefaultChange ? : null} - {actions} - - ); -}; - export const ToggleStatusChange: FC = ({ enabled, actions, diff --git a/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx b/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx deleted file mode 100644 index c569d9f5a1..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx +++ /dev/null @@ -1,91 +0,0 @@ -// deprecated: remove with flag crDiffView -import type { - IChangeRequestDeleteSegment, - IChangeRequestUpdateSegment, -} from 'component/changeRequest/changeRequest.types'; -import type React from 'react'; -import type { FC } from 'react'; -import { EventDiff } from 'component/events/EventDiff/EventDiff'; -import omit from 'lodash.omit'; -import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; -import { styled } from '@mui/material'; -import { textTruncated } from 'themes/themeStyles'; -import type { ISegment } from 'interfaces/segment'; -import { NameWithChangeInfo } from './Changes/Change/NameWithChangeInfo/NameWithChangeInfo.tsx'; - -const StyledCodeSection = styled('div')(({ theme }) => ({ - overflowX: 'auto', - '& code': { - wordWrap: 'break-word', - whiteSpace: 'pre-wrap', - fontFamily: 'monospace', - lineHeight: 1.5, - fontSize: theme.fontSizes.smallBody, - }, -})); - -export const SegmentDiff: FC<{ - change: IChangeRequestUpdateSegment | IChangeRequestDeleteSegment; - currentSegment?: ISegment; -}> = ({ change, currentSegment }) => { - const changeRequestSegment = - change.action === 'deleteSegment' ? undefined : change.payload; - - return ( - - - - ); -}; -interface IStrategyTooltipLinkProps { - children?: React.ReactNode; - name?: string; - previousName?: string; -} - -const StyledContainer: FC<{ children?: React.ReactNode }> = styled('div')( - ({ theme }) => ({ - display: 'grid', - gridAutoFlow: 'column', - gridTemplateColumns: 'auto 1fr', - gap: theme.spacing(1), - alignItems: 'center', - }), -); - -const ViewDiff = styled('span')(({ theme }) => ({ - color: theme.palette.primary.main, - marginLeft: theme.spacing(1), -})); - -const Truncated = styled('div')(() => ({ - ...textTruncated, - maxWidth: 500, - display: 'flex', -})); - -export const SegmentTooltipLink: FC = ({ - name, - previousName, - children, -}) => ( - - - - - View Diff - - - -); diff --git a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx b/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx deleted file mode 100644 index 2443c548e0..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { render } from 'utils/testRenderer'; -import { screen } from '@testing-library/react'; -import { StrategyDiff } from './StrategyTooltipLink.tsx'; -import type { IFeatureStrategy } from 'interfaces/strategy'; -import type { IChangeRequestUpdateStrategy } from 'component/changeRequest/changeRequest.types'; - -test('Should not render the `snapshot` property', async () => { - const existingStrategy: IFeatureStrategy = { - name: 'flexibleRollout', - constraints: [], - variants: [], - parameters: { - groupId: 'aaa', - rollout: '71', - stickiness: 'default', - }, - sortOrder: 0, - id: '31572930-2db7-461f-813b-3eedc200cb33', - title: '', - disabled: false, - segments: [], - }; - - const change: IChangeRequestUpdateStrategy = { - id: 39, - action: 'updateStrategy' as const, - payload: { - id: '31572930-2db7-461f-813b-3eedc200cb33', - name: 'flexibleRollout', - title: '', - disabled: false, - segments: [], - snapshot: existingStrategy, - variants: [], - parameters: { - groupId: 'aaa', - rollout: '38', - stickiness: 'default', - }, - constraints: [], - }, - createdAt: new Date('2024-01-18T07:58:36.314Z'), - createdBy: { - id: 1, - username: 'admin', - imageUrl: - 'https://gravatar.com/avatar/8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918?s=42&d=retro&r=g', - }, - }; - - render(); - - expect(screen.queryByText(/snapshot/)).toBeNull(); -}); diff --git a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx b/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx deleted file mode 100644 index ca1a64c50b..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx +++ /dev/null @@ -1,125 +0,0 @@ -// deprecated: remove with flag crDiffView -import type { - IChangeRequestAddStrategy, - IChangeRequestDeleteStrategy, - IChangeRequestUpdateStrategy, -} from 'component/changeRequest/changeRequest.types'; -import type React from 'react'; -import type { FC } from 'react'; -import { - formatStrategyName, - GetFeatureStrategyIcon, -} from 'utils/strategyNames'; -import { EventDiff } from 'component/events/EventDiff/EventDiff'; -import omit from 'lodash.omit'; -import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; -import { Typography, styled } from '@mui/material'; -import type { IFeatureStrategy } from 'interfaces/strategy'; -import { textTruncated } from 'themes/themeStyles'; -import { NameWithChangeInfo } from '../Changes/Change/NameWithChangeInfo/NameWithChangeInfo.tsx'; - -const StyledCodeSection = styled('div')(({ theme }) => ({ - overflowX: 'auto', - '& code': { - wordWrap: 'break-word', - whiteSpace: 'pre-wrap', - fontFamily: 'monospace', - lineHeight: 1.5, - fontSize: theme.fontSizes.smallBody, - }, -})); - -const sortSegments = ( - item?: T, -): T | undefined => { - if (!item || !item.segments) { - return item; - } - return { - ...item, - segments: [...item.segments].sort((a, b) => a - b), - }; -}; - -export const StrategyDiff: FC<{ - change: - | IChangeRequestAddStrategy - | IChangeRequestUpdateStrategy - | IChangeRequestDeleteStrategy; - currentStrategy?: IFeatureStrategy; -}> = ({ change, currentStrategy }) => { - const changeRequestStrategy = - change.action === 'deleteStrategy' ? undefined : change.payload; - - const sortedCurrentStrategy = sortSegments(currentStrategy); - const sortedChangeRequestStrategy = sortSegments(changeRequestStrategy); - - return ( - - - - ); -}; - -interface IStrategyTooltipLinkProps { - name: string; - title?: string; - previousTitle?: string; - children?: React.ReactNode; -} - -const StyledContainer: FC<{ children?: React.ReactNode }> = styled('div')( - ({ theme }) => ({ - display: 'grid', - gridAutoFlow: 'column', - gridTemplateColumns: 'auto 1fr', - gap: theme.spacing(1), - alignItems: 'center', - }), -); - -const ViewDiff = styled('span')(({ theme }) => ({ - color: theme.palette.primary.main, - marginLeft: theme.spacing(1), -})); - -const Truncated = styled('div')(() => ({ - ...textTruncated, - maxWidth: 500, -})); - -export const StrategyTooltipLink: FC = ({ - name, - title, - previousTitle, - children, -}) => { - return ( - - - - - {formatStrategyName(name)} - - - View Diff - - - - - ); -}; diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index 2c85786f61..58f7375d89 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -89,7 +89,6 @@ export type UiFlags = { lifecycleMetrics?: boolean; createFlagDialogCache?: boolean; impactMetrics?: boolean; - crDiffView?: boolean; changeRequestApproverEmails?: boolean; reportUnknownFlags?: boolean; lifecycleGraphs?: boolean; diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 6378a9cb4e..5b4d2fdc99 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -58,7 +58,6 @@ export type IFlagKey = | 'customMetrics' | 'impactMetrics' | 'createFlagDialogCache' - | 'crDiffView' | 'changeRequestApproverEmails' | 'paygTrialEvents' | 'paygInstanceStatsEvents' @@ -274,10 +273,6 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENTAL_CHANGE_REQUEST_APPROVER_EMAILS, false, ), - crDiffView: parseEnvVarBoolean( - process.env.UNLEASH_EXPERIMENTAL_CR_DIFF_VIEW, - false, - ), impactMetrics: parseEnvVarBoolean( process.env.UNLEASH_EXPERIMENTAL_IMPACT_METRICS, false, diff --git a/src/server-dev.ts b/src/server-dev.ts index eefb22fd36..904b36c06b 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -55,7 +55,6 @@ process.nextTick(async () => { customMetrics: true, lifecycleMetrics: true, impactMetrics: true, - crDiffView: true, paygTrialEvents: true, lifecycleGraphs: true, addConfiguration: true,