-
Notifications
You must be signed in to change notification settings - Fork 16
Upgrade to RJSF v5 #1819
base: develop
Are you sure you want to change the base?
Upgrade to RJSF v5 #1819
Conversation
Tests still failing.
Changes to fix tests and build errors
@@ -15,7 +15,6 @@ const globals = { | |||
'rss-parser': 'Parser', | |||
'react-mailchimp-subscribe': 'ReactMailchimpSubscribe', | |||
'plotly.js-basic-dist': 'Plotly', | |||
'@rjsf/core': 'JSONSchemaForm', |
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.
Let's include RJSF in the bundle. Bundle size doesn't change much since we were bundling our forked version, and now we're dropping it.
// These tests are unstable, so we'll skip them until we can fix them | ||
// The component is in experimental mode only, so not a big deal for now | ||
describe.skip('SchemaDrivenAnnotationEditor tests', () => { | ||
describe('SchemaDrivenAnnotationEditor tests', () => { |
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.
Hopefully these are stable now. The test suite also should emit no errors/warnings.
@@ -191,6 +195,17 @@ describe.skip('SchemaDrivenAnnotationEditor tests', () => { | |||
return res(ctx.status(201), ctx.json({ token: mockAsyncTokenId })) | |||
}, | |||
), | |||
rest.get( |
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.
A while ago we changed how SynapseClient requests the result for asynchronous jobs. This accommodates that change.
// TODO: Test is not working, but the functionality is working in the browser | ||
it.skip('Removes a custom annotation field when the last value is removed', async () => { |
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.
This is the only skipped test now.
* - convert schema-defined formData from an array to a non-array if the schema type is not an array | ||
* @param props | ||
*/ | ||
export function objectFieldComponentDidUpdate(props: FieldProps) { |
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.
This logic used to be split up in FieldTemplate
and AdditionalPropertiesSchemaField
. Each of those components wrapped the call to onChange
in useEffect
with a setTimeout
.
That wasn't working very well. In short, multiple fields would call onChange
at once, and only one would succeed.
This eliminates the race condition by changing all of the fields in the object in one pass.
* If the intitial data is a string, returns an array of substrings separated by commas. | ||
* Otherwise, wrap the data in an array. | ||
*/ | ||
function convertToArray(value: T): Array<any> { |
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.
moved to AnnotationEditorUtils
const { list, handleListChange, handleListRemove, appendToList, setList } = | ||
useListState(convertToArray(formData)) | ||
|
||
const list = Array.isArray(formData) ? formData : convertToArray(formData) |
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.
Let's remove this excess state (which also lets us get rid of another effect)
useEffect(() => { | ||
// The item may not be an array when we get it, and we need to convert it right away because the order of items is not stable, and seems to depend on if the item is an array or not. | ||
// Otherwise, the order of the properties will change when the user modifies the data. We may be able to fix this by modifying react-jsonschema-form to stabilize the item order. | ||
|
||
// FIXME: This doesn't work without a delay. | ||
setTimeout(() => { | ||
onChange(list) | ||
}, 50) | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []) |
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.
This logic was moved to ObjectField via AnnotationEditorUtils.objectFieldComponentDidUpdate
Fix test suite broken from moving files
/** | ||
* This file is mostly a direct copy of the RJSF ObjectField component. Because it handles a lot of complex logic for | ||
* rendering a form, when we upgrade RJSF, we should replace this file with the new version. | ||
* | ||
* The only change that we have applied is adding the `componentDidUpdate` method to the class. | ||
*/ |
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.
See here ^^^
* | ||
* @param props - The `ArrayFieldTemplateItemType` props for the component | ||
*/ | ||
export default function ArrayFieldItemTemplate<T, F>( |
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.
Template that didn't exist before RJSF v5. Pulled from our custom ArrayFieldTemplate.
* Identical to @rjsf/core ArrayFieldDescriptionTemplate except doesn't render null if there is no description | ||
* @param props - The `ArrayFieldDescriptionProps` for the component | ||
*/ | ||
export default function ArrayFieldDescriptionTemplate<T = any, F = any>( |
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.
Template that didn't exist before RJSF v5. Mostly copied and pasted from the base one
* | ||
* @param props - The `ArrayFieldTemplateItemType` props for the component | ||
*/ | ||
function ArrayFieldTemplate<T = any, F = any>( |
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.
Moved from CustomArrayFieldTemplate
. Since it now uses other templates that didn't exist before, it was substantially rewritten.
useEffect(() => { | ||
if (props.items.length === 0) { | ||
props.onAddClick() | ||
} | ||
}, [props]) |
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.
This is our addition (unchanged from previous version)
* @param props | ||
* @returns | ||
*/ | ||
export default function ArrayFieldTitleTemplate<T, F>( |
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.
Template that didn't exist before RJSF v5.
) | ||
} | ||
|
||
export default { |
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.
Ability to simply override buttons didn't exist before RJSF v5.
import React from 'react' | ||
import Typography from '../../../../utils/typography/Typography' | ||
|
||
export default function DescriptionFieldTemplate(props: DescriptionFieldProps) { |
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.
Used to be FieldDescriptionTable.tsx
and was manually inserted into each template. Now, we can just override the DescriptionFieldTemplate.
import { HelpOutline } from '@material-ui/icons' | ||
import { Collapse } from '@material-ui/core' | ||
|
||
export function FieldTemplate<T>(props: FieldTemplateProps<T>) { |
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.
Used to be CustomDefaultTemplate
. Now is just concerned with layout
@@ -13,10 +20,35 @@ import { displayToast } from '../../ToastMessage' | |||
* @param props | |||
* @returns | |||
*/ | |||
export function CustomObjectFieldTemplate( | |||
props: ObjectFieldTemplateProps<Record<string, unknown>>, | |||
export function ObjectFieldTemplate<T, F>( |
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.
Mostly code style changes in this component to match the base RJSF v5 ObjectFieldTemplate
onKeyChange: (newKey: string) => void | ||
}, | ||
) => { | ||
export default function WrapIfAdditionalTemplate<T = any, F = any>( |
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.
For additionalProperties
, we were overriding an entire FieldTemplate
to alter the layout of an internal RJSF component called WrapIfAdditional
. We added WrapIfAdditionalTemplate
to RJSF v5 to make this easier.
Upgrade to RJSF v5.
Includes many changes to clean up code + fix existing bugs.