Skip to content

Commit

Permalink
feat: show changes that would be overwritten in change request overvi…
Browse files Browse the repository at this point in the history
…ew UI (#5964)

This PR adds a first, rough iteration of what it could look like to show
changes that would be overwritten by applying a PR.

The changes are listed in a table (semantically; looks more like a list
visually) and show the property, the current live value and the version
that you have in your changes. The changes are hidden by default, but
can be shown by expanding a details element.

@nicolaesocaciu Suggested that we merge this version for now and iterate
on the design later.

Here's what it looks like closed:

![image](https://github.com/Unleash/unleash/assets/17786332/3a641642-0537-4e7a-aeca-b3d3df6b8e31)

Here's what it looks like with a typical change load:

![image](https://github.com/Unleash/unleash/assets/17786332/b7aa7265-d1c7-4b6b-a9a2-f58cb966f25c)


Here's what it looks like if you change more or less every property
changed:

![image](https://github.com/Unleash/unleash/assets/17786332/4d94ab69-86ed-4c3e-be6a-6890c654e37e)
  • Loading branch information
thomasheartman committed Jan 22, 2024
1 parent 8f4780c commit 0bb709a
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
Expand Up @@ -17,6 +17,7 @@ import { Badge } from 'component/common/Badge/Badge';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { flexRow } from 'themes/themeStyles';
import { EnvironmentVariantsTable } from 'component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsCard/EnvironmentVariantsTable/EnvironmentVariantsTable';
import { ChangesToOverwrite } from './StrategyChangeOverwriteWarning';

export const ChangeItemWrapper = styled(Box)({
display: 'flex',
Expand Down Expand Up @@ -209,6 +210,10 @@ export const StrategyChange: VFC<{
)}
{change.action === 'updateStrategy' && (
<>
<ChangesToOverwrite
currentStrategy={currentStrategy}
change={change}
/>
<ChangeItemCreateEditWrapper>
<ChangeItemInfo>
<EditHeader
Expand Down
@@ -0,0 +1,154 @@
import { Box, styled } from '@mui/material';
import { IChangeRequestUpdateStrategy } from 'component/changeRequest/changeRequest.types';
import { useUiFlag } from 'hooks/useUiFlag';
import { IFeatureStrategy } from 'interfaces/strategy';
import { getChangesThatWouldBeOverwritten } from './strategy-change-diff-calculation';

const ChangesToOverwriteWarning = styled(Box)(({ theme }) => ({
color: theme.palette.warning.dark,
backgroundColor: theme.palette.warning.light,
fontSize: theme.fontSizes.smallBody,
borderRadius: theme.shape.borderRadiusLarge,
padding: theme.spacing(2),
marginBottom: theme.spacing(2),
}));

const OverwriteTable = styled('table')(({ theme }) => ({
'&,td,tr,thead': {
display: 'block',
textAlign: 'margin-inline-start',
},

thead: {
clip: 'rect(0 0 0 0)',
clipPath: 'inset(50%)',
height: '1px',
overflow: 'hidden',
position: 'absolute',
whiteSpace: 'nowrap',
width: '1px',
},

'tr + tr': {
marginBlockStart: theme.spacing(2),
},

'td:first-of-type': {
fontWeight: 'bold',
'::after': {
content: '":"',
},
textTransform: 'capitalize',
fontSize: theme.fontSizes.bodySize,
},
'td + td::before': {
content: 'attr(data-column)',
marginInlineEnd: theme.spacing(1),
fontWeight: 'bold',
},

pre: {
background: theme.palette.background.default,
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
width: '100%',

'ins, del': {
textDecoration: 'none',
'code::before': {
marginInlineEnd: theme.spacing(1),
},
},
'del code::before': {
content: '"-"',
},
'ins code::before': {
content: '"+"',
},
},
}));

export const ChangesToOverwrite: React.FC<{
currentStrategy?: IFeatureStrategy;
change: IChangeRequestUpdateStrategy;
}> = ({ change, currentStrategy }) => {
const checkForChanges = useUiFlag('changeRequestConflictHandling');
const changesThatWouldBeOverwritten = checkForChanges
? getChangesThatWouldBeOverwritten(currentStrategy, change)
: null;

if (!changesThatWouldBeOverwritten) {
return null;
}

return (
<ChangesToOverwriteWarning>
<p>
<strong>Heads up!</strong> The strategy has been updated since
you made your changes. Applying this change now would overwrite
the configuration that is currently live.
</p>
<details>
<summary>Changes that would be overwritten</summary>

<OverwriteTable>
<thead>
<tr>
<th>Property</th>
<th>Current value</th>
<th>Value after change</th>
</tr>
</thead>

<tbody>
{changesThatWouldBeOverwritten.map(
({ property, oldValue, newValue }) => (
<tr key={property}>
<td data-column='Property'>{property}</td>
<td data-column='Current value'>
<pre>
<del>
{JSON.stringify(
oldValue,
null,
2,
)
.split('\n')
.map((line, index) => (
<code
key={`${property}${line}${index}`}
>
{`${line}\n`}
</code>
))}
</del>
</pre>
</td>
<td data-column='Value after change'>
<pre>
<ins>
{JSON.stringify(
newValue,
null,
2,
)
.split('\n')
.map((line, index) => (
<code
key={`${property}${line}${index}`}
>
{`${line}\n`}
</code>
))}
</ins>
</pre>
</td>
</tr>
),
)}
</tbody>
</OverwriteTable>
</details>
</ChangesToOverwriteWarning>
);
};
1 change: 1 addition & 0 deletions frontend/src/interfaces/uiConfig.ts
Expand Up @@ -76,6 +76,7 @@ export type UiFlags = {
extendedUsageMetricsUI?: boolean;
adminTokenKillSwitch?: boolean;
executiveDashboard?: boolean;
changeRequestConflictHandling?: boolean;
};

export interface IVersionInfo {
Expand Down

0 comments on commit 0bb709a

Please sign in to comment.