import React, { FC, VFC } from 'react'; import { Alert, Box, styled } from '@mui/material'; import { ChangeRequestFeatureToggleChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ChangeRequestFeatureToggleChange'; import { objectId } from 'utils/objectId'; import { ToggleStatusChange } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/ToggleStatusChange'; import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi'; import { formatUnknownError } from 'utils/formatUnknownError'; import useToast from 'hooks/useToast'; import type { IChange, IChangeRequest, IChangeRequestFeature, } from '../changeRequest.types'; import { hasNameField } from '../changeRequest.types'; import { Discard, StrategyAddedChange, StrategyDeletedChange, StrategyEditedChange, } from '../ChangeRequestOverview/ChangeRequestFeatureToggleChange/StrategyChange'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled'; import { StrategyExecution } from '../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution'; import { CodeSnippetPopover, PopoverDiff, } from './CodeSnippetPopover/CodeSnippetPopover'; interface IChangeRequestProps { changeRequest: IChangeRequest; onRefetch?: () => void; onNavigate?: () => void; } const StyledSingleChangeBox = styled(Box, { shouldForwardProp: (prop: string) => !prop.startsWith('$'), })<{ $hasConflict: boolean; $isAfterWarning: boolean; $isLast: boolean; $isInConflictFeature: boolean; }>( ({ theme, $hasConflict, $isInConflictFeature, $isAfterWarning, $isLast, }) => ({ borderLeft: '1px solid', borderRight: '1px solid', borderTop: '1px solid', borderBottom: $isLast ? '1px solid' : 'none', borderRadius: $isLast ? `0 0 ${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px` : 0, borderColor: $hasConflict || $isInConflictFeature ? theme.palette.warning.border : theme.palette.dividerAlternative, borderTopColor: ($hasConflict || $isAfterWarning) && !$isInConflictFeature ? theme.palette.warning.border : theme.palette.dividerAlternative, }) ); const StyledAlert = styled(Alert)(({ theme }) => ({ borderRadius: 0, padding: theme.spacing(0, 2), '&.MuiAlert-standardWarning': { borderStyle: 'none none solid none', }, })); const Change: FC<{ onDiscard: () => Promise; index: number; changeRequest: IChangeRequest; change: IChange; feature: IChangeRequestFeature; }> = ({ index, change, feature, changeRequest, onDiscard }) => { const { isChangeRequestConfigured } = useChangeRequestsEnabled( changeRequest.project ); const allowChangeRequestActions = isChangeRequestConfigured( changeRequest.environment ); const showDiscard = allowChangeRequestActions && !['Cancelled', 'Applied'].includes(changeRequest.state) && changeRequest.features.flatMap(feature => feature.changes).length > 1; return ( Conflict! This change can’t be applied.{' '} {change.conflict}. } /> {change.action === 'updateEnabled' && ( } /> } /> )} {change.action === 'addStrategy' && ( <> } /> } > )} {change.action === 'deleteStrategy' && ( } /> } > {hasNameField(change.payload) && ( )} )} {change.action === 'updateStrategy' && ( <> } /> } > )} ); }; export const ChangeRequest: VFC = ({ changeRequest, onRefetch, onNavigate, }) => { const { discardChange } = useChangeRequestApi(); const { setToastData, setToastApiError } = useToast(); const onDiscard = (id: number) => async () => { try { await discardChange(changeRequest.project, changeRequest.id, id); setToastData({ title: 'Change discarded from change request draft.', type: 'success', }); onRefetch?.(); } catch (error: unknown) { setToastApiError(formatUnknownError(error)); } }; return ( {changeRequest.features?.map(feature => ( {feature.changes.map((change, index) => ( ))} ))} ); };