1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-26 01:17:00 +02:00

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)
This commit is contained in:
Thomas Heartman 2023-08-09 16:15:14 +02:00 committed by GitHub
parent 75c15e5cac
commit fe0c7087de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 121 deletions

View File

@ -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(
<NameWithChangeInfo newName={newName} previousName={previousName} />
);
// 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(
<NameWithChangeInfo newName={newName} previousName={previousName} />
);
// 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(
<NameWithChangeInfo newName={newName} previousName={previousName} />
);
// 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(<NameWithChangeInfo newName={name} previousName={name} />);
// 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(<NameWithChangeInfo newName={undefined} previousName={undefined} />);
expect(screen.queryByText('', { selector: 'ins' })).toBeNull();
expect(screen.queryByText('', { selector: 'del' })).toBeNull();
expect(screen.queryByText('', { selector: 'span' })).toBeNull();
});

View File

@ -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 (
<>
<ConditionallyRender
condition={titleHasChanged}
show={
<Truncated>
<Typography component="del" color="text.secondary">
{previousName}
</Typography>
</Truncated>
}
/>
<ConditionallyRender
condition={Boolean(newName)}
show={
<Truncated>
<Typography
component={
titleHasChangedOrBeenAdded ? 'ins' : 'span'
}
>
{newName}
</Typography>
</Truncated>
}
/>
</>
);
};

View File

@ -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<IStrategyTooltipLinkProps> = ({
maxHeight: 600,
}}
>
<Typography component="span">
{formatStrategyName(change.payload.name)}
</Typography>
<NameWithChangeInfo
previousName={change.name}
newName={change.payload.name}
/>
</TooltipLink>
</Truncated>
</StyledContainer>

View File

@ -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(
<StrategyName newTitle={newTitle} previousTitle={previousTitle} />
);
// 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(
<StrategyName newTitle={newTitle} previousTitle={previousTitle} />
);
// 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(<StrategyName newTitle={newTitle} previousTitle={previousTitle} />);
// 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(<StrategyName newTitle={title} previousTitle={title} />);
// 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(<StrategyName newTitle={undefined} previousTitle={undefined} />);
expect(screen.queryByText('', { selector: 'ins' })).toBeNull();
expect(screen.queryByText('', { selector: 'del' })).toBeNull();
expect(screen.queryByText('', { selector: 'span' })).toBeNull();
});

View File

@ -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 (
<>
<ConditionallyRender
condition={titleHasChanged}
show={
<Truncated>
<Typography component="del" color="text.secondary">
{previousTitle}
</Typography>
</Truncated>
}
/>
<ConditionallyRender
condition={Boolean(newTitle)}
show={
<Truncated>
<Typography
component={
titleHasChangedOrBeenAdded ? 'ins' : 'span'
}
>
{newTitle}
</Typography>
</Truncated>
}
/>
</>
);
};
interface IStrategyTooltipLinkProps {
change:
| IChangeRequestAddStrategy
@ -131,9 +89,9 @@ export const StrategyTooltipLink: FC<IStrategyTooltipLinkProps> = ({
{formatStrategyName(change.payload.name)}
</Typography>
</TooltipLink>
<StrategyName
newTitle={change.payload.title}
previousTitle={previousTitle}
<NameWithChangeInfo
newName={change.payload.title}
previousName={previousTitle}
/>
</Truncated>
</StyledContainer>

View File

@ -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;