From fe0c7087de0a7f3b17094ff5f19ddfca7c516f4a Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Wed, 9 Aug 2023 16:15:14 +0200 Subject: [PATCH] Add name with change info to segment changes (1-1230-update-name-change) (#4459) Extract and reuse the component that we use for strategy name changes. ## Discussion points: This impl only shows the new name in the second field (editing segment). Should we show it in both? Why do we have both? Do we have UI designs for this? ![image](https://github.com/Unleash/unleash/assets/17786332/5521b1f1-1688-4063-9a16-ec17e4811e91) --- .../NameWithChangeInfo.test.tsx | 74 +++++++++++++++++++ .../NameWithChangeInfo/NameWithChangeInfo.tsx | 49 ++++++++++++ .../ChangeRequest/SegmentTooltipLink.tsx | 8 +- .../StrategyTooltipLink.test.tsx | 72 ------------------ .../StrategyTooltipLink.tsx | 50 +------------ .../changeRequest/changeRequest.types.ts | 2 + 6 files changed, 134 insertions(+), 121 deletions(-) create mode 100644 frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.test.tsx create mode 100644 frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.tsx delete mode 100644 frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx diff --git a/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.test.tsx b/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.test.tsx new file mode 100644 index 0000000000..72e5d0e9ee --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.test.tsx @@ -0,0 +1,74 @@ +import { screen } from '@testing-library/react'; +import { render } from 'utils/testRenderer'; +import React from 'react'; +import { NameWithChangeInfo } from './NameWithChangeInfo'; + +test.each(['', undefined])( + 'Should render only the new name if the previous name was %s', + async previousName => { + const newName = 'new name'; + render( + + ); + + // expect no del elements + expect( + screen.queryByText(previousName || '', { selector: 'del' }) + ).toBeNull(); + + // expect ins element with new strategy name + await screen.findByText(newName, { selector: 'ins' }); + } +); + +test.each(['', undefined])( + 'Should render the old name as deleted and no new name if there was a previous name and the new one is %s', + async newName => { + const previousName = 'previous name'; + render( + + ); + + // expect no ins elements + expect( + screen.queryByText(newName || '', { selector: 'ins' }) + ).toBeNull(); + + // expect del element with old strategy name + await screen.findByText(previousName, { selector: 'del' }); + } +); + +test('Should render the old name as deleted and the new name as inserted if the previous name was different', async () => { + const newName = 'new name'; + const previousName = 'previous name'; + render( + + ); + + // expect del element with old strategy name + await screen.findByText(previousName, { selector: 'del' }); + + // expect ins element with new strategy name + await screen.findByText(newName, { selector: 'ins' }); +}); + +test('Should render the name in a span if it has not changed', async () => { + const name = 'name'; + render(); + + // expect no del or ins elements + expect(screen.queryByText(name, { selector: 'ins' })).toBeNull(); + expect(screen.queryByText(name, { selector: 'del' })).toBeNull(); + + // expect span element with the strategy name + await screen.findByText(name, { selector: 'span' }); +}); + +test('Should render nothing if there was no name and there is still no name', async () => { + render(); + + expect(screen.queryByText('', { selector: 'ins' })).toBeNull(); + expect(screen.queryByText('', { selector: 'del' })).toBeNull(); + expect(screen.queryByText('', { selector: 'span' })).toBeNull(); +}); diff --git a/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.tsx b/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.tsx new file mode 100644 index 0000000000..65ce62722d --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequest/NameWithChangeInfo/NameWithChangeInfo.tsx @@ -0,0 +1,49 @@ +import { FC } from 'react'; +import { Typography, styled } from '@mui/material'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import { textTruncated } from 'themes/themeStyles'; + +const Truncated = styled('div')(() => ({ + ...textTruncated, + maxWidth: 500, +})); + +export const NameWithChangeInfo: FC<{ + newName: string | undefined; + previousName: string | undefined; +}> = ({ newName, previousName }) => { + const titleHasChanged = Boolean(previousName && previousName !== newName); + + const titleHasChangedOrBeenAdded = Boolean( + titleHasChanged || (!previousName && newName) + ); + + return ( + <> + + + {previousName} + + + } + /> + + + {newName} + + + } + /> + + ); +}; diff --git a/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx b/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx index f3997706a3..dab7c7a826 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/SegmentTooltipLink.tsx @@ -10,6 +10,7 @@ import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; import { Typography, styled } from '@mui/material'; import { textTruncated } from 'themes/themeStyles'; import { ISegment } from 'interfaces/segment'; +import { NameWithChangeInfo } from './NameWithChangeInfo/NameWithChangeInfo'; const StyledCodeSection = styled('div')(({ theme }) => ({ overflowX: 'auto', @@ -70,9 +71,10 @@ export const SegmentTooltipLink: FC = ({ maxHeight: 600, }} > - - {formatStrategyName(change.payload.name)} - + 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 1f6535cd44..0000000000 --- a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.test.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { screen } from '@testing-library/react'; -import { render } from 'utils/testRenderer'; -import React from 'react'; -import { StrategyName } from './StrategyTooltipLink'; - -test.each(['', undefined])( - 'Should render only the new title if the previous title was %s', - async previousTitle => { - const newTitle = 'new title'; - render( - - ); - - // expect no del elements - expect( - screen.queryByText(previousTitle || '', { selector: 'del' }) - ).toBeNull(); - - // expect ins element with new strategy name - await screen.findByText(newTitle, { selector: 'ins' }); - } -); - -test.each(['', undefined])( - 'Should render the old title as deleted and no new title if there was a previous title and the new one is %s', - async newTitle => { - const previousTitle = 'previous title'; - render( - - ); - - // expect no ins elements - expect( - screen.queryByText(newTitle || '', { selector: 'ins' }) - ).toBeNull(); - - // expect del element with old strategy name - await screen.findByText(previousTitle, { selector: 'del' }); - } -); - -test('Should render the old title as deleted and the new title as inserted if the previous title was different', async () => { - const newTitle = 'new title'; - const previousTitle = 'previous title'; - render(); - - // expect del element with old strategy name - await screen.findByText(previousTitle, { selector: 'del' }); - - // expect ins element with new strategy name - await screen.findByText(newTitle, { selector: 'ins' }); -}); - -test('Should render the title in a span if it has not changed', async () => { - const title = 'title'; - render(); - - // expect no del or ins elements - expect(screen.queryByText(title, { selector: 'ins' })).toBeNull(); - expect(screen.queryByText(title, { selector: 'del' })).toBeNull(); - - // expect span element with the strategy name - await screen.findByText(title, { selector: 'span' }); -}); - -test('Should render nothing if there was no title and there is still no title', async () => { - render(); - - expect(screen.queryByText('', { selector: 'ins' })).toBeNull(); - expect(screen.queryByText('', { selector: 'del' })).toBeNull(); - expect(screen.queryByText('', { selector: 'span' })).toBeNull(); -}); diff --git a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx b/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx index 3b8cbf4eb0..26fa4df406 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/StrategyTooltipLink/StrategyTooltipLink.tsx @@ -13,8 +13,8 @@ import omit from 'lodash.omit'; import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; import { Typography, styled } from '@mui/material'; import { IFeatureStrategy } from 'interfaces/strategy'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { textTruncated } from 'themes/themeStyles'; +import { NameWithChangeInfo } from '../NameWithChangeInfo/NameWithChangeInfo'; const StyledCodeSection = styled('div')(({ theme }) => ({ overflowX: 'auto', @@ -49,48 +49,6 @@ export const StrategyDiff: FC<{ ); }; -export const StrategyName: FC<{ - newTitle: string | undefined; - previousTitle: string | undefined; -}> = ({ newTitle, previousTitle }) => { - const titleHasChanged = Boolean( - previousTitle && previousTitle !== newTitle - ); - - const titleHasChangedOrBeenAdded = Boolean( - titleHasChanged || (!previousTitle && newTitle) - ); - - return ( - <> - - - {previousTitle} - - - } - /> - - - {newTitle} - - - } - /> - - ); -}; - interface IStrategyTooltipLinkProps { change: | IChangeRequestAddStrategy @@ -131,9 +89,9 @@ export const StrategyTooltipLink: FC = ({ {formatStrategyName(change.payload.name)} - diff --git a/frontend/src/component/changeRequest/changeRequest.types.ts b/frontend/src/component/changeRequest/changeRequest.types.ts index c817f91dcf..87bf31c37b 100644 --- a/frontend/src/component/changeRequest/changeRequest.types.ts +++ b/frontend/src/component/changeRequest/changeRequest.types.ts @@ -112,6 +112,7 @@ export interface IChangeRequestReorderStrategy export interface IChangeRequestUpdateSegment { action: 'updateSegment'; conflict?: string; + name: string; payload: { id: number; name: string; @@ -124,6 +125,7 @@ export interface IChangeRequestUpdateSegment { export interface IChangeRequestDeleteSegment { action: 'deleteSegment'; conflict?: string; + name: string; payload: { id: number; name: string;