diff --git a/docs/customize/img/custom_fields_example_deposit_form.png b/docs/customize/img/custom_fields_example_deposit_form.png index 75a71c25..41d64022 100644 Binary files a/docs/customize/img/custom_fields_example_deposit_form.png and b/docs/customize/img/custom_fields_example_deposit_form.png differ diff --git a/docs/customize/img/custom_fields_example_landing_page.png b/docs/customize/img/custom_fields_example_landing_page.png index 27936cca..9a2ce16e 100644 Binary files a/docs/customize/img/custom_fields_example_landing_page.png and b/docs/customize/img/custom_fields_example_landing_page.png differ diff --git a/docs/customize/img/landing_page.png b/docs/customize/img/landing_page.png deleted file mode 100644 index 0158a778..00000000 Binary files a/docs/customize/img/landing_page.png and /dev/null differ diff --git a/docs/customize/img/landing_page_fields_display.png b/docs/customize/img/landing_page_fields_display.png index e5e8af3a..afd3a826 100644 Binary files a/docs/customize/img/landing_page_fields_display.png and b/docs/customize/img/landing_page_fields_display.png differ diff --git a/docs/customize/metadata/custom_fields/records.md b/docs/customize/metadata/custom_fields/records.md index 2a3ce305..7f19c97f 100644 --- a/docs/customize/metadata/custom_fields/records.md +++ b/docs/customize/metadata/custom_fields/records.md @@ -1,52 +1,13 @@ # Records custom fields -*Introduced in InvenioRDM v10* - While the InvenioRDM's [metadata schema](../../../reference/metadata.md) includes a wide range of bibliographic fields, there might still be cases where you need to include domain or system specific information in your records. This can be achieved using custom fields. -To demonstrate how to take advantage of custom fields, we will use the following examples: - -_In my university repository, when uploading my work, I want to input the programming language that I have used._ +To demonstrate how to take advantage of custom fields, we will use the following example: _At CERN, I want to input or select the experiment information of the research preprint that I am uploading. In addition, when searching for other preprints, I want to filter the search results by experiment name._ !!! warning - Before jumping into adding custom fields, take a close look at the existing set of fields in the metadata schema, and especially the [subjects field](../../../reference/metadata.md#subjects-0-n), which can be extended with terms from external vocabularies that might already exist. - -## Quickstart, how does it look? - -To add a _programming language_ field, you will need to configure the type of -field and how it should be displayed. The configuration will look like: - -```python -from invenio_records_resources.services.custom_fields import TextCF - -RDM_CUSTOM_FIELDS = [ - TextCF(name="programming_language") -] - -RDM_CUSTOM_FIELDS_UI = [ - { - "section": _("Quickstart example section"), - "fields": [ - dict( - field="programming_language", - ui_widget="Input", - props=dict( - label="Programming language", - placeholder="Python...", - icon="pencil", - description="The programming language of your choice...", - ) - ), - ] - } -] -``` - -This will create a new section in the bottom of the record's upload page and will look like: - -![Programmatic language field](../../img/programmatic_language.png) + Before jumping into adding custom fields, take a close look at the [optional fields](../optional_fields.md) as well as the default set of fields in the metadata schema. For example, the [subjects field](../../../reference/metadata.md#subjects-0-n) can be extended with terms from external vocabularies instead of creating custom fields. ## Configuration @@ -64,8 +25,6 @@ The `RDM_NAMESPACES` config variable accepts key-value pairs of namespace prefix ```python RDM_NAMESPACES = { - # CodeMeta - "code": "https://codemeta.github.io/terms/", # CERN "cern": "https://greybook.cern.ch/", } @@ -89,9 +48,6 @@ RDM_CUSTOM_FIELDS = [ dump_options=True, # True when the list of all possible values will be visible in the dropdown UI component, typically for small vocabularies multiple=False, # if the field accepts a list of values (True) or single value (False) ), - TextCF( # a simple text input field - name="programming_language" - ), TextCF( # a text input field that will allow HTML tags name="cern:experiment_description_html", field_cls=SanitizedHTML, @@ -99,6 +55,33 @@ RDM_CUSTOM_FIELDS = [ ] ``` +### Defining a custom vocabulary + +For a VocabularyCF field to work, you need a custom vocabulary for it to search from. First you'll want to edit `app_data/vocabularies.yaml` to add the name of the vocabulary + +```yaml +cernexperiments: + pid-type: cexp + data-file: vocabularies/cern_experiments.jsonl +``` + +You can read more about [all the vocabulary options](../../vocabularies/) in that documentation section. + +For our example, you'll then want to make a file `app_data/vocabularies/cern_experiments.jsonl` with content + +```json +{"id": "ATLAS", "title": {"en": "ATLAS"}} +{"id": "LHC", "title": {"en": "Large Hadron Collider"}} +``` + +If you've already set up your services, you can create this vocabulary with + +``` +pipenv run invenio rdm-records fixtures +``` + +You can see then see the vocabulary at `/api/vocabularies/cernexperiments` + ### Customizing validation and error messages In the [reference](#reference) section, you can find the complete list of available custom field types. You can also customize each field type: @@ -152,7 +135,7 @@ When you want to make a new specific field searchable: ```bash # initialize specific custom fields to make them searchable -pipenv run invenio rdm-records custom-fields init -f -f +pipenv run invenio rdm-records custom-fields init -f cern:experiment -f ``` !!! tip @@ -250,41 +233,7 @@ The additional details section: ![Custom fields in additional details section](../../img/landing_page_fields_display.png) -The landing page with the configured custom fields: - -![Custom fields in landing page](../../img/landing_page.png) - -However, it is possible to change this default layout by overriding the Jinja templates of the landing page. - -You can change how a specific field is displayed in the _additional details_ section via the _template_ parameter: - -```python -RDM_CUSTOM_FIELDS_UI = [ - { - "section": _("Quickstart example section"), - "fields": [ - dict( - field="programming_language", - ui_widget="Input", - template="/my_template.html" - props=dict( - label="Programming language", - placeholder="Python...", - icon="pencil", - description="The programming language of your choice...", - ) - ), - ] - } -] -``` - -You should add the `my_template.html` file in the `my-site/templates` folder in your instance. In your custom template, the following variables are injected and can be used: - -- `field_value`: the value of the field, as it is stored in the record after the UI serialization i.e. what is returned from the `ui_field` method when you [define your custom field](../../../develop/howtos/custom_fields.md). -- `field_cfg`: the UI configuration for that specific field as it is defined in the `RDM_CUSTOM_FIELDS_UI` config. - -See the example in the [How-to](../../../develop/howtos/custom_fields.md#define-the-template-for-the-record-landing-page). +It is possible to do additional customization of both how custom fields display on the deposit form and landing page. See this [How-to](../../../develop/howtos/custom_fields.md#define-the-template-for-the-record-landing-page) for an example. ### Search @@ -418,189 +367,3 @@ This section lists the field types and UI widgets that are available in InvenioR - `AutocompleteDropdown` for a value from a controlled vocabulary or a list of controlled vocabularies. The corresponding `VocabularyCF` must have the parameter `dump_options=False`. This widget will provide suggestions to autocomplete the user input. Similar to _subjects_, _languages_, _names_, etc. You can see a detailed view of all the available widgets at the [UI widgets](../../../reference/custom_fields/widgets.md) reference section. - -## Complete examples - -Below you can find multiple examples on how to add custom fields to records. - -### Create custom fields and add them to records - -You can find below a complete example of the configuration to add to your `invenio.cfg`. - -```python -from invenio_rdm_records.config import RDM_FACETS, RDM_SEARCH -from invenio_records_resources.services.custom_fields import TextCF -from invenio_records_resources.services.records.facets import CFTermsFacet -from invenio_vocabularies.services.custom_fields import VocabularyCF -from marshmallow import validate -from marshmallow_utils.fields import SanitizedHTML - -RDM_NAMESPACES = { - # CodeMeta - "code": "https://codemeta.github.io/terms/", - # CERN - "cern": "https://greybook.cern.ch/", -} - -RDM_CUSTOM_FIELDS = [ - VocabularyCF( - name="cern:experiment", - vocabulary_id="cernexperiments", - dump_options=True, - multiple=False, - ), - TextCF( - name="cern:experiment_description_html", - field_cls=SanitizedHTML, - ), - TextCF( - name="cern:experiment_url", - field_args={ - "validate": validate.URL(), - "required": True, - "error_messages": { - "required": "You must provide the experiment homepage URL. " - } - }, - multiple=False, - ), -] - -RDM_CUSTOM_FIELDS_UI = [ - { - "section": _("CERN Experiment"), - "fields": [ - dict( - field="cern:experiment", - ui_widget="Dropdown", - props=dict( - label="CERN Experiment", - placeholder="ATLAS", - icon="lab", - description="You should fill this field with one of the experiments e.g LHC, ATLAS etc.", - search=False, # True for autocomplete dropdowns - multiple=False, # True for list of values - clearable=True, - ) - ), - dict( - field="cern:experiment_description_html", - ui_widget="RichInput", - props=dict( - label="Experiment description", - placeholder="This experiment aims to...", - icon="pencil", - description="You should fill this field with the experiment description.", - ) - ), - dict( - field="cern:experiment_url", - ui_widget="Input", - props=dict( - label="Experiment URL", - placeholder="https://your.experiment.url", - icon="linkify", - description="URL of the experiment to which the record belongs to.", - required=True, - ) - ), - ] - } -] - -RDM_FACETS = { - **RDM_FACETS, - "experiment": { - "facet": CFTermsFacet( # backend facet - field="cern:experiment.id", # id is the keyword field of a vocabulary - label=_("CERN Experiment"), - ), - "ui": { # ui display - "field": CFTermsFacet.field("cern:experiment.id"), - }, - }, -} - -RDM_SEARCH = { - **RDM_SEARCH, - "facets": RDM_SEARCH["facets"] + ["experiment"] -} -``` - -### Add reusable custom fields to records - -Invenio provides a set of [custom fields ](../../../reference/custom_fields/fields_list.md) that can be added to an instance on demand. - -In the following example, we will customize fields, create a new section ("Publishing Information") to group custom fields, and hide the "Conference" section on the landing page. It is important to note that this change only affects the visual representation of the fields and not the underlying data model (metadata fields). - -```python -from invenio_i18n import lazy_gettext as _ -from invenio_rdm_records.contrib.imprint import ( - IMPRINT_CUSTOM_FIELDS, - IMPRINT_CUSTOM_FIELDS_UI, - IMPRINT_NAMESPACE, -) -from invenio_rdm_records.contrib.journal import ( - JOURNAL_CUSTOM_FIELDS, - JOURNAL_CUSTOM_FIELDS_UI, - JOURNAL_NAMESPACE, -) -from invenio_rdm_records.contrib.thesis import ( - THESIS_CUSTOM_FIELDS, - THESIS_CUSTOM_FIELDS_UI, - THESIS_NAMESPACE, -) -from invenio_rdm_records.contrib.meeting import ( - MEETING_CUSTOM_FIELDS, - MEETING_CUSTOM_FIELDS_UI, - MEETING_NAMESPACE, -) - -RDM_NAMESPACES = { - **JOURNAL_NAMESPACE, - **IMPRINT_NAMESPACE, - **THESIS_NAMESPACE, - **MEETING_NAMESPACE, -} - -# Combine custom fields -RDM_CUSTOM_FIELDS = [ - # journal - *JOURNAL_CUSTOM_FIELDS, - # meeting - *MEETING_CUSTOM_FIELDS, - # imprint - *IMPRINT_CUSTOM_FIELDS, - # thesis - *THESIS_CUSTOM_FIELDS, -] - -# Hide "meeting" section in the landing page -MEETING_CUSTOM_FIELDS_UI["hidden"] = True - -# Create a "Publishing Information" section in the deposit form and add multiple fields -RDM_CUSTOM_FIELDS_UI = [ - { - "section": _("Publishing information"), - "hidden": True, - "fields": [ - # journal - *JOURNAL_CUSTOM_FIELDS_UI["fields"], - # imprint - *IMPRINT_CUSTOM_FIELDS_UI["fields"], - # thesis - *THESIS_CUSTOM_FIELDS_UI["fields"], - ], - }, - # meeting - MEETING_CUSTOM_FIELDS_UI, -] -``` - -The previous configuration produces the following result in the deposit form: - -![Reusable custom field result (deposit form)](../../img/custom_fields_example_deposit_form.png) - -and landing page: - -![Reusable custom field result (landing page)](../../img/custom_fields_example_landing_page.png) diff --git a/docs/customize/metadata/optional_fields.md b/docs/customize/metadata/optional_fields.md new file mode 100644 index 00000000..d71fb14b --- /dev/null +++ b/docs/customize/metadata/optional_fields.md @@ -0,0 +1,177 @@ +# Configuring optional metadata fields + +_Introduced in InvenioRDM v12_ + +InvenioRDM comes with a base [metadata schema](../../../reference/metadata.md), which is used for every record in the system and includes many common fields. InvenioRDM also includes *optional* metadata fields, which can be activated by an administrator. These fields may not be applicable to every instance, but if they are applicable we recommend you use them instead of creating your own custom fields. + +The current optional fields are: + +- Journal (Publication) +- Imprint (Book, Chapter or Report) +- Thesis +- Meeting (Conference) +- Software (CodeMeta) + +You can see more details about each field group in [the metadata documentation](../../reference/metadata/optional_metadata.md) + +Metadata fields in InvenioRDM are defined by three configuration variables: + +- `RDM_NAMESPACES` - Defines fields namespaces to avoid name clashes. +- `RDM_CUSTOM_FIELDS` - Defines the name, type, and validation rules of your fields. +- `RDM_CUSTOM_FIELDS_UI` - Defines how the fields are displayed in the uploads form UI. + +For optional metadata fields, each of these configurations is already defined. You simply need to import the configuration. For example, if you wanted to add meeting metadata to your instance, you would edit your `invenio.cfg` file and add: + +```python +from invenio_rdm_records.contrib.meeting import ( + MEETING_CUSTOM_FIELDS, + MEETING_CUSTOM_FIELDS_UI, + MEETING_NAMESPACE, +) +``` + +Then you need to add the imported configurations to the configuration variables. + +```python +RDM_NAMESPACES = { + **MEETING_NAMESPACE, +} +RDM_CUSTOM_FIELDS = [ + *MEETING_CUSTOM_FIELDS, +] + +RDM_CUSTOM_FIELDS_UI = [ + MEETING_CUSTOM_FIELDS_UI +] +``` + +You'll need to initialize the field by typing `pipenv run invenio rdm-records custom-fields init`. Restart your instance, and you should see the fields appear in the deposit form. If you create a record, the metadata will also appear in the UI. By default, much of the optional field metadata will appear in both the "Additional details" section and in a condensed citation style form in the "Details" sidebar of the landing pages. This is a bit repetitive, and you can remove the metadata from the "Additional details" section with the configuration. + +```python +MEETING_CUSTOM_FIELDS_UI["hide_from_landing_page"] = True +``` + +You can also combine optional fields in the deposit form into sections. For example, we usually combine the journal, imprint, and thesis fields into a "Publishing Information" section. You'll need to import internationalization and all the fields like: + +```python +from invenio_i18n import lazy_gettext as _ +from invenio_rdm_records.contrib.imprint import ( + IMPRINT_CUSTOM_FIELDS, + IMPRINT_CUSTOM_FIELDS_UI, + IMPRINT_NAMESPACE, +) +from invenio_rdm_records.contrib.journal import ( + JOURNAL_CUSTOM_FIELDS, + JOURNAL_CUSTOM_FIELDS_UI, + JOURNAL_NAMESPACE, +) +from invenio_rdm_records.contrib.thesis import ( + THESIS_CUSTOM_FIELDS, + THESIS_CUSTOM_FIELDS_UI, + THESIS_NAMESPACE, +) +``` + +Then add the namespace and fields + +```python +RDM_NAMESPACES = { + **JOURNAL_NAMESPACE, + **IMPRINT_NAMESPACE, + **THESIS_NAMESPACE, +} + +RDM_CUSTOM_FIELDS = [ + *JOURNAL_CUSTOM_FIELDS, + *IMPRINT_CUSTOM_FIELDS, + *THESIS_CUSTOM_FIELDS, +] +``` + +And finally make a new section in the UI + +```python +RDM_CUSTOM_FIELDS_UI = [ + { + "section": _("Publishing information"), + "hide_from_landing_page": True, + "fields": [ + # journal + *JOURNAL_CUSTOM_FIELDS_UI["fields"], + # imprint + *IMPRINT_CUSTOM_FIELDS_UI["fields"], + # thesis + *THESIS_CUSTOM_FIELDS_UI["fields"], + ], + }, +] +``` + +You'll need to initialize the field by typing `pipenv run invenio rdm-records custom-fields init`. Restart your instance, and you should see the fields appear in the deposit form. + +You can activate both the meeting and publishing fields at once, with this full configuration: + +```python +from invenio_i18n import lazy_gettext as _ +from invenio_rdm_records.contrib.imprint import ( + IMPRINT_CUSTOM_FIELDS, + IMPRINT_CUSTOM_FIELDS_UI, + IMPRINT_NAMESPACE, +) +from invenio_rdm_records.contrib.journal import ( + JOURNAL_CUSTOM_FIELDS, + JOURNAL_CUSTOM_FIELDS_UI, + JOURNAL_NAMESPACE, +) +from invenio_rdm_records.contrib.thesis import ( + THESIS_CUSTOM_FIELDS, + THESIS_CUSTOM_FIELDS_UI, + THESIS_NAMESPACE, +) +from invenio_rdm_records.contrib.meeting import ( + MEETING_CUSTOM_FIELDS, + MEETING_CUSTOM_FIELDS_UI, + MEETING_NAMESPACE, +) + +RDM_NAMESPACES = { + **JOURNAL_NAMESPACE, + **IMPRINT_NAMESPACE, + **THESIS_NAMESPACE, + **MEETING_NAMESPACE, +} + +RDM_CUSTOM_FIELDS = [ + *MEETING_CUSTOM_FIELDS, + *JOURNAL_CUSTOM_FIELDS, + *IMPRINT_CUSTOM_FIELDS, + *THESIS_CUSTOM_FIELDS, +] + +RDM_CUSTOM_FIELDS_UI = [ + { + "section": _("Publishing information"), + "hide_from_landing_page": True, + "fields": [ + # journal + *JOURNAL_CUSTOM_FIELDS_UI["fields"], + # imprint + *IMPRINT_CUSTOM_FIELDS_UI["fields"], + # thesis + *THESIS_CUSTOM_FIELDS_UI["fields"], + ], + }, + # meeting + MEETING_CUSTOM_FIELDS_UI, +] + +MEETING_CUSTOM_FIELDS_UI["hide_from_landing_page"] = True +``` + +You'll need to initialize the field by typing `pipenv run invenio rdm-records custom-fields init`. Restart your instance, and you should see the fields appear in the deposit form like: + +![Optional field result (deposit form)](../../img/custom_fields_example_deposit_form.png) + +and the landing page should look like: + +![Optional field result (landing page)](../../img/custom_fields_example_landing_page.png) \ No newline at end of file diff --git a/docs/images/codemeta_deposit_form.png b/docs/images/codemeta_deposit_form.png index aeda4a00..87feb130 100644 Binary files a/docs/images/codemeta_deposit_form.png and b/docs/images/codemeta_deposit_form.png differ diff --git a/docs/images/codemeta_landing_page.png b/docs/images/codemeta_landing_page.png index 2a554211..9979af22 100644 Binary files a/docs/images/codemeta_landing_page.png and b/docs/images/codemeta_landing_page.png differ diff --git a/docs/images/meeting_landing_page.png b/docs/images/meeting_landing_page.png index 67551bb2..c81c6b78 100644 Binary files a/docs/images/meeting_landing_page.png and b/docs/images/meeting_landing_page.png differ diff --git a/docs/images/pub_info_deposit_form.png b/docs/images/pub_info_deposit_form.png index e764b7d5..9e27bca0 100644 Binary files a/docs/images/pub_info_deposit_form.png and b/docs/images/pub_info_deposit_form.png differ diff --git a/docs/images/pub_info_landing_page.png b/docs/images/pub_info_landing_page.png index a8383648..baf9095f 100644 Binary files a/docs/images/pub_info_landing_page.png and b/docs/images/pub_info_landing_page.png differ diff --git a/docs/reference/metadata.md b/docs/reference/metadata/index.md similarity index 100% rename from docs/reference/metadata.md rename to docs/reference/metadata/index.md diff --git a/docs/reference/custom_fields/fields_list.md b/docs/reference/metadata/optional_metadata.md similarity index 62% rename from docs/reference/custom_fields/fields_list.md rename to docs/reference/metadata/optional_metadata.md index ce3dfec6..6ee9264d 100644 --- a/docs/reference/custom_fields/fields_list.md +++ b/docs/reference/metadata/optional_metadata.md @@ -1,15 +1,15 @@ -# Fields list +# Optional metadata fields list _Introduced in InvenioRDM v12_ -The following document is a reference guide for all the custom fields available in InvenioRDM. +The following document is a reference guide for the optional metadata fields available in InvenioRDM. !!!tip "How to add a field to an instance?" - If you want to add a field to an instance, please refer to the custom fields [documentation](../../customize/metadata/custom_fields/records.md#add-reusable-custom-fields-to-records). + If you want to add a field to an instance, please refer to the custom fields [documentation](../../customize/metadata/custom_fields/optional_fields.mds. ## Publishing information -This group of fields contains the metadata for "Journal", "Imprint" and "Thesis". Each field has its own data representation, however, they are grouped in the UI. +This group of fields contains the metadata for "Journal", "Imprint" and "Thesis". Each set of fields can be used independently, but the normal configuration is to group them in the UI. **Deposit form** @@ -19,7 +19,7 @@ This group of fields contains the metadata for "Journal", "Imprint" and "Thesis" ![Landing page](../../images/pub_info_landing_page.png) -Publishing information is displayed in the section "Details", on the right side bar, under "Published in". +Publishing information is typically displayed in the section "Details", on the right side bar, under "Published in", "Imprint", or "Awarding university". ### Journal @@ -28,6 +28,7 @@ This field implements a journal's metadata. It can be used to describe a journal **Metadata** - **title** `String`: The title of the journal. +- **issn** `ISSN`(defined by [idutils](https://github.com/inveniosoftware/idutils/blob/10b05b702b06e93f02774426df59a217035b1cee/idutils/__init__.py#L408)): The ISSN of the journal. - **volume** `String`: The volume where the article was published. - **issue** `String`: The issue within the volume. - **pages** `String`: The pages within the issue where the article was published. It can be a number or a range in any format. @@ -39,7 +40,7 @@ This nested field implements an imprint's metadata. It can be used to describe a **Metadata** - **title** `String`: The title of the book or report where the record was published. -- **isbn** `String`: The book's International Standard Book Number. Applies if the imprint is a book. +- **isbn** `ISBN`(defined by [idutils](https://github.com/inveniosoftware/idutils/blob/10b05b702b06e93f02774426df59a217035b1cee/idutils/__init__.py#L400)): The book's International Standard Book Number. Applies if the imprint is a book. - **place** `String`: Location where the book (or report) was published. - **pages** `String`: The pages within the book or report. It can be a number or a range in any format. @@ -73,11 +74,11 @@ Meeting information is displayed in the section "Details", under "Conference". - **place** `String`: Location where the meeting took place. - **session** `String`: Session within the meeting or conference. - **session_part** `String`: Part within the session. -- **url** `String`: Link of the conference website. +- **url** `URL`: Link of the conference website. -## Software +## CodeMeta -This group of fields contains metadata to describe a software record. +This group of fields contains metadata to describe a software record based on the [CodeMeta standard](https://codemeta.github.io/index.html). **Deposit form** @@ -91,8 +92,6 @@ Software information is displayed in the section "Additional details", under the **Metadata** -- **codeRepository** `String`: Link to the repository where the related code is located (e.g. Github). -- **programmingLanguage** `String`: Name of the programming language used to develop the software. -- **runtimePlatform** `String`: Runtime platform dependencies (e.g. Python3.8). -- **operatingSystem** `String`: Supported operating systems. -- **developmentStatus** `String`: Description of the development status (e.g. "Active"). Uses a controlled vocabulary defined in [repostatus](http://www.repostatus.org/). +- **codeRepository** `URL`: Link to the repository where the related code is located (e.g. Github). +- **programmingLanguage** `Vocabulary`: Name of the programming language used to develop the software from the [vocabulary](https://github.com/inveniosoftware/invenio-rdm-records/blob/e64dd0b81757a391584e63d162d5e6caf6780637/invenio_rdm_records/fixtures/data/vocabularies/contrib/codemeta/programming_languages.yaml). +- **developmentStatus** `Vocabulary`: Description of the development status (e.g. "Active"). Uses a controlled vocabulary defined in [repostatus](http://www.repostatus.org/).