diff --git a/frontend/src/component/common/HtmlTooltip/HtmlTooltip.tsx b/frontend/src/component/common/HtmlTooltip/HtmlTooltip.tsx index 2df622be5b..6c6a61ff15 100644 --- a/frontend/src/component/common/HtmlTooltip/HtmlTooltip.tsx +++ b/frontend/src/component/common/HtmlTooltip/HtmlTooltip.tsx @@ -69,13 +69,10 @@ export interface IHtmlTooltipProps extends TooltipProps { maxHeight?: SpacingArgument; fontSize?: string; tabIndex?: number; + disableFocusListener?: boolean; } export const HtmlTooltip = (props: IHtmlTooltipProps) => { if (!props.title) return props.children; - return ( - - {props.children} - - ); + return {props.children}; }; diff --git a/frontend/src/component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell.tsx b/frontend/src/component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell.tsx index 6d4f5f54f8..92d2322c6c 100644 --- a/frontend/src/component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell.tsx +++ b/frontend/src/component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell.tsx @@ -54,7 +54,13 @@ export const FeatureLifecycleCell: VFC = ({ : []; return ( - + ({ + display: 'flex', + justifyContent: 'center', + padding: theme.spacing(0, expanded ? 1 : 0), + })} + > { ), enableSorting: false, - size: 80, }), columnHelper.accessor('project', { header: 'Project', @@ -208,10 +207,12 @@ export const FeatureToggleListTable: FC = () => { )?.name; return ( - + + + ); }, }), diff --git a/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.test.tsx b/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.test.tsx new file mode 100644 index 0000000000..870b134a69 --- /dev/null +++ b/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.test.tsx @@ -0,0 +1,84 @@ +import { render } from 'utils/testRenderer'; +import { StatusCell } from './StatusCell'; +import { screen } from '@testing-library/dom'; +import userEvent from '@testing-library/user-event'; + +describe('StatusCell', () => { + it('displays "–" as default status', () => { + const { getByText } = render( + , + ); + expect(getByText('–')).toBeInTheDocument(); + }); + + it('shows "change requests" icon', () => { + const { getByTestId } = render( + , + ); + + expect(getByTestId('change-requests-icon')).toBeInTheDocument(); + }); + + it('shows change requests on focus', async () => { + const ui = ( + + ); + const { getByTestId, getByText, rerender } = render(ui); + + expect(await screen.queryByText('Change requests:')).toBeNull(); + await userEvent.hover(getByTestId('change-requests-icon')); + await screen.findByRole('tooltip'); + expect( + await screen.queryByText('Change requests:'), + ).toBeInTheDocument(); + expect(getByText('#123')).toBeInTheDocument(); + }); +}); diff --git a/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.tsx b/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.tsx index cd82ab3893..9e783e03fa 100644 --- a/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.tsx +++ b/frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.tsx @@ -5,25 +5,39 @@ import { getStatus } from './getStatus'; import DifferenceIcon from '@mui/icons-material/Difference'; import { Link } from 'react-router-dom'; import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip'; +import { Truncator } from 'component/common/Truncator/Truncator'; const Container = styled('div')(({ theme }) => ({ padding: theme.spacing(0, 2), display: 'flex', alignItems: 'center', - gap: theme.spacing(1), + gap: theme.spacing(0.5), + minWidth: '180px', })); const ChangeRequestIcon = styled(DifferenceIcon)(({ theme }) => ({ color: theme.palette.primary.main, - fontSize: theme.spacing(2.5), - marginLeft: theme.spacing(0.5), + fontSize: theme.spacing(3.5), + padding: theme.spacing(0.5), })); -export const StatusCell: FC = ({ - lifecycle, - environments, - project, -}) => { +const ChangeRequestTooltip = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: theme.spacing(0.5), + ul: { + listStyle: 'none', + padding: 0, + margin: 0, + display: 'flex', + flexDirection: 'column', + }, +})); + +export const StatusCell: FC< + Pick +> = ({ lifecycle, environments, project }) => { const status = useMemo( () => getStatus({ lifecycle, environments }), [lifecycle, environments], @@ -35,28 +49,35 @@ export const StatusCell: FC = ({ return ( -
{status}
+ + {status} + {changeRequestIds.length > 0 && ( - Change requests: -
- {changeRequestIds.map((id) => ( - - {`#${id}`} - - ))} - + +
Change requests:
+
    + {changeRequestIds.map((id) => ( +
  • + + {`#${id}`} + +
  • + ))} +
+
} > - +
)}
diff --git a/frontend/src/component/feature/FeatureToggleList/StatusCell/getStatus.test.ts b/frontend/src/component/feature/FeatureToggleList/StatusCell/getStatus.test.ts index 21c802c58e..cbddb7ea28 100644 --- a/frontend/src/component/feature/FeatureToggleList/StatusCell/getStatus.test.ts +++ b/frontend/src/component/feature/FeatureToggleList/StatusCell/getStatus.test.ts @@ -148,4 +148,44 @@ describe('getStatus', () => { ).toBe('No strategies'); }); }); + + describe('release plan - milestones', () => { + it('should show the release plan', () => { + expect( + getStatus({ + environments: [ + { + ...prodEnvEnabled, + totalMilestones: 2, + milestoneOrder: 0, + milestoneName: 'First step', + }, + ], + lifecycle: { + stage: 'live', + enteredStageAt: null as any, + }, + }), + ).toBe('Milestone: First step (1 of 2)'); + }); + + it('should not show the milestone if a flag is disabled', () => { + expect( + getStatus({ + environments: [ + { + ...prodEnvDisabled, + totalMilestones: 2, + milestoneOrder: 0, + milestoneName: 'First step', + }, + ], + lifecycle: { + stage: 'live', + enteredStageAt: null as any, + }, + }), + ).not.toBe('Release plan'); + }); + }); });