From 453cf703e63d5d16c57e31fb78d3539705d2c469 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Tue, 22 Oct 2024 16:56:49 +0100 Subject: [PATCH 1/3] Override Creatibutor form fields --- .../overridableRegistry/mapping.js | 7 +- .../ic_data_repo/OptionalRoleCreatibutors.js | 486 ++++++++++++++++++ site/ic_data_repo/webpack.py | 2 +- 3 files changed, 493 insertions(+), 2 deletions(-) create mode 100644 site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js diff --git a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js index e26f951..64e5282 100644 --- a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js +++ b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js @@ -8,4 +8,9 @@ * Add here all the overridden components of your app. */ -export const overriddenComponents = {} +import { OptionalRoleCreatibutorsField, NoRoleCreatibutorsField } from "../../ic_data_repo/OptionalRoleCreatibutors" + +export const overriddenComponents = { + "InvenioAppRdm.Deposit.ContributorsField.container": OptionalRoleCreatibutorsField, + "InvenioAppRdm.Deposit.CreatorsField.container": NoRoleCreatibutorsField, +}; diff --git a/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js b/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js new file mode 100644 index 0000000..f1e3ecc --- /dev/null +++ b/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js @@ -0,0 +1,486 @@ +import React, { Component } from "react"; +import { + CreatibutorsField, + sortOptions, +} from "@js/invenio_rdm_records"; +import { CreatibutorsFieldItem } from "@js/invenio_rdm_records/src/deposit/fields/CreatibutorsField/CreatibutorsFieldItem"; +import { CreatibutorsModal } from "@js/invenio_rdm_records/src/deposit/fields/CreatibutorsField/CreatibutorsModal"; +import { CreatibutorsIdentifiers } from "@js/invenio_rdm_records/src/deposit/fields/CreatibutorsField/CreatibutorsIdentifiers"; +import { CREATIBUTOR_TYPE } from "@js/invenio_rdm_records/src/deposit/fields/CreatibutorsField/type"; +import { AffiliationsField } from "@js/invenio_rdm_records/src/deposit/fields/AffiliationsField"; +import _get from "lodash/get"; +import _map from "lodash/map"; +import _isEmpty from "lodash/isEmpty"; +import PropTypes from "prop-types"; +import { Formik } from "formik"; +import { getIn, FieldArray } from "formik"; +import { Button, Form, Label, List, Modal, Icon } from "semantic-ui-react"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { DndProvider } from "react-dnd"; +import { + FieldLabel, + SelectField, + Image, + RadioField, + RemoteSelectField, + TextField, + } from "react-invenio-forms"; +import { i18next } from "@translations/invenio_rdm_records/i18next"; + +const creatibutorNameDisplay = (value) => { + const creatibutorType = _get(value, "person_or_org.type", CREATIBUTOR_TYPE.PERSON); + const isPerson = creatibutorType === CREATIBUTOR_TYPE.PERSON; + + const familyName = _get(value, "person_or_org.family_name", ""); + const givenName = _get(value, "person_or_org.given_name", ""); + const affiliationName = _get(value, `affiliations[0].name`, ""); + const name = _get(value, `person_or_org.name`); + + const affiliation = affiliationName ? ` (${affiliationName})` : ""; + + if (isPerson) { + const givenNameSuffix = givenName ? `, ${givenName}` : ""; + return `${familyName}${givenNameSuffix}${affiliation}`; + } + + return `${name}${affiliation}`; +}; + + +const ModalActions = { + ADD: "add", + EDIT: "edit", +}; + +const NamesAutocompleteOptions = { + SEARCH: "search", + SEARCH_ONLY: "search_only", + OFF: "off", +}; + +class OptionalRoleCreatibutorsModal extends CreatibutorsModal { + render() { + const { initialCreatibutor, autocompleteNames, roleOptions, trigger, action, includeRole} = + this.props; + const { + open, + showPersonForm, + personIdentifiers, + personAffiliations, + organizationIdentifiers, + organizationAffiliations, + saveAndContinueLabel, + } = this.state; + + const ActionLabel = this.displayActionLabel(); + return ( + + {({ values, resetForm, handleSubmit }) => { + const personOrOrgPath = `person_or_org`; + const typeFieldPath = `${personOrOrgPath}.type`; + const familyNameFieldPath = `${personOrOrgPath}.family_name`; + const givenNameFieldPath = `${personOrOrgPath}.given_name`; + const organizationNameFieldPath = `${personOrOrgPath}.name`; + const identifiersFieldPath = `${personOrOrgPath}.identifiers`; + const affiliationsFieldPath = "affiliations"; + const roleFieldPath = "role"; + return ( + this.openModal()} + open={open} + trigger={trigger} + onClose={() => { + this.closeModal(); + resetForm(); + }} + closeIcon + closeOnDimmerClick={false} + > + + {ActionLabel} + + +
+ + { + this.setState({ + isOrganization: false, + }); + formikProps.form.setFieldValue( + typeFieldPath, + CREATIBUTOR_TYPE.PERSON + ); + formikProps.form.setFieldValue( + identifiersFieldPath, + personIdentifiers + ); + formikProps.form.setFieldValue( + affiliationsFieldPath, + personAffiliations + ); + }} + // eslint-disable-next-line + autoFocus + optimized + /> + { + this.setState({ + isOrganization: true, + }); + formikProps.form.setFieldValue( + typeFieldPath, + CREATIBUTOR_TYPE.ORGANIZATION + ); + formikProps.form.setFieldValue( + affiliationsFieldPath, + organizationAffiliations + ); + formikProps.form.setFieldValue( + identifiersFieldPath, + organizationIdentifiers + ); + }} + optimized + /> + + {_get(values, typeFieldPath, "") === CREATIBUTOR_TYPE.PERSON ? ( +
+ {autocompleteNames !== NamesAutocompleteOptions.OFF && ( + options} + suggestionAPIUrl="/api/names" + serializeSuggestions={this.serializeSuggestions} + onValueChange={this.onPersonSearchChange} + ref={this.namesAutocompleteRef} + /> + )} + {showPersonForm && ( +
+ + + + + ({ + text: identifier, + value: identifier, + key: identifier, + }) + )} + fieldPath={identifiersFieldPath} + ref={this.identifiersRef} + /> + +
+ )} +
+ ) : ( + <> + {autocompleteNames !== NamesAutocompleteOptions.OFF && ( + options} + suggestionAPIUrl="/api/affiliations" + serializeSuggestions={this.serializeSuggestions} + onValueChange={this.onOrganizationSearchChange} + /> + )} + + ({ + text: identifier, + value: identifier, + key: identifier, + }) + )} + fieldPath={identifiersFieldPath} + ref={this.identifiersRef} + placeholder={i18next.t("e.g. ROR, ISNI or GND.")} + /> + + + )} + {(_get(values, typeFieldPath) === CREATIBUTOR_TYPE.ORGANIZATION || + (showPersonForm && + _get(values, typeFieldPath) === CREATIBUTOR_TYPE.PERSON)) && includeRole && ( +
+ +
+ )} + +
+ + + } + includeRole={includeRole} + /> + {creatibutorsError && typeof creatibutorsError == "string" && ( + + )} + + + ); + } +} + + + +export class OptionalRoleCreatibutorsField extends CreatibutorsField { + render() { + const { fieldPath } = this.props; + return ( + ( + + )} + /> + ); + } +} + +OptionalRoleCreatibutorsField.propTypes = { + includeRole: PropTypes.bool, + ...CreatibutorsField.propTypes, +} + +OptionalRoleCreatibutorsField.defaultProps = { + includeRole: true, + ...CreatibutorsField.defaultProps, +} + +export class NoRoleCreatibutorsField extends OptionalRoleCreatibutorsField {} + +NoRoleCreatibutorsField.defaultProps = { + includeRole: false, + ...CreatibutorsField.defaultProps +} diff --git a/site/ic_data_repo/webpack.py b/site/ic_data_repo/webpack.py index cd2cad6..e286d0d 100644 --- a/site/ic_data_repo/webpack.py +++ b/site/ic_data_repo/webpack.py @@ -9,7 +9,7 @@ themes={ "semantic-ui": dict( entry={ - # Add your webpack entrypoints + "optional-role-creatibutors": "./js/ic_data_repo/OptionalRoleCreatibutors.js" # noqa: E501 }, ), }, From 3dd245d138023a064ffeef55b3c05eaaaa50ce88 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Wed, 23 Oct 2024 14:56:58 +0100 Subject: [PATCH 2/3] Add help text to creator field --- .../invenio_app_rdm/overridableRegistry/mapping.js | 12 +++++++----- .../js/ic_data_repo/OptionalRoleCreatibutors.js | 14 +++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js index 64e5282..a3f7718 100644 --- a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js +++ b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js @@ -4,13 +4,15 @@ // Invenio App RDM is free software; you can redistribute it and/or modify it // under the terms of the MIT License; see LICENSE file for more details. -/** - * Add here all the overridden components of your app. - */ +import { OptionalRoleCreatibutorsField } from "../../ic_data_repo/OptionalRoleCreatibutors"; +import { parametrize } from "react-overridable"; -import { OptionalRoleCreatibutorsField, NoRoleCreatibutorsField } from "../../ic_data_repo/OptionalRoleCreatibutors" +const CreatorsField = parametrize(OptionalRoleCreatibutorsField, { + helpText: "The main individuals or institutions involved in creating the data set.", + includeRole: false, +}); export const overriddenComponents = { "InvenioAppRdm.Deposit.ContributorsField.container": OptionalRoleCreatibutorsField, - "InvenioAppRdm.Deposit.CreatorsField.container": NoRoleCreatibutorsField, + "InvenioAppRdm.Deposit.CreatorsField.container": CreatorsField, }; diff --git a/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js b/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js index f1e3ecc..2ed77ab 100644 --- a/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js +++ b/site/ic_data_repo/assets/semantic-ui/js/ic_data_repo/OptionalRoleCreatibutors.js @@ -378,6 +378,7 @@ class OptionalRoleCreatibutorsFieldForm extends Component { autocompleteNames, addButtonLabel, includeRole, + helpText, } = this.props; const creatibutorsList = getIn(values, fieldPath, []); @@ -447,6 +448,10 @@ class OptionalRoleCreatibutorsFieldForm extends Component { )} + { + // eslint-disable-next-line jsx-a11y/label-has-associated-control + helpText && + } ); } @@ -470,17 +475,12 @@ export class OptionalRoleCreatibutorsField extends CreatibutorsField { OptionalRoleCreatibutorsField.propTypes = { includeRole: PropTypes.bool, + helpText: PropTypes.sting, ...CreatibutorsField.propTypes, } OptionalRoleCreatibutorsField.defaultProps = { includeRole: true, + helpText: "", ...CreatibutorsField.defaultProps, } - -export class NoRoleCreatibutorsField extends OptionalRoleCreatibutorsField {} - -NoRoleCreatibutorsField.defaultProps = { - includeRole: false, - ...CreatibutorsField.defaultProps -} From 1aa7f211f8fde0fce0692f5b4725e6ad8bb9b9f4 Mon Sep 17 00:00:00 2001 From: Christopher Cave-Ayland Date: Wed, 23 Oct 2024 16:22:47 +0100 Subject: [PATCH 3/3] Add help text for contributors field --- assets/js/invenio_app_rdm/overridableRegistry/mapping.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js index a3f7718..19e4571 100644 --- a/assets/js/invenio_app_rdm/overridableRegistry/mapping.js +++ b/assets/js/invenio_app_rdm/overridableRegistry/mapping.js @@ -12,7 +12,12 @@ const CreatorsField = parametrize(OptionalRoleCreatibutorsField, { includeRole: false, }); +const ContributorsField = parametrize(OptionalRoleCreatibutorsField, { + helpText: "Individuals or institutions, in addition to the creators, responsible for collecting, managing, distributing or other-wise contributing to the development of the resource.", + includeRole: true, +}); + export const overriddenComponents = { - "InvenioAppRdm.Deposit.ContributorsField.container": OptionalRoleCreatibutorsField, + "InvenioAppRdm.Deposit.ContributorsField.container": ContributorsField, "InvenioAppRdm.Deposit.CreatorsField.container": CreatorsField, };