From 3fd74262bb638db62a556d5cbd80b57dc6bf2a9b Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Tue, 15 Apr 2025 13:22:50 +0200
Subject: [PATCH] feat: search page - improved change request tooltip (#9750)
improved and tested tooltip for change requests and adjusted column width
---
.../common/HtmlTooltip/HtmlTooltip.tsx | 7 +-
.../FeatureEnvironmentSeenCell.tsx | 8 +-
.../FeatureToggleListTable.tsx | 11 +--
.../StatusCell/StatusCell.test.tsx | 84 +++++++++++++++++++
.../StatusCell/StatusCell.tsx | 69 +++++++++------
.../StatusCell/getStatus.test.ts | 40 +++++++++
6 files changed, 184 insertions(+), 35 deletions(-)
create mode 100644 frontend/src/component/feature/FeatureToggleList/StatusCell/StatusCell.test.tsx
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');
+ });
+ });
});