Skip to content

Commit 1eb1632

Browse files
palkerecsenyizzacharo
authored andcommitted
overridable: breaking change and deprecation notices, dynamicParametrize usage for both built-in and custom fields
1 parent 33ebb67 commit 1eb1632

File tree

4 files changed

+167
-15
lines changed

4 files changed

+167
-15
lines changed

docs/operate/customize/look-and-feel/override_components.md

Lines changed: 123 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,21 @@ For this guide, we assume that you are familiar with React and JavaScript.
1818
The UI of InvenioRDM is composed of classic HTML web pages for mostly static content, and React web apps for very dynamic content to enhance the user experience.
1919
While a [dedicated guide](./templates.md) describes how to override HTML web pages (Jinja templates), this guide focus on how to override React components.
2020

21-
InvenioRDM uses the React library [`react-overridable`](https://github.com/indico/react-overridable). The library provides a mechanism to mark React components as "overridable" by id.
22-
Developers can define a map `{ id: Overridden React component }`, which is then applied when each React component is rendered: the overridden component is rendered instead of the default one.
21+
InvenioRDM uses the React library [`react-overridable`](https://github.com/indico/react-overridable). The library provides a mechanism to mark React components as "overridable" by ID.
22+
Developers can define a mapping which is then applied when each React component is rendered.
23+
The override can be specified in one of three ways:
24+
25+
- completely replacing a component with a custom one
26+
- a static override of the props passed to the component
27+
- a 'dynamic' override of the props based on the form's state
2328

2429
As example for this guide, you will learn how to override the UI React component **in the upload form that marks a record as "Metadata only"**. More specifically, you will replace the "Metadata-only record" checkbox with a toggle, a "switch-like" component.
2530

2631
![Metadata-only record checkbox](./imgs/metadata_only_checkbox.png)
2732

28-
## Steps
33+
## Guided example
2934

30-
### Identify how to override
35+
### 1. Identify which component to override
3136

3237
At the moment, the easiest way to understand how to identify if the component that you want to override is a classic HTML component or a React component is to use the Developer Tools in your browser (e.g. [Chrome](https://developer.chrome.com/docs/devtools/) or [Firefox DevTools](https://firefox-source-docs.mozilla.org/devtools-user/)). You can inspect the code and take advantage of some useful [React browser extensions](https://beta.reactjs.org/learn/react-developer-tools) to select and inspect elements:
3338

@@ -37,7 +42,7 @@ You can then find the component in the InvenioRDM modules source code, searching
3742

3843
You can always [ask for help](../../../install/troubleshoot.md#getting-help)!
3944

40-
### Find the React Overridable ID
45+
### 2. Find the React Overridable ID
4146

4247
The easiest way to to find the ID of an overridable component is to use `react-overridable`'s built-in developer tool.
4348
Simply open a browser console on your local instance and call the global function `reactOverridableEnableDevMode()`.
@@ -46,11 +51,11 @@ You can click a tag to copy its ID to your clipboard.
4651

4752
![Metadata-only checkbox overridable ID in an overlay](./imgs/metadata_id_overlay.png)
4853

49-
The React component's overridable ID for the '`Metadata-only record`' checkbox component is `ReactInvenioDeposit.FileUploaderToolbar.MetadataOnlyToggle.container`. It can be found in the [`invenio-rdm-records`](https://github.com/inveniosoftware/invenio-rdm-records/blob/dd72962b713f07b81699f7d5c9a8a673d585466a/invenio_rdm_records/assets/semantic-ui/js/invenio_rdm_records/src/deposit/fields/FileUploader/FileUploaderToolbar.js#L56) module.
54+
The React component's overridable ID for the '`Metadata-only record`' checkbox component is `InvenioRdmRecords.DepositForm.FileUploaderToolbar.MetadataOnlyToggle`. It can be found in the [`invenio-rdm-records`](https://github.com/inveniosoftware/invenio-rdm-records/blob/dd72962b713f07b81699f7d5c9a8a673d585466a/invenio_rdm_records/assets/semantic-ui/js/invenio_rdm_records/src/deposit/fields/FileUploader/FileUploaderToolbar.js#L56) module.
5055

51-
### The mapping file
56+
### 3. Find or create the mapping file
5257

53-
In a new InvenioRDM v11 or above installations, an almost empty file named `mapping.js` is available at the following path in your `assets` folder:
58+
In new InvenioRDM v11 or above installations, a near-empty file named `mapping.js` is available at the following path in your `assets` folder:
5459

5560
```terminal
5661
├── assets
@@ -68,7 +73,7 @@ export const overriddenComponents = {};
6873

6974
The `const overriddenComponents` is the map that will contain all your future overridden components.
7075

71-
### New component creation
76+
### 4. Create a new component creation
7277

7378
Let's create a new React component, very similar to the default `FileUploaderToolbar`, changing the UI component that will render. In the same file `mapping.js`, add the following code above the `const overriddenComponents`:
7479

@@ -109,7 +114,7 @@ Now, change the map by adding your new component:
109114
...
110115

111116
export const overriddenComponents = {
112-
"ReactInvenioDeposit.FileUploaderToolbar.MetadataOnlyToggle.container": MetadataToggle,
117+
"InvenioRdmRecords.DepositForm.FileUploaderToolbar.MetadataOnlyToggle": MetadataToggle,
113118
};
114119
```
115120

@@ -125,18 +130,122 @@ When navigating to the upload form, you should now see your new React component
125130

126131
!["`Metadata-only record`" toggle](./imgs/metadata_only_toggle.png)
127132

133+
## Overriding props only
134+
135+
In many cases, you simply want to make a small modification to a component by changing one of its props instead of recreating the component from scratch by yourself.
136+
This can either be done by specifying the desired prop overrides statically, or by expressing them as a function of the form state.
137+
138+
### Static
139+
140+
You can use the `parametrize` function built into `react-overridable`, into which you need to pass the component you wish to override and an object containing your props.
141+
These props will be 'merged' with the existing props, with yours taking precedence over existing ones of the same name.
142+
143+
```javascript
144+
import { parametrize } from "react-overridable"
145+
import { TitlesField } from "@js/invenio_rdm_records"
146+
147+
export const overriddenComponents = {
148+
"InvenioRdmRecords.DepositForm.TitlesField": parametrize(
149+
TitlesField,
150+
{
151+
helpText: "Describe your resource in a few words"
152+
}
153+
)
154+
}
155+
```
156+
157+
### Dynamic
158+
159+
To implement more complex functionality in the deposit form, you can override the props of components by using a custom function.
160+
This allows you to express a range of behaviours:
161+
162+
- hiding fields that are inapplicable to a certain resource type
163+
- changing the label of fields to be more contextually relevant
164+
- marking a field as disabled when its value has been made obvious by the value of another field
165+
- showing certain fields only when a specific community is selected
166+
- etc.
167+
168+
For this, you can use the `dynamicParametrize` function in `react-invenio-forms`, which behaves similarly to `parametrize`.
169+
The callback you pass will be evaluated whenever the form state changes, and the object you return will override the props
170+
passed to the component.
171+
172+
```javascript
173+
import { dynamicParametrize } from "react-invenio-forms"
174+
import { RelatedWorksField } from "@js/invenio_rdm_records"
175+
176+
export const overriddenComponents = {
177+
"InvenioRdmRecords.DepositForm.TitlesField": dynamicParametrize(
178+
TitlesField,
179+
({ formValues }) => {
180+
return {
181+
helpText: `Enter the title of your ${formValue.metadata.resource_type}`
182+
}
183+
}
184+
)
185+
}
186+
```
187+
188+
The callback function is currently passed an object as its single argument, containing the following values:
189+
190+
- `formValues`: the raw values of the entire deposit form as given by Formik. The majority of field values are under the `metadata` key.
191+
- `existingProps`: the props passed to the element before your override.
192+
193+
### Deposit form field props
194+
195+
The built-in fields in the deposit form (e.g. title, description, etc.) have a number of common props to make customizing basic functionality easier.
196+
197+
The following props may be overriden on all built-in fields:
198+
199+
- `label`: the user-facing short label
200+
- `labelIcon`: the ID of the [Semantic UI Icon](https://semantic-ui.com/elements/icon.html) to include in the label
201+
- `helpText`: a small optional text generally shown below the field, providing additional context to the user
202+
- `placeholder`: same as the [HTML attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/placeholder)
203+
204+
Additionally, the following props may be overriden on fields that are not mandatory.
205+
At the moment, this is all fields except the Resource Type, Title, Publication Date, and Creatibutors.
206+
207+
- `hidden`: if `true`, the field is not rendered at all
208+
- If a field already had a value before being hidden, this will still be included in the model and will be sent to the server when the form is submitted.
209+
- Fields retain their values when they are hidden and later re-shown.
210+
- `disabled`: same as the [HTML attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/disabled)
211+
- `required`: if `true`, shows a red asterisk in the field label
212+
- This does not affect the form validation model on the frontend or the backend, and is purely a stylistic setting.
213+
214+
Many fields have their own props in addition to these.
215+
Please [view the source code](https://github.com/inveniosoftware/invenio-rdm-records/tree/master/invenio_rdm_records/assets/semantic-ui/js/invenio_rdm_records/src/deposit/fields) for more details.
216+
128217
## Other examples
129218

130-
Let's hide completely the '`Metadata-only record`'checkbox from the upload form.
219+
### Showing/hiding
220+
221+
You can completely hide a field in the deposit form, based on either a static `true`/`false` value or in response to the current state of the form.
131222

132-
It is possible to remove a component using the overridable strategy. In the previous example, instead of declaring a target component `MetadataToggle` you can simply change the map to:
223+
To simply permanently hide the field, you can use something like this:
133224

134225
```javascript
135226
export const overriddenComponents = {
136-
"ReactInvenioDeposit.FileUploaderToolbar.MetadataOnlyToggle.container": () => null,
227+
"InvenioRdmRecords.DepositForm.RelatedWorksField": () => null,
137228
};
138229
```
139230

140-
The expression `() => null` above is defining an "empty" component, thus removing it from the upload form.
231+
The expression `() => null` above is defining an "empty" component, thus removing it from the deposit form.
232+
233+
To dynamically only show the field when the `image` resource type is selected, you can use the `dynamicParametrize` function.
234+
235+
```javascript
236+
import { dynamicParametrize } from "react-invenio-forms"
237+
import { RelatedWorksField } from "@js/invenio_rdm_records"
238+
239+
export const overriddenComponents = {
240+
"InvenioRdmRecords.DepositForm.RelatedWorksField": dynamicParametrize(
241+
TitlesField,
242+
({ formValues }) => {
243+
return {
244+
hidden: formValues.metadata.resource_type !== "image"
245+
}
246+
}
247+
)
248+
}
249+
```
141250

142251
In order to see more examples in action, you can check the [zenodo-rdm](https://github.com/zenodo/zenodo-rdm) repository!

docs/operate/customize/metadata/custom_fields/widgets.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,36 @@ These props are applicable to all widgets. In the reference below, only props ad
2828

2929
To improve consistency with the fields in the deposit form, the `icon` prop has been renamed to `labelIcon` and `description` has been renamed to `helpText`. The functionality of these props is unchanged and the old names will continue working for now, albeit with a deprecation notice.
3030

31+
## Dynamic behaviour
32+
33+
While controlling the static prop values via the [`RDM_CUSTOM_FIELDS_UI` config value](records.md#upload-deposit-form) is relatively straightforward, it doesn't allow
34+
you to specify dynamic behaviour, such as showing/hiding the field only in specific cases, or using a different `helpText` depending on the resource type.
35+
36+
This can instead be done using the `dynamicParametrize` function.
37+
For more details on its usage, [see the documentation on overriding React components](../../look-and-feel/override_components.md#dynamic).
38+
39+
The ID of the overridable is the internal name of your custom field (e.g. `cern:experiment`).
40+
You can override any of the props listed on this page (except `fieldPath`), depending on the specific widget.
41+
42+
For example, to make the `cern:experiment` field only be shown for thesis records:
43+
44+
```javascript
45+
// my-rdm-instance/assets/js/invenio_app_rdm/overridableRegistry/mapping.js
46+
47+
import { dynamicParametrize, Input } from "react-invenio-forms"
48+
49+
export const overriddenComponents = {
50+
"cern:experiment": dynamicParametrize(
51+
Input,
52+
({ formValues }) => {
53+
return {
54+
hidden: formValues.metadata.resource_type !== "thesis"
55+
}
56+
}
57+
)
58+
}
59+
```
60+
3161
## Input
3262

3363
An input field for a single string value.

docs/releases/vNext/upgrade-vNext.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,22 @@ affected by `invenio index destroy --yes-i-know` and are totally functional afte
172172

173173
### Required changes
174174

175+
#### Overridable IDs in the deposit form
176+
177+
To improve consistency in naming conventions and structure, some IDs of Overridables in the deposit form have been modified. If you are overriding any of these components, you will need to change the ID in your mapping file to reflect these modifications.
178+
179+
The full list of ID changes [can be found here](https://github.com/inveniosoftware/invenio-rdm-records/pull/2101/files#diff-ff3c479edefad986d2fe6fe7ead575a46b086e3bbcf0ccc86d85efc4a4c63c79).
180+
181+
If you are not overriding any of these components, you do not need to change anything.
182+
175183
### Optional changes
176184

177185
#### Deprecations
178186

187+
##### Custom field widget prop names
188+
189+
Many [custom field widgets](../../operate/customize/metadata/custom_fields/widgets.md) used the `icon` and `description` props, which have now been deprecated and replaced with `labelIcon` and `helpText` respectively. This is to improve consistency with the naming of the built-in fields used in the deposit form and thereby avoid confusion. The old names will continue to function for now, but we recommend updating to the new names where applicable.
190+
179191
#### New configuration variables
180192

181193
These are the new configuration variables introduced in this release. Make sure that you read the related documentation before enabling them. Add them to your `invenio.cfg` as needed:

docs/releases/vNext/version-vNext.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ Here is a quick summary of the myriad of other improvements in this release:
2626

2727
## Deprecations
2828

29-
29+
- Many [custom field widgets](../../operate/customize/metadata/custom_fields/widgets.md) used the `icon` and `description` props, which have now been deprecated and replaced with `labelIcon` and `helpText` respectively. This is to improve consistency with the naming of the built-in fields used in the deposit form and thereby avoid confusion. The old names will continue to function for now.
3030

3131
## Breaking changes
3232

33+
- Overridables in the deposit form have been modified to improve consistency in structure and naming conventions. This has involved renaming the IDs of several `<Overridable>`s, but none have been removed. If you are using these IDs to override components, please see [the full list of updates](https://github.com/inveniosoftware/invenio-rdm-records/pull/2101/files#diff-ff3c479edefad986d2fe6fe7ead575a46b086e3bbcf0ccc86d85efc4a4c63c79) and change your IDs accordingly.
3334

3435
## Requirements
3536

0 commit comments

Comments
 (0)