mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-23 13:46:45 +02:00
chore(AI): improvedJsonDiff flag cleanup (#10486)
This PR cleans up the improvedJsonDiff flag. These changes were automatically generated by AI and should be reviewed carefully. Fixes #10483 ## 🧹 AI Flag Cleanup Summary This PR removes the `improvedJsonDiff` feature flag, making the enhanced JSON diffing component the default and only option. The now-unused legacy diff component and all related feature flag logic have been removed to streamline the codebase. ### 🚮 Removed - **Components** - `OldEventDiff` component was removed, along with its helper types and constants. - **Flag Logic** - All conditional rendering based on the `improvedJsonDiff` flag was removed. - The `sort` prop from `EventDiff` was removed as it was only used by the legacy component. - **Configuration** - `improvedJsonDiff` flag definition was removed from `uiConfig.ts`, `experimental.ts`, and `server-dev.ts`. - **Tests** - Mock configuration for `improvedJsonDiff` in tests was removed. ### 🛠 Kept - **Components** - `NewEventDiff` was renamed to `EventDiff` and is now the standard implementation. ### 📝 Why The `improvedJsonDiff` feature flag was marked as completed with its outcome being "kept". This cleanup finalizes the feature rollout by removing the flag and associated legacy code, simplifying the implementation and reducing code complexity. --------- Co-authored-by: unleash-bot <194219037+unleash-bot[bot]@users.noreply.github.com> Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
parent
f5eafb2d6e
commit
d6ddc95c1e
@ -1,18 +1,4 @@
|
||||
import { styled } from '@mui/material';
|
||||
import { EventDiff } from 'component/events/EventDiff/EventDiff';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
const StyledCodeSection = styled('div')(({ theme }) => ({
|
||||
overflowX: 'auto',
|
||||
'& code': {
|
||||
wordWrap: 'break-word',
|
||||
whiteSpace: 'pre-wrap',
|
||||
fontFamily: 'monospace',
|
||||
lineHeight: 1.5,
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
},
|
||||
}));
|
||||
type StrategyIds = { strategyIds: string[] };
|
||||
interface IDiffProps {
|
||||
preData: StrategyIds;
|
||||
@ -20,18 +6,12 @@ interface IDiffProps {
|
||||
}
|
||||
|
||||
export const EnvironmentStrategyOrderDiff = ({ preData, data }: IDiffProps) => {
|
||||
const useNewDiff = useUiFlag('improvedJsonDiff');
|
||||
const Wrapper = useNewDiff ? Fragment : StyledCodeSection;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<EventDiff
|
||||
entry={{
|
||||
preData: preData.strategyIds,
|
||||
data: data.strategyIds,
|
||||
}}
|
||||
sort={(a, b) => a.index - b.index}
|
||||
/>
|
||||
</Wrapper>
|
||||
<EventDiff
|
||||
entry={{
|
||||
preData: preData.strategyIds,
|
||||
data: data.strategyIds,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ import type {
|
||||
import { useReleasePlanPreview } from 'hooks/useReleasePlanPreview';
|
||||
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
|
||||
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||
import { EventDiff } from 'component/events/EventDiff/EventDiff';
|
||||
import { ReleasePlan } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan';
|
||||
import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone';
|
||||
import type { IReleasePlan } from 'interfaces/releasePlans';
|
||||
|
@ -27,12 +27,6 @@ const strategy = {
|
||||
};
|
||||
|
||||
const setupApi = () => {
|
||||
testServerRoute(server, '/api/admin/ui-config', {
|
||||
flags: {
|
||||
improvedJsonDiff: true,
|
||||
},
|
||||
});
|
||||
|
||||
testServerRoute(
|
||||
server,
|
||||
`/api/admin/projects/${projectId}/features/${feature}`,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { styled } from '@mui/material';
|
||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||
import { EventDiff } from 'component/events/EventDiff/EventDiff';
|
||||
import type { IFeatureVariant } from 'interfaces/featureToggle';
|
||||
|
||||
const StyledCodeSection = styled('div')(({ theme }) => ({
|
||||
@ -31,7 +31,6 @@ export const VariantDiff = ({ preData, data }: IDiffProps) => (
|
||||
preData: variantsArrayToObject(preData),
|
||||
data: variantsArrayToObject(data),
|
||||
}}
|
||||
sort={(a, b) => a.index - b.index}
|
||||
/>
|
||||
</StyledCodeSection>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Typography, Button, useTheme, useMediaQuery } from '@mui/material';
|
||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||
import { EventDiff } from 'component/events/EventDiff/EventDiff';
|
||||
import {
|
||||
fadeInBottomEnter,
|
||||
fadeInBottomStartWithoutFixed,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||
import { EventDiff } from 'component/events/EventDiff/EventDiff';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||
import { formatDateYMDHMS } from 'utils/formatDate';
|
||||
|
@ -1,23 +1,27 @@
|
||||
import { render } from 'utils/testRenderer';
|
||||
import { screen } from '@testing-library/react';
|
||||
import EventDiff from './EventDiff.tsx';
|
||||
import { EventDiff } from './EventDiff.tsx';
|
||||
|
||||
test('Show no changes', async () => {
|
||||
render(<EventDiff entry={{ preData: [], data: [] }} />);
|
||||
|
||||
expect(screen.getByText('(no changes)')).toBeInTheDocument();
|
||||
const { container } = render(
|
||||
<EventDiff entry={{ preData: [{ a: 'b' }], data: [{ a: 'b' }] }} />,
|
||||
);
|
||||
const diff = container.querySelector('.diff');
|
||||
expect(diff).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
test('Show new data added diff', async () => {
|
||||
render(<EventDiff entry={{ preData: {}, data: { segments: [] } }} />);
|
||||
|
||||
expect(screen.getByText('+ segments: []')).toBeInTheDocument();
|
||||
const element = await screen.findByText(/segments:.*/);
|
||||
expect(element).toHaveClass('addition');
|
||||
});
|
||||
|
||||
test('Show new data removed diff', async () => {
|
||||
render(<EventDiff entry={{ preData: { segments: [] }, data: {} }} />);
|
||||
|
||||
expect(screen.getByText('- segments (deleted)')).toBeInTheDocument();
|
||||
const element = await screen.findByText(/segments:.*/);
|
||||
expect(element).toHaveClass('deletion');
|
||||
});
|
||||
|
||||
test('Show new data changes diff', async () => {
|
||||
@ -27,8 +31,10 @@ test('Show new data changes diff', async () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('- segments: "a"')).toBeInTheDocument();
|
||||
expect(screen.getByText('+ segments: "b"')).toBeInTheDocument();
|
||||
const deleted = await screen.findByText(/segments: "a".*/);
|
||||
expect(deleted).toHaveClass('deletion');
|
||||
const added = await screen.findByText(/segments: "b".*/);
|
||||
expect(added).toHaveClass('addition');
|
||||
});
|
||||
|
||||
test('Show new data only', async () => {
|
||||
@ -36,7 +42,8 @@ test('Show new data only', async () => {
|
||||
<EventDiff entry={{ preData: undefined, data: { segments: [] } }} />,
|
||||
);
|
||||
|
||||
expect(screen.getByText('{ "segments": [] }')).toBeInTheDocument();
|
||||
const element = await screen.findByText(/segments:.*/);
|
||||
expect(element).toHaveClass('addition');
|
||||
});
|
||||
|
||||
test('Show old data only', async () => {
|
||||
@ -44,5 +51,6 @@ test('Show old data only', async () => {
|
||||
<EventDiff entry={{ preData: { segments: [] }, data: undefined }} />,
|
||||
);
|
||||
|
||||
expect(screen.getByText('{ "segments": [] }')).toBeInTheDocument();
|
||||
const element = await screen.findByText(/segments:.*/);
|
||||
expect(element).toHaveClass('deletion');
|
||||
});
|
||||
|
@ -1,28 +1,9 @@
|
||||
import { diff } from 'deep-diff';
|
||||
import { type JSX, type CSSProperties, useState, type FC, useId } from 'react';
|
||||
import { useState, type FC, useId } from 'react';
|
||||
import { JsonDiffComponent, type JsonValue } from 'json-diff-react';
|
||||
import { Button, styled, useTheme } from '@mui/material';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
const DIFF_PREFIXES: Record<string, string> = {
|
||||
A: ' ',
|
||||
E: ' ',
|
||||
D: '-',
|
||||
N: '+',
|
||||
};
|
||||
|
||||
interface IEventDiffResult {
|
||||
key: string;
|
||||
value: JSX.Element;
|
||||
index: number;
|
||||
}
|
||||
import { Button, styled } from '@mui/material';
|
||||
|
||||
interface IEventDiffProps {
|
||||
entry: { data?: unknown; preData?: unknown };
|
||||
/**
|
||||
* @deprecated remove with flag improvedJsonDiff
|
||||
*/
|
||||
sort?: (a: IEventDiffResult, b: IEventDiffResult) => number;
|
||||
excludeKeys?: string[];
|
||||
}
|
||||
|
||||
@ -78,7 +59,7 @@ const ButtonIcon = styled('span')(({ theme }) => ({
|
||||
marginInlineEnd: theme.spacing(0.5),
|
||||
}));
|
||||
|
||||
export const NewEventDiff: FC<IEventDiffProps> = ({ entry, excludeKeys }) => {
|
||||
export const EventDiff: FC<IEventDiffProps> = ({ entry, excludeKeys }) => {
|
||||
const changeType = entry.preData && entry.data ? 'edit' : 'replacement';
|
||||
const showExpandButton = changeType === 'edit';
|
||||
const [full, setFull] = useState(false);
|
||||
@ -112,115 +93,3 @@ export const NewEventDiff: FC<IEventDiffProps> = ({ entry, excludeKeys }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const OldEventDiff: FC<IEventDiffProps> = ({
|
||||
entry,
|
||||
sort = (a, b) => a.key.localeCompare(b.key),
|
||||
}: IEventDiffProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const styles: Record<string, CSSProperties> = {
|
||||
A: { color: theme.palette.eventLog.edited }, // array edited
|
||||
E: { color: theme.palette.eventLog.edited }, // edited
|
||||
D: { color: theme.palette.eventLog.diffSub }, // deleted
|
||||
N: { color: theme.palette.eventLog.diffAdd }, // added
|
||||
};
|
||||
|
||||
const diffs =
|
||||
entry.data && entry.preData
|
||||
? diff(entry.preData, entry.data)
|
||||
: undefined;
|
||||
|
||||
const buildItemDiff = (diff: any, key: string) => {
|
||||
let change: JSX.Element | undefined;
|
||||
if (diff.lhs !== undefined) {
|
||||
change = (
|
||||
<div style={styles.D}>
|
||||
- {key}: {JSON.stringify(diff.lhs)}
|
||||
</div>
|
||||
);
|
||||
} else if (diff.rhs !== undefined) {
|
||||
change = (
|
||||
<div style={styles.N}>
|
||||
+ {key}: {JSON.stringify(diff.rhs)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return change;
|
||||
};
|
||||
|
||||
const buildDiff = (diff: any, index: number): IEventDiffResult => {
|
||||
let change: JSX.Element | undefined;
|
||||
const key = diff.path?.join('.') ?? diff.index;
|
||||
|
||||
if (diff.item) {
|
||||
change = buildItemDiff(diff.item, key);
|
||||
} else if (diff.lhs !== undefined && diff.rhs !== undefined) {
|
||||
change = (
|
||||
<div>
|
||||
<div style={styles.D}>
|
||||
- {key}: {JSON.stringify(diff.lhs)}
|
||||
</div>
|
||||
<div style={styles.N}>
|
||||
+ {key}: {JSON.stringify(diff.rhs)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
const changeValue = JSON.stringify(diff.rhs || diff.item);
|
||||
change = (
|
||||
<div style={styles[diff.kind]}>
|
||||
{DIFF_PREFIXES[diff.kind]} {key}
|
||||
{changeValue
|
||||
? `: ${changeValue}`
|
||||
: diff.kind === 'D'
|
||||
? ' (deleted)'
|
||||
: ''}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
key: key.toString(),
|
||||
value: <div key={index}>{change}</div>,
|
||||
index,
|
||||
};
|
||||
};
|
||||
|
||||
let changes: any[] = [];
|
||||
|
||||
if (diffs) {
|
||||
changes = diffs
|
||||
.map(buildDiff)
|
||||
.sort(sort)
|
||||
.map(({ value }) => value);
|
||||
} else if (entry.data == null || entry.preData == null) {
|
||||
// Just show the data if there is no diff yet.
|
||||
const data = entry.data || entry.preData;
|
||||
changes = [
|
||||
<div key={0} style={entry.data ? styles.N : styles.D}>
|
||||
{JSON.stringify(data, null, 2)}
|
||||
</div>,
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<pre style={{ overflowX: 'auto', overflowY: 'hidden' }}>
|
||||
<code>{changes.length === 0 ? '(no changes)' : changes}</code>
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
export const EventDiff: FC<IEventDiffProps> = (props) => {
|
||||
const useNewJsonDiff = useUiFlag('improvedJsonDiff');
|
||||
if (useNewJsonDiff) {
|
||||
return <NewEventDiff {...props} />;
|
||||
}
|
||||
return <OldEventDiff {...props} />;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated remove the default export with flag improvedJsonDiff. Switch imports in files that use this to the named import instead.
|
||||
*/
|
||||
export default EventDiff;
|
||||
|
@ -88,7 +88,6 @@ export type UiFlags = {
|
||||
customMetrics?: boolean;
|
||||
lifecycleMetrics?: boolean;
|
||||
createFlagDialogCache?: boolean;
|
||||
improvedJsonDiff?: boolean;
|
||||
impactMetrics?: boolean;
|
||||
crDiffView?: boolean;
|
||||
changeRequestApproverEmails?: boolean;
|
||||
|
1
pijul/identities/publickey.json
Normal file
1
pijul/identities/publickey.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -54,7 +54,7 @@ export class MetricsTranslator {
|
||||
): Record<string, string | number> {
|
||||
return {
|
||||
...(sample.labels || {}),
|
||||
origin: (sample.labels && sample.labels.origin) || 'sdk',
|
||||
origin: sample.labels?.origin || 'sdk',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,6 @@ export type IFlagKey =
|
||||
| 'customMetrics'
|
||||
| 'impactMetrics'
|
||||
| 'createFlagDialogCache'
|
||||
| 'improvedJsonDiff'
|
||||
| 'crDiffView'
|
||||
| 'changeRequestApproverEmails'
|
||||
| 'paygTrialEvents'
|
||||
@ -275,10 +274,6 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_CHANGE_REQUEST_APPROVER_EMAILS,
|
||||
false,
|
||||
),
|
||||
improvedJsonDiff: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_IMPROVED_JSON_DIFF,
|
||||
false,
|
||||
),
|
||||
crDiffView: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_CR_DIFF_VIEW,
|
||||
false,
|
||||
|
@ -54,7 +54,6 @@ process.nextTick(async () => {
|
||||
reportUnknownFlags: true,
|
||||
customMetrics: true,
|
||||
lifecycleMetrics: true,
|
||||
improvedJsonDiff: true,
|
||||
impactMetrics: true,
|
||||
crDiffView: true,
|
||||
paygTrialEvents: true,
|
||||
|
Loading…
Reference in New Issue
Block a user