From 0bb709a718f1223c14808128b2989245fa40af11 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Mon, 22 Jan 2024 11:13:38 +0400 Subject: [PATCH] feat: show changes that would be overwritten in change request overview 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) --- .../Changes/Change/StrategyChange.tsx | 5 + .../Change/StrategyChangeOverwriteWarning.tsx | 154 ++++++++++++++++++ frontend/src/interfaces/uiConfig.ts | 1 + 3 files changed, 160 insertions(+) create mode 100644 frontend/src/component/changeRequest/ChangeRequest/Changes/Change/StrategyChangeOverwriteWarning.tsx diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/StrategyChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/StrategyChange.tsx index da411b101d..c7b71a4c9e 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/StrategyChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/StrategyChange.tsx @@ -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', @@ -209,6 +210,10 @@ export const StrategyChange: VFC<{ )} {change.action === 'updateStrategy' && ( <> + ({ + 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 ( + +

+ Heads up! The strategy has been updated since + you made your changes. Applying this change now would overwrite + the configuration that is currently live. +

+
+ Changes that would be overwritten + + + + + Property + Current value + Value after change + + + + + {changesThatWouldBeOverwritten.map( + ({ property, oldValue, newValue }) => ( + + {property} + +
+                                            
+                                                {JSON.stringify(
+                                                    oldValue,
+                                                    null,
+                                                    2,
+                                                )
+                                                    .split('\n')
+                                                    .map((line, index) => (
+                                                        
+                                                            {`${line}\n`}
+                                                        
+                                                    ))}
+                                            
+                                        
+ + +
+                                            
+                                                {JSON.stringify(
+                                                    newValue,
+                                                    null,
+                                                    2,
+                                                )
+                                                    .split('\n')
+                                                    .map((line, index) => (
+                                                        
+                                                            {`${line}\n`}
+                                                        
+                                                    ))}
+                                            
+                                        
+ + + ), + )} + +
+
+
+ ); +}; diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index ecf118c4a8..b0bf4a01b7 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -76,6 +76,7 @@ export type UiFlags = { extendedUsageMetricsUI?: boolean; adminTokenKillSwitch?: boolean; executiveDashboard?: boolean; + changeRequestConflictHandling?: boolean; }; export interface IVersionInfo {