From 66b1cfdabcc9c8f4db3908a298e48bfb5729c79a Mon Sep 17 00:00:00 2001 From: tri10 Date: Tue, 3 May 2022 17:01:32 +0530 Subject: [PATCH 1/2] feat(EG): copy edition name to edition group --- .../entity-editor/name-section/actions.ts | 16 +++++++++++++++- .../name-section/name-section.js | 19 ++++++++++++++++++- .../entity-editor/name-section/reducer.js | 7 +++++-- src/server/routes/entity/edition.js | 1 + src/server/routes/entity/entity.tsx | 16 ++++++++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/client/entity-editor/name-section/actions.ts b/src/client/entity-editor/name-section/actions.ts index 2551849695..40dbd04bdd 100644 --- a/src/client/entity-editor/name-section/actions.ts +++ b/src/client/entity-editor/name-section/actions.ts @@ -26,7 +26,7 @@ export const UPDATE_NAME_FIELD = 'UPDATE_NAME_FIELD'; export const UPDATE_SORT_NAME_FIELD = 'UPDATE_SORT_NAME_FIELD'; export const UPDATE_WARN_IF_EXISTS = 'UPDATE_WARN_IF_EXISTS'; export const UPDATE_SEARCH_RESULTS = 'UPDATE_SEARCH_RESULTS'; - +export const UPDATE_COPY_CHECKBOX = 'UPDATE_COPY_CHECKBOX'; export type Action = { type: string, payload?: unknown, @@ -203,3 +203,17 @@ export function searchName( }); }; } + +/** + * Produces an action indicating that the checkbox + * should be updated with the provided value. + * + * @param {boolean} isCheck - The new value to be used for the checkbox. + * @returns {Action} The resulting UPDATE_COPY_CHECKBOX action. + */ +export function updateCheckbox(isCheck:boolean): Action { + return { + payload: isCheck, + type: UPDATE_COPY_CHECKBOX + }; +} diff --git a/src/client/entity-editor/name-section/name-section.js b/src/client/entity-editor/name-section/name-section.js index 774050f93c..80891abe8e 100644 --- a/src/client/entity-editor/name-section/name-section.js +++ b/src/client/entity-editor/name-section/name-section.js @@ -16,13 +16,14 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -import {Alert, Col, ListGroup, Row} from 'react-bootstrap'; +import {Alert, Col, Form, ListGroup, Row} from 'react-bootstrap'; import { checkIfNameExists, debouncedUpdateDisambiguationField, debouncedUpdateNameField, debouncedUpdateSortNameField, searchName, + updateCheckbox, updateLanguageField } from './actions'; import {isAliasEmpty, isRequiredDisambiguationEmpty} from '../helpers'; @@ -63,6 +64,7 @@ import {getEntityDisambiguation} from '../../helpers/entity'; * @param {string} props.nameValue - The name currently set for this entity. * @param {string} props.sortNameValue - The sort name currently set for this * entity. + * @param {Function} props.onCheckboxToggle - A function to be called when toggle copy name to EG checkbox * @param {Function} props.onLanguageChange - A function to be called when a * different language type is selected. * @param {Function} props.onNameChange - A function to be called when the name @@ -129,6 +131,7 @@ class NameSection extends React.Component { render() { const { + action, disambiguationDefaultValue, entityType, exactMatches, @@ -136,6 +139,7 @@ class NameSection extends React.Component { languageValue, nameValue, sortNameValue, + onCheckboxToggle, onLanguageChange, onSortNameChange, onDisambiguationChange, @@ -172,6 +176,17 @@ class NameSection extends React.Component { onChange={this.handleNameChange} /> + {action === 'edit' && entityType === 'edition' && + + + + } {isRequiredDisambiguationEmpty( warnIfExists, @@ -271,6 +286,7 @@ NameSection.propTypes = { languageOptions: PropTypes.array.isRequired, languageValue: PropTypes.number, nameValue: PropTypes.string.isRequired, + onCheckboxToggle: PropTypes.func.isRequired, onDisambiguationChange: PropTypes.func.isRequired, onLanguageChange: PropTypes.func.isRequired, onNameChange: PropTypes.func.isRequired, @@ -314,6 +330,7 @@ function mapStateToProps(rootState) { function mapDispatchToProps(dispatch, {entity, entityType}) { const entityBBID = entity && entity.bbid; return { + onCheckboxToggle: (event) => dispatch(updateCheckbox(event.target.checked)), onDisambiguationChange: (event) => dispatch(debouncedUpdateDisambiguationField(event.target.value)), onLanguageChange: (value) => diff --git a/src/client/entity-editor/name-section/reducer.js b/src/client/entity-editor/name-section/reducer.js index ca2553f33e..f7c3704538 100644 --- a/src/client/entity-editor/name-section/reducer.js +++ b/src/client/entity-editor/name-section/reducer.js @@ -17,14 +17,15 @@ */ import { - UPDATE_DISAMBIGUATION_FIELD, UPDATE_LANGUAGE_FIELD, UPDATE_NAME_FIELD, - UPDATE_SEARCH_RESULTS, UPDATE_SORT_NAME_FIELD, UPDATE_WARN_IF_EXISTS + UPDATE_COPY_CHECKBOX, UPDATE_DISAMBIGUATION_FIELD, UPDATE_LANGUAGE_FIELD, + UPDATE_NAME_FIELD, UPDATE_SEARCH_RESULTS, UPDATE_SORT_NAME_FIELD, UPDATE_WARN_IF_EXISTS } from './actions'; import Immutable from 'immutable'; function reducer( state = Immutable.Map({ + copyToEG: false, disambiguation: '', exactMatches: [], language: null, @@ -48,6 +49,8 @@ function reducer( return state.set('searchResults', payload); case UPDATE_WARN_IF_EXISTS: return state.set('exactMatches', payload); + case UPDATE_COPY_CHECKBOX: + return state.set('copyToEG', payload); // no default } return state; diff --git a/src/server/routes/entity/edition.js b/src/server/routes/entity/edition.js index e5b49c8b68..ee9fc311aa 100644 --- a/src/server/routes/entity/edition.js +++ b/src/server/routes/entity/edition.js @@ -73,6 +73,7 @@ function transformNewForm(data) { return { aliases, annotation: data.annotationSection.content, + copyToEG: data.nameSection.copyToEG ?? false, depth: data.editionSection.depth && parseInt(data.editionSection.depth, 10), disambiguation: data.nameSection.disambiguation, diff --git a/src/server/routes/entity/entity.tsx b/src/server/routes/entity/entity.tsx index b949fd3828..44bddfe468 100644 --- a/src/server/routes/entity/entity.tsx +++ b/src/server/routes/entity/entity.tsx @@ -1020,6 +1020,7 @@ export function handleCreateOrEditEntity( aliasSet: {id: number} | null | undefined, annotation: {id: number} | null | undefined, bbid: string, + editionGroup:any | undefined, disambiguation: {id: number} | null | undefined, identifierSet: {id: number} | null | undefined, type: EntityTypeString @@ -1085,6 +1086,21 @@ export function handleCreateOrEditEntity( let allEntities = [...otherEntities, mainEntity] .filter(entity => entity.get('dataId') !== null); + // copy name to the edition group + if (!isNew && entityType === 'Edition' && body.copyToEG) { + const currentEditionGroup = currentEntity.editionGroup; + const entityDefaultAlias = body.aliases.find((alias) => alias.default); + if (currentEditionGroup.defaultAlias.name !== entityDefaultAlias.name) { + const tempBody = {aliases: [{...currentEditionGroup.defaultAlias, default: true, name: entityDefaultAlias.name}]}; + const aliasSet = await getNextAliasSet(orm, transacting, currentEditionGroup, tempBody); + const EGEntity = await fetchOrCreateMainEntity( + orm, transacting, false, currentEditionGroup.bbid, 'EditionGroup' + ); + EGEntity.set('aliasSetId', aliasSet.id); + EGEntity.shouldInsert = false; + allEntities.push(EGEntity); + } + } if (isMergeOperation) { allEntities = await processMergeOperation(orm, transacting, req.session, mainEntity, allEntities, relationshipSets); From 595f1ac943114fab15cb07bca48bf276224ad19d Mon Sep 17 00:00:00 2001 From: tri10 Date: Thu, 9 Jun 2022 23:25:57 +0530 Subject: [PATCH 2/2] minor code improvements --- .../entity-editor/name-section/actions.ts | 8 ++-- .../name-section/name-section.js | 26 ++++++------ .../entity-editor/name-section/reducer.js | 8 ++-- src/server/routes/entity/edition.js | 4 +- src/server/routes/entity/entity.tsx | 41 +++++++++++++------ 5 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/client/entity-editor/name-section/actions.ts b/src/client/entity-editor/name-section/actions.ts index 40dbd04bdd..dd682d45d6 100644 --- a/src/client/entity-editor/name-section/actions.ts +++ b/src/client/entity-editor/name-section/actions.ts @@ -26,7 +26,7 @@ export const UPDATE_NAME_FIELD = 'UPDATE_NAME_FIELD'; export const UPDATE_SORT_NAME_FIELD = 'UPDATE_SORT_NAME_FIELD'; export const UPDATE_WARN_IF_EXISTS = 'UPDATE_WARN_IF_EXISTS'; export const UPDATE_SEARCH_RESULTS = 'UPDATE_SEARCH_RESULTS'; -export const UPDATE_COPY_CHECKBOX = 'UPDATE_COPY_CHECKBOX'; +export const UPDATE_COPY_NAME_TO_EDITION_GROUP = 'UPDATE_COPY_NAME_TO_EDITION_GROUP'; export type Action = { type: string, payload?: unknown, @@ -209,11 +209,11 @@ export function searchName( * should be updated with the provided value. * * @param {boolean} isCheck - The new value to be used for the checkbox. - * @returns {Action} The resulting UPDATE_COPY_CHECKBOX action. + * @returns {Action} The resulting UPDATE_COPY_NAME_TO_EDITION_GROUP action. */ -export function updateCheckbox(isCheck:boolean): Action { +export function updateCopyNameCheckbox(isCheck:boolean): Action { return { payload: isCheck, - type: UPDATE_COPY_CHECKBOX + type: UPDATE_COPY_NAME_TO_EDITION_GROUP }; } diff --git a/src/client/entity-editor/name-section/name-section.js b/src/client/entity-editor/name-section/name-section.js index 80891abe8e..8bd77e4e15 100644 --- a/src/client/entity-editor/name-section/name-section.js +++ b/src/client/entity-editor/name-section/name-section.js @@ -23,7 +23,7 @@ import { debouncedUpdateNameField, debouncedUpdateSortNameField, searchName, - updateCheckbox, + updateCopyNameCheckbox, updateLanguageField } from './actions'; import {isAliasEmpty, isRequiredDisambiguationEmpty} from '../helpers'; @@ -176,17 +176,6 @@ class NameSection extends React.Component { onChange={this.handleNameChange} /> - {action === 'edit' && entityType === 'edition' && - - - - } {isRequiredDisambiguationEmpty( warnIfExists, @@ -272,6 +261,17 @@ class NameSection extends React.Component { onChange={onDisambiguationChange} /> + {action === 'edit' && entityType === 'edition' && + + + + } ); @@ -330,7 +330,7 @@ function mapStateToProps(rootState) { function mapDispatchToProps(dispatch, {entity, entityType}) { const entityBBID = entity && entity.bbid; return { - onCheckboxToggle: (event) => dispatch(updateCheckbox(event.target.checked)), + onCheckboxToggle: (event) => dispatch(updateCopyNameCheckbox(event.target.checked)), onDisambiguationChange: (event) => dispatch(debouncedUpdateDisambiguationField(event.target.value)), onLanguageChange: (value) => diff --git a/src/client/entity-editor/name-section/reducer.js b/src/client/entity-editor/name-section/reducer.js index f7c3704538..61ac4e2aa4 100644 --- a/src/client/entity-editor/name-section/reducer.js +++ b/src/client/entity-editor/name-section/reducer.js @@ -17,7 +17,7 @@ */ import { - UPDATE_COPY_CHECKBOX, UPDATE_DISAMBIGUATION_FIELD, UPDATE_LANGUAGE_FIELD, + UPDATE_COPY_NAME_TO_EDITION_GROUP, UPDATE_DISAMBIGUATION_FIELD, UPDATE_LANGUAGE_FIELD, UPDATE_NAME_FIELD, UPDATE_SEARCH_RESULTS, UPDATE_SORT_NAME_FIELD, UPDATE_WARN_IF_EXISTS } from './actions'; import Immutable from 'immutable'; @@ -25,7 +25,7 @@ import Immutable from 'immutable'; function reducer( state = Immutable.Map({ - copyToEG: false, + copyNameToEditionGroup: false, disambiguation: '', exactMatches: [], language: null, @@ -49,8 +49,8 @@ function reducer( return state.set('searchResults', payload); case UPDATE_WARN_IF_EXISTS: return state.set('exactMatches', payload); - case UPDATE_COPY_CHECKBOX: - return state.set('copyToEG', payload); + case UPDATE_COPY_NAME_TO_EDITION_GROUP: + return state.set('copyNameToEditionGroup', payload); // no default } return state; diff --git a/src/server/routes/entity/edition.js b/src/server/routes/entity/edition.js index ee9fc311aa..ae60c2374a 100644 --- a/src/server/routes/entity/edition.js +++ b/src/server/routes/entity/edition.js @@ -73,7 +73,7 @@ function transformNewForm(data) { return { aliases, annotation: data.annotationSection.content, - copyToEG: data.nameSection.copyToEG ?? false, + copyNameToEditionGroup: data.nameSection.copyNameToEditionGroup ?? false, depth: data.editionSection.depth && parseInt(data.editionSection.depth, 10), disambiguation: data.nameSection.disambiguation, @@ -297,7 +297,7 @@ router.param( middleware.makeEntityLoader( 'Edition', [ - 'editionGroup.defaultAlias', + 'editionGroup.aliasSet.aliases', 'languageSet.languages', 'editionFormat', 'editionStatus', diff --git a/src/server/routes/entity/entity.tsx b/src/server/routes/entity/entity.tsx index 44bddfe468..27c0197467 100644 --- a/src/server/routes/entity/entity.tsx +++ b/src/server/routes/entity/entity.tsx @@ -1002,6 +1002,31 @@ function sanitizeBody(body:any) { return body; } +/** + * @param {Object} body - form body + * @param {Object} currentEditionGroup - current Edition Group + * @param {Object} orm - orm + * @param {Object} transacting - bookshelf transaction + * @returns {Promise} - resolve to edition group modal + */ +async function copyNameToEditionGroup(body:Record, currentEditionGroup:Record, orm, transacting):Promise { + const entityDefaultAlias = body.aliases.find((alias) => alias.default); + const tempAliases = currentEditionGroup.aliasSet.aliases.map((alias) => { + const mAlias = _.pick(alias, ['id', 'name', 'sortName', 'languageId', 'primary', 'default']); + if (alias.id === currentEditionGroup.aliasSet.defaultAliasId) { + return {...mAlias, default: true, name: entityDefaultAlias.name}; + } + return mAlias; + }); + const aliasSet = await getNextAliasSet(orm, transacting, currentEditionGroup, {aliases: tempAliases}); + const EGEntity = await fetchOrCreateMainEntity( + orm, transacting, false, currentEditionGroup.bbid, 'EditionGroup' + ); + EGEntity.set('aliasSetId', aliasSet.id); + EGEntity.shouldInsert = false; + return EGEntity; +} + export function handleCreateOrEditEntity( req: PassportRequest, res: $Response, @@ -1087,19 +1112,9 @@ export function handleCreateOrEditEntity( .filter(entity => entity.get('dataId') !== null); // copy name to the edition group - if (!isNew && entityType === 'Edition' && body.copyToEG) { - const currentEditionGroup = currentEntity.editionGroup; - const entityDefaultAlias = body.aliases.find((alias) => alias.default); - if (currentEditionGroup.defaultAlias.name !== entityDefaultAlias.name) { - const tempBody = {aliases: [{...currentEditionGroup.defaultAlias, default: true, name: entityDefaultAlias.name}]}; - const aliasSet = await getNextAliasSet(orm, transacting, currentEditionGroup, tempBody); - const EGEntity = await fetchOrCreateMainEntity( - orm, transacting, false, currentEditionGroup.bbid, 'EditionGroup' - ); - EGEntity.set('aliasSetId', aliasSet.id); - EGEntity.shouldInsert = false; - allEntities.push(EGEntity); - } + if (!isNew && entityType === 'Edition' && body.copyNameToEditionGroup) { + const EGEntity = await copyNameToEditionGroup(body, currentEntity.editionGroup, orm, transacting); + allEntities.push(EGEntity); } if (isMergeOperation) { allEntities = await processMergeOperation(orm, transacting, req.session,