import type React from 'react'; import type { FC, ReactNode } from 'react'; import { Box, Button, styled, Tooltip, Typography } from '@mui/material'; import { Tab, Tabs, TabsList, TabPanel } from '@mui/base'; 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: 'flex', justifyContent: 'space-between', gap: theme.spacing(1), alignItems: 'center', 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 RightHandSide = styled('div')(({ theme }) => ({ display: 'flex', gap: theme.spacing(1), alignItems: 'center', })); const StyledTabList = styled(TabsList)(({ theme }) => ({ display: 'inline-flex', flexDirection: 'row', gap: theme.spacing(0.5), })); const StyledButton = styled(Button)(({ theme }) => ({ whiteSpace: 'nowrap', color: theme.palette.text.secondary, fontWeight: 'normal', '&[aria-selected="true"]': { fontWeight: 'bold', color: theme.palette.primary.main, background: theme.palette.background.elevation1, }, })); 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 ( value={0} slots={{ root: StyledButton }} > Change value={1} slots={{ root: StyledButton }} > View diff {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; }> = ({ change, actions }) => ( <> + Adding strategy:
{actions}
{change.payload.variants?.length ? ( Adding strategy variants: ) : null} ); export const DiffableChange: FC<{ actions?: ReactNode; change: | IChangeRequestAddStrategy | IChangeRequestDeleteStrategy | IChangeRequestUpdateStrategy; environmentName: string; featureName: string; projectId: string; changeRequestState: ChangeRequestState; }> = ({ actions, change, featureName, environmentName, projectId, changeRequestState, }) => { const currentStrategy = useCurrentStrategy( change, projectId, featureName, environmentName, ); return ( <> {change.action === 'addStrategy' && ( )} {change.action === 'deleteStrategy' && ( )} {change.action === 'updateStrategy' && ( )} ); };