Repository navigation
fix(frontend): show audit log rule changes as JSON instead of [object Object] #8893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { stringifyDiffValue } from 'common/utils/diffValue' | ||
|
|
||
| describe('stringifyDiffValue', () => { | ||
| it('returns an empty string for null and undefined', () => { | ||
| expect(stringifyDiffValue(null)).toBe('') | ||
| expect(stringifyDiffValue(undefined)).toBe('') | ||
| }) | ||
|
|
||
| it('quotes the empty string', () => { | ||
| expect(stringifyDiffValue('')).toBe('""') | ||
| }) | ||
|
|
||
| it('stringifies primitives', () => { | ||
| expect(stringifyDiffValue('abc')).toBe('abc') | ||
| expect(stringifyDiffValue(3)).toBe('3') | ||
| expect(stringifyDiffValue(false)).toBe('false') | ||
| }) | ||
|
|
||
| it('pretty-prints arrays of objects instead of [object Object]', () => { | ||
| const rules = [ | ||
| { conditions: [{ operator: 'EQUAL', property: 'a', value: '1' }] }, | ||
| ] | ||
| const result = stringifyDiffValue(rules) | ||
| expect(result).not.toContain('[object Object]') | ||
| expect(JSON.parse(result)).toEqual(rules) | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /** | ||
| * Turns an audit-log / diff value into the string shown in the diff viewer. | ||
| * Objects and arrays (e.g. a segment's `rules_data`) are pretty-printed as JSON, | ||
| * otherwise template interpolation would render them as `[object Object]`. | ||
| */ | ||
| export const stringifyDiffValue = (value: unknown): string => { | ||
| if (value === undefined || value === null) { | ||
| return '' | ||
| } | ||
| if (value === '') { | ||
| return '""' | ||
| } | ||
| if (typeof value === 'object') { | ||
| return JSON.stringify(value, null, 2) | ||
| } | ||
| return `${value}` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,23 +3,15 @@ import Diff, { DiffMethod } from 'react-diff-viewer-continued' | |
| import Prism from 'prismjs' | ||
| import 'prismjs/components/prism-json' | ||
| import { FlagsmithValue } from 'common/types/responses' | ||
| import { stringifyDiffValue } from 'common/utils/diffValue' | ||
| import DiffRow from './DiffRow' | ||
|
|
||
| type DiffType = { | ||
| oldValue: FlagsmithValue | ||
| newValue: FlagsmithValue | ||
| oldValue: FlagsmithValue | object | ||
| newValue: FlagsmithValue | object | ||
| compareMethod?: DiffMethod | ||
| } | ||
|
|
||
| const sanitiseDiffString = (value: FlagsmithValue) => { | ||
| if (value === undefined || value === null) { | ||
| return '' | ||
| } | ||
| if (value === '') { | ||
| return '""' | ||
| } | ||
| return `${value}` | ||
| } | ||
| const DiffString: FC<DiffType> = ({ | ||
| compareMethod = DiffMethod.WORDS_WITH_SPACE, | ||
| newValue, | ||
|
|
@@ -34,7 +26,7 @@ const DiffString: FC<DiffType> = ({ | |
| ) | ||
| } | ||
|
|
||
| if (oldValue === newValue) { | ||
| if (stringifyDiffValue(oldValue) === stringifyDiffValue(newValue)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (oldValue === null || oldValue === '') { | ||
| return <div className='text-muted'>No Value.</div> | ||
| } | ||
|
|
@@ -44,7 +36,7 @@ const DiffString: FC<DiffType> = ({ | |
| className='d-inline mb-0' | ||
| dangerouslySetInnerHTML={{ | ||
| __html: Prism.highlight( | ||
| sanitiseDiffString(newValue), | ||
| stringifyDiffValue(newValue), | ||
| Prism.languages.json, | ||
| 'json', | ||
| ), | ||
|
|
@@ -55,11 +47,14 @@ const DiffString: FC<DiffType> = ({ | |
| } | ||
| return ( | ||
| <Diff | ||
| oldValue={sanitiseDiffString(oldValue)} | ||
| newValue={sanitiseDiffString(newValue)} | ||
| oldValue={stringifyDiffValue(oldValue)} | ||
| newValue={stringifyDiffValue(newValue)} | ||
| compareMethod={compareMethod} | ||
| hideLineNumbers={ | ||
| !(`${oldValue}`.includes?.('\n') || `${newValue}`.includes?.('\n')) | ||
| !( | ||
| stringifyDiffValue(oldValue).includes('\n') || | ||
| stringifyDiffValue(newValue).includes('\n') | ||
|
Comment on lines
+50
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ) | ||
| } | ||
| renderContent={(str) => ( | ||
| <pre | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: Flagsmith/flagsmith
Length of output: 4187
Script executed:
Repository: Flagsmith/flagsmith
Length of output: 15456
Script executed:
Repository: Flagsmith/flagsmith
Length of output: 37496
Web query:
React 19 documentation React children plain JavaScript objects invalid as a React child arrays objectsResult:
Script executed:
Repository: Flagsmith/flagsmith
Length of output: 20887
Web query:
@types/react 19.3.0 ReactNode type React HTMLAttributes children ReactNode declaration index.d.tsResult:
Script executed:
Repository: Flagsmith/flagsmith
Length of output: 3365
Serialise objects in the E2E branch.
When
rules_datacontains rule objects, React cannot render the audit-log detail in E2E mode. The widened types also cause typechecking to fail. Serialise objects in this branch while preserving primitive values.Suggested fix