Skip to content

Instantly share code, notes, and snippets.

@anirudhjain75
Created April 10, 2020 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anirudhjain75/6f1852568ef35969f0974deb04890da3 to your computer and use it in GitHub Desktop.
Save anirudhjain75/6f1852568ef35969f0974deb04890da3 to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 2016 Ben Ockmore
* 2016 Sean Burke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// @flow
import * as achievement from '../../helpers/achievement';
import * as error from '../../../common/helpers/error';
import * as handler from '../../helpers/handler';
import * as propHelpers from '../../../client/helpers/props';
import * as search from '../../helpers/search';
import * as utils from '../../helpers/utils';
import type {$Request, $Response, NextFunction} from 'express';
import type {
EntityTypeString,
FormLanguageT as Language,
FormPublisherT as Publisher,
FormReleaseEventT as ReleaseEvent,
Transaction
} from 'bookbrainz-data/lib/func/types';
import {escapeProps, generateProps} from '../../helpers/props';
import AuthorPage from '../../../client/components/pages/entities/author';
import DeletionForm from '../../../client/components/forms/deletion';
import EditionGroupPage from '../../../client/components/pages/entities/edition-group';
import EditionPage from '../../../client/components/pages/entities/edition';
import EntityRevisions from '../../../client/components/pages/entity-revisions';
import Layout from '../../../client/containers/layout';
import Log from 'log';
import Promise from 'bluebird';
import PublisherPage from '../../../client/components/pages/entities/publisher';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import WorkPage from '../../../client/components/pages/entities/work';
import _ from 'lodash';
import config from '../../../common/helpers/config';
import {getEntityLabel} from '../../../client/helpers/entity';
import {getOrderedRevisionsForEntityPage} from '../../helpers/revisions';
import target from '../../templates/target';
type PassportRequest = $Request & {user: any, session: any};
const log = new Log(config.site.log);
const entityComponents = {
author: AuthorPage,
edition: EditionPage,
editionGroup: EditionGroupPage,
publisher: PublisherPage,
work: WorkPage
};
export function displayEntity(req: PassportRequest, res: $Response) {
const {orm}: {orm: any} = req.app.locals;
const {AchievementUnlock, EditorEntityVisits} = orm;
const {locals: resLocals}: {locals: any} = res;
const {entity}: {entity: any} = resLocals;
// Get unique identifier types for display
// $FlowFixMe
const identifierTypes = entity.identifierSet &&
_.uniqBy(
_.map(entity.identifierSet.identifiers, 'type'),
(type) => type.id
);
let editorEntityVisitPromise;
if (resLocals.user) {
editorEntityVisitPromise = new EditorEntityVisits({
bbid: resLocals.entity.bbid,
editorId: resLocals.user.id
})
.save(null, {method: 'insert'})
.then(() => achievement.processPageVisit(orm, resLocals.user.id))
.catch(
// error caused by duplicates we do not want in database
() => Promise.resolve(false)
);
}
else {
editorEntityVisitPromise = Promise.resolve(false);
}
let alertPromise = editorEntityVisitPromise.then((visitAlert) => {
let alertIds = [];
if (visitAlert.alert) {
alertIds = alertIds.concat(visitAlert.alert.split(',').map(
(id) => parseInt(id, 10)
));
}
if (_.isString(req.query.alert)) {
// $FlowFixMe
alertIds = alertIds.concat(req.query.alert.split(',').map(
(id) => parseInt(id, 10)
));
}
if (alertIds.length > 0) {
const promiseList = alertIds.map(
(achievementAlert) =>
new AchievementUnlock(
{id: achievementAlert}
)
.fetch({
require: true,
withRelated: 'achievement'
})
.then((unlock) => unlock.toJSON())
.then((unlock) => {
let unlockName;
if (req.user.id === unlock.editorId) {
unlockName = {
name: unlock.achievement.name
};
}
return unlockName;
})
.catch((err) => {
log.debug(err);
})
);
alertPromise = Promise.all(promiseList);
}
else {
alertPromise = Promise.resolve(false);
}
return alertPromise;
});
return alertPromise.then((alert) => {
const entityName = _.camelCase(entity.type);
const EntityComponent = entityComponents[entityName];
if (EntityComponent) {
const props = generateProps(req, res, {
alert,
identifierTypes
});
const markup = ReactDOMServer.renderToString(
<Layout {...propHelpers.extractLayoutProps(props)}>
<EntityComponent
{...propHelpers.extractEntityProps(props)}
/>
</Layout>
);
res.send(target({
markup,
page: entityName,
props: escapeProps(props),
script: '/js/entity/entity.js',
title: `${getEntityLabel(props.entity, false)} (${_.upperFirst(entityName)})`
}));
}
else {
throw new Error(
`Component was not found for the following entity:${entityName}`
);
}
});
}
export function displayDeleteEntity(req: PassportRequest, res: $Response) {
const props = generateProps(req, res);
const markup = ReactDOMServer.renderToString(
<Layout {...propHelpers.extractLayoutProps(props)}>
<DeletionForm entity={props.entity}/>
</Layout>
);
res.send(target({
markup,
props: escapeProps(props),
script: '/js/deletion.js'
}));
}
export async function displayRevisions(
req: PassportRequest, res: $Response, next: NextFunction, RevisionModel: any
) {
const size = req.query.size ? parseInt(req.query.size, 10) : 20;
const from = req.query.from ? parseInt(req.query.from, 10) : 0;
try {
// get 1 more revision than required to check nextEnabled
const orderedRevisions = await getOrderedRevisionsForEntityPage(from, size + 1, RevisionModel, req);
const {newResultsArray, nextEnabled} = utils.getNextEnabledAndResultsArray(orderedRevisions, size);
const props = generateProps(req, res, {
from,
nextEnabled,
revisions: newResultsArray,
showRevisionEditor: true,
showRevisionNote: true,
size
});
const markup = ReactDOMServer.renderToString(
<Layout {...propHelpers.extractLayoutProps(props)}>
<EntityRevisions
entity={props.entity}
{...propHelpers.extractChildProps(props)}
/>
</Layout>
);
return res.send(target({
markup,
page: 'revisions',
props: escapeProps(props),
script: '/js/entity/entity.js'
}));
}
catch (err) {
return next(err);
}
}
// eslint-disable-next-line consistent-return
export async function updateDisplayedRevisions(
req: PassportRequest, res: $Response, next: NextFunction, RevisionModel: any
) {
const size = req.query.size ? parseInt(req.query.size, 10) : 20;
const from = req.query.from ? parseInt(req.query.from, 10) : 0;
try {
const orderedRevisions = await getOrderedRevisionsForEntityPage(from, size, RevisionModel, req);
res.send(orderedRevisions);
}
catch (err) {
return next(err);
}
}
function _createNote(orm, content, editorID, revision, transacting) {
const {Note} = orm;
if (content) {
const revisionId = revision.get('id');
return new Note({
authorId: editorID,
content,
revisionId
})
.save(null, {transacting});
}
return null;
}
export function addNoteToRevision(req: PassportRequest, res: $Response) {
const {orm}: {orm: any} = req.app.locals;
const {Revision, bookshelf} = orm;
const editorJSON = req.session.passport.user;
const revision = Revision.forge({id: req.params.id});
const {body}: {body: any} = req;
const revisionNotePromise = bookshelf.transaction(
(transacting) => _createNote(
orm, body.note, editorJSON.id, revision, transacting
)
);
return handler.sendPromiseResult(res, revisionNotePromise);
}
async function deleteRelationships(orm, transacting, mainEntity) {
const mainBBID = mainEntity.bbid;
const {relationshipSet} = mainEntity;
const otherBBID = [];
const otherEntities = [];
if (relationshipSet) {
relationshipSet.relationships.map((relationship) => {
if (relationship.sourceBbid === mainBBID) {
otherBBID.push(relationship.targetBbid);
}
else if (relationship.targetBbid === mainBBID) {
otherBBID.push(relationshipSet.sourceBbid);
}
});
}
if (otherBBID.length) {
await Promise.all(otherBBID.map(async (entityBbid) => {
console.log('This is called with ', entityBbid);
const otherEntity = await getEntityByBBID(orm, transacting, entityBbid);
const otherEntityRelationshipSet = await otherEntity.relationshipSet()
.fetch({require: false, transacting, withRelated: 'relationships'});
console.log('otherEntity', await otherEntity);
console.log('RelationshipSet', await otherEntityRelationshipSet);
// console.log(await orm.func.relationship.getMasterRelationshipSetForEntity(orm, transacting, entityBbid));
// const tempEntity = await getEntityByBBID(orm, transacting, entityBbid);
// console.log(tempEntity);
// const otherEntityRelationshipSet = await tempEntity.relationshipSet()
// .fetch({require: false, transacting, withRelated: 'relationships'});
// console.log('temp entity', await otherEntityRelationshipSet);
// otherEntities.push(await otherEntityRelationshipSet);
}));
}
console.log(mainBBID);
console.log(otherBBID);
console.log(await otherEntities);
console.log(relationshipSet);
}
export function handleDelete(
orm: any, req: PassportRequest, res: $Response, HeaderModel: any,
RevisionModel: any
) {
const {entity}: {entity: any} = res.locals;
const {Revision, bookshelf} = orm;
const editorJSON = req.session.passport.user;
const {body}: {body: any} = req;
const entityDeletePromise = bookshelf.transaction((transacting) => {
deleteRelationships(orm, transacting, entity);
const editorUpdatePromise =
utils.incrementEditorEditCountById(orm, editorJSON.id, transacting);
const newRevisionPromise = new Revision({
authorId: editorJSON.id
}).save(null, {transacting});
// Get the parents of the new revision
const revisionParentsPromise = newRevisionPromise
.then((revision) =>
revision.related('parents').fetch({require: false, transacting}));
// Add the previous revision as a parent of this revision.
const parentAddedPromise =
revisionParentsPromise.then(
(parents) => parents && parents.attach(
entity.revisionId, {transacting}
)
);
const notePromise = newRevisionPromise
.then((revision) => _createNote(
orm, body.note, editorJSON.id, revision, transacting
));
/*
* No trigger for deletions, so manually create the <Entity>Revision
* and update the entity header
*/
const newEntityRevisionPromise = newRevisionPromise
.then((revision) => new RevisionModel({
bbid: entity.bbid,
dataId: null,
id: revision.get('id')
}).save(null, {
method: 'insert',
transacting
}));
const entityHeaderPromise = newEntityRevisionPromise
.then((entityRevision) => new HeaderModel({
bbid: entity.bbid,
masterRevisionId: entityRevision.get('id')
}).save(null, {transacting}));
const searchDeleteEntityPromise = search.deleteEntity(entity)
.catch(err => { log.error(err); });
return Promise.join(
editorUpdatePromise, newRevisionPromise, notePromise,
newEntityRevisionPromise, entityHeaderPromise, parentAddedPromise,
searchDeleteEntityPromise
);
});
return handler.sendPromiseResult(res, entityDeletePromise);
}
type ProcessEditionSetsBody = {
languages: Array<Language>,
publishers: Array<Publisher>,
releaseEvents: Array<ReleaseEvent>
};
async function processEditionSets(
orm: any,
currentEntity: ?{},
body: ProcessEditionSetsBody,
transacting: Transaction
) {
const languageSetID = _.get(currentEntity, ['languageSet', 'id']);
const oldLanguageSet = await (
languageSetID &&
orm.LanguageSet.forge({id: languageSetID})
.fetch({transacting, withRelated: ['languages']})
);
const languages = _.get(body, 'languages') || [];
const newLanguageSetIDPromise = orm.func.language.updateLanguageSet(
orm, transacting, oldLanguageSet,
languages.map((languageID) => ({id: languageID}))
)
.then((set) => set && set.get('id'));
const publisherSetID = _.get(currentEntity, ['publisherSet', 'id']);
const oldPublisherSet = await (
publisherSetID &&
orm.PublisherSet.forge({id: publisherSetID})
.fetch({transacting, withRelated: ['publishers']})
);
const publishers = _.get(body, 'publishers') || [];
const newPublisherSetIDPromise = orm.func.publisher.updatePublisherSet(
orm, transacting, oldPublisherSet,
publishers.map((publisherBBID) => ({bbid: publisherBBID}))
)
.then((set) => set && set.get('id'));
const releaseEventSetID = _.get(currentEntity, ['releaseEventSet', 'id']);
const oldReleaseEventSet = await (
releaseEventSetID &&
orm.ReleaseEventSet.forge({id: releaseEventSetID})
.fetch({transacting, withRelated: ['releaseEvents']})
);
const releaseEvents = _.get(body, 'releaseEvents') || [];
// if areaId is not present, set it to null.
// otherwise it shows error while comparing old and new releaseEvent;
if (releaseEvents[0] && _.isNil(releaseEvents[0].areaId)) {
releaseEvents[0].areaId = null;
}
const newReleaseEventSetIDPromise =
orm.func.releaseEvent.updateReleaseEventSet(
orm, transacting, oldReleaseEventSet, releaseEvents
)
.then((set) => set && set.get('id'));
return Promise.props({
languageSetId: newLanguageSetIDPromise,
publisherSetId: newPublisherSetIDPromise,
releaseEventSetId: newReleaseEventSetIDPromise
});
}
async function processWorkSets(
orm, currentEntity: ?{}, body: {languages: Array<Language>},
transacting: Transaction
) {
const id = _.get(currentEntity, ['languageSet', 'id']);
const oldSet = await (
id &&
orm.LanguageSet.forge({id})
.fetch({transacting, withRelated: ['languages']})
);
const languages = _.get(body, 'languages') || [];
return Promise.props({
languageSetId: orm.func.language.updateLanguageSet(
orm, transacting, oldSet,
languages.map((languageID) => ({id: languageID}))
).then((set) => set && set.get('id'))
});
}
function processEntitySets(
orm: any,
currentEntity: ?{},
entityType: EntityTypeString,
body: any,
transacting: Transaction
) {
if (entityType === 'Edition') {
return processEditionSets(orm, currentEntity, body, transacting);
}
if (entityType === 'Work') {
return processWorkSets(orm, currentEntity, body, transacting);
}
return Promise.resolve(null);
}
async function getNextAliasSet(orm, transacting, currentEntity, body) {
const {AliasSet} = orm;
const id = _.get(currentEntity, ['aliasSet', 'id']);
const oldAliasSet = await (
id &&
new AliasSet({id}).fetch({require: false, transacting, withRelated: ['aliases']})
);
return orm.func.alias.updateAliasSet(
orm, transacting, oldAliasSet,
oldAliasSet && oldAliasSet.get('defaultAliasId'),
body.aliases || []
);
}
async function getNextIdentifierSet(orm, transacting, currentEntity, body) {
const {IdentifierSet} = orm;
const id = _.get(currentEntity, ['identifierSet', 'id']);
const oldIdentifierSet = await (
id &&
new IdentifierSet({id}).fetch({
require: false,
transacting, withRelated: ['identifiers']
})
);
return orm.func.identifier.updateIdentifierSet(
orm, transacting, oldIdentifierSet, body.identifiers || []
);
}
async function getNextRelationshipSets(
orm, transacting, currentEntity, body
) {
const {RelationshipSet} = orm;
const id = _.get(currentEntity, ['relationshipSet', 'id']);
const oldRelationshipSet = await (
id &&
new RelationshipSet({id}).fetch({
require: false,
transacting, withRelated: ['relationships']
})
);
const updatedRelationships = orm.func.relationship.updateRelationshipSets(
orm, transacting, oldRelationshipSet, body.relationships || []
);
return updatedRelationships;
}
async function getNextAnnotation(
orm, transacting, currentEntity, body, revision
) {
const {Annotation} = orm;
const id = _.get(currentEntity, ['annotation', 'id']);
const oldAnnotation = await (
id && new Annotation({id}).fetch({require: false, transacting})
);
return body.annotation ? orm.func.annotation.updateAnnotation(
orm, transacting, oldAnnotation, body.annotation, revision
) : Promise.resolve(null);
}
async function getNextDisambiguation(orm, transacting, currentEntity, body) {
const {Disambiguation} = orm;
const id = _.get(currentEntity, ['disambiguation', 'id']);
const oldDisambiguation = await (
id && new Disambiguation({id}).fetch({require: false, transacting})
);
return orm.func.disambiguation.updateDisambiguation(
orm, transacting, oldDisambiguation, body.disambiguation
);
}
async function getChangedProps(
orm, transacting, isNew, currentEntity, body, entityType,
newRevisionPromise, derivedProps
) {
const aliasSetPromise =
getNextAliasSet(orm, transacting, currentEntity, body);
const identSetPromise =
getNextIdentifierSet(orm, transacting, currentEntity, body);
const annotationPromise = newRevisionPromise.then(
(revision) => getNextAnnotation(
orm, transacting, currentEntity, body, revision
)
);
const disambiguationPromise =
getNextDisambiguation(orm, transacting, currentEntity, body);
const entitySetIdsPromise =
processEntitySets(orm, currentEntity, entityType, body, transacting);
const [
aliasSet, identSet, annotation, disambiguation, entitySetIds
] = await Promise.all([
aliasSetPromise, identSetPromise, annotationPromise,
disambiguationPromise, entitySetIdsPromise
]);
const propsToSet = {
aliasSetId: aliasSet && aliasSet.get('id'),
annotationId: annotation && annotation.get('id'),
disambiguationId:
disambiguation && disambiguation.get('id'),
identifierSetId: identSet && identSet.get('id'),
...derivedProps,
...entitySetIds
};
if (isNew) {
return propsToSet;
}
// Construct a set of differences between the new values and old
return _.reduce(propsToSet, (result, value, key) => {
if (!_.isEqual(value, currentEntity[key])) {
result[key] = value;
}
return result;
}, {});
}
function fetchOrCreateMainEntity(
orm, transacting, isNew, currentEntity, entityType
) {
const model = utils.getEntityModelByType(orm, entityType);
const entity = model.forge({bbid: currentEntity.bbid});
if (isNew) {
return Promise.resolve(entity);
}
return entity.fetch({transacting});
}
async function getEntityByBBID(orm, transacting, bbid) {
const entityHeader = await orm.Entity.forge({bbid}).fetch({transacting});
const model = utils.getEntityModelByType(orm, entityHeader.get('type'));
return model.forge({bbid}).fetch({transacting});
}
function fetchEntitiesForRelationships(
orm, transacting, currentEntity, relationshipSets
) {
const bbidsToFetch = _.without(
_.keys(relationshipSets), _.get(currentEntity, 'bbid')
);
return Promise.all(bbidsToFetch.map(
(bbid) =>
getEntityByBBID(orm, transacting, bbid)
));
}
async function setParentRevisions(transacting, newRevision, parentRevisionIDs) {
if (_.isEmpty(parentRevisionIDs)) {
return Promise.resolve(null);
}
// Get the parents of the new revision
const parents =
await newRevision.related('parents').fetch({transacting});
// Add the previous revision as a parent of this revision.
return parents.attach(parentRevisionIDs, {transacting});
}
async function saveEntitiesAndFinishRevision(
orm, transacting, isNew: boolean, newRevision: any, mainEntity: any,
updatedEntities: [], editorID: number, note: string
) {
const parentRevisionIDs = _.compact(_.uniq(updatedEntities.map(
(entityModel) => entityModel.get('revisionId')
)));
const entitiesSavedPromise = Promise.all(
_.map(updatedEntities, (entityModel) => {
entityModel.set('revisionId', newRevision.get('id'));
const shouldInsert =
entityModel.get('bbid') === mainEntity.get('bbid') && isNew;
const method = shouldInsert ? 'insert' : 'update';
return entityModel.save(null, {method, transacting});
})
);
const editorUpdatePromise =
utils.incrementEditorEditCountById(orm, editorID, transacting);
const notePromise = _createNote(
orm, note, editorID, newRevision, transacting
);
const parentsAddedPromise =
setParentRevisions(transacting, newRevision, parentRevisionIDs);
/** model.save returns a refreshed model */
const [savedEntities, ...others] = await Promise.all([
entitiesSavedPromise,
editorUpdatePromise,
parentsAddedPromise,
notePromise
]);
return savedEntities.find(entityModel => entityModel.get('bbid') === mainEntity.get('bbid')) || mainEntity;
}
export function handleCreateOrEditEntity(
req: PassportRequest,
res: $Response,
entityType: EntityTypeString,
derivedProps: {}
) {
const {orm}: {orm: any} = req.app.locals;
const {Entity, Revision, bookshelf} = orm;
const editorJSON = req.user;
const {body}: {body: any} = req;
const {locals: resLocals}: {locals: any} = res;
let currentEntity: ?{
aliasSet: ?{id: number},
annotation: ?{id: number},
bbid: string,
disambiguation: ?{id: number},
identifierSet: ?{id: number},
type: EntityTypeString
} = resLocals.entity;
const entityEditPromise = bookshelf.transaction(async (transacting) => {
// Determine if a new entity is being created
const isNew = !currentEntity;
if (isNew) {
const newEntity = await new Entity({type: entityType})
.save(null, {transacting});
const newEntityBBID = newEntity.get('bbid');
body.relationships = _.map(
body.relationships,
({sourceBbid, targetBbid, ...others}) => ({
sourceBbid: sourceBbid || newEntityBBID,
targetBbid: targetBbid || newEntityBBID,
...others
})
);
currentEntity = newEntity.toJSON();
}
// Then, edit the entity
const newRevisionPromise = new Revision({
authorId: editorJSON.id
}).save(null, {transacting});
const relationshipSetsPromise = getNextRelationshipSets(
orm, transacting, currentEntity, body
);
const changedPropsPromise = getChangedProps(
orm, transacting, isNew, currentEntity, body, entityType,
newRevisionPromise, derivedProps
);
const [newRevision, changedProps, relationshipSets] =
await Promise.all([
newRevisionPromise, changedPropsPromise, relationshipSetsPromise
]);
// If there are no differences, bail
if (_.isEmpty(changedProps) && _.isEmpty(relationshipSets)) {
throw new error.FormSubmissionError('No Updated Field');
}
// Fetch or create main entity
const mainEntity = await fetchOrCreateMainEntity(
orm, transacting, isNew, currentEntity, entityType
);
// Fetch all entities that definitely exist
const otherEntities = await fetchEntitiesForRelationships(
orm, transacting, currentEntity, relationshipSets
);
_.forOwn(changedProps, (value, key) => mainEntity.set(key, value));
const allEntities = [...otherEntities, mainEntity];
_.forEach(allEntities, (entityModel) => {
const bbid: string = entityModel.get('bbid');
if (_.has(relationshipSets, bbid)) {
entityModel.set(
'relationshipSetId',
relationshipSets[bbid] && relationshipSets[bbid].get('id')
);
}
});
const savedMainEntity = await saveEntitiesAndFinishRevision(
orm, transacting, isNew, newRevision, mainEntity, allEntities,
editorJSON.id, body.note
);
/** savedMainEntity should already be updated, but we need to refresh the aliases for search reindexing */
const savedEntityWithRelationships = await savedMainEntity.refresh({
transacting,
withRelated: ['aliasSet.aliases']
});
return savedEntityWithRelationships.toJSON();
});
const achievementPromise = entityEditPromise.then(
(entityJSON) => achievement.processEdit(
orm, editorJSON.id, entityJSON.revisionId
)
.then((unlock) => {
if (unlock.alert) {
entityJSON.alert = unlock.alert;
}
return entityJSON;
})
);
return handler.sendPromiseResult(
res,
achievementPromise,
search.indexEntity
);
}
type AliasEditorT = {
language: ?number,
name: string,
primary: boolean,
sortName: string
};
type NameSectionT = {
disambiguation: string,
language: ?number,
name: string,
sortName: string
};
export function constructAliases(
aliasEditor: {[string]: AliasEditorT}, nameSection: NameSectionT
) {
const aliases = _.map(
aliasEditor,
(
{language: languageId, name, primary, sortName}: AliasEditorT,
id
) => ({
default: false,
id,
languageId,
name,
primary,
sortName
})
);
return [{
default: true,
id: nameSection.id,
languageId: nameSection.language,
name: nameSection.name,
primary: true,
sortName: nameSection.sortName
}, ...aliases];
}
type IdentifierEditorT = {
type: number,
value: string
};
export function constructIdentifiers(
identifierEditor: {[string]: IdentifierEditorT}
) {
return _.map(
identifierEditor,
({type: typeId, value}: IdentifierEditorT, id: string) =>
({id, typeId, value})
);
}
export function constructRelationships(relationshipSection) {
return _.map(
relationshipSection.relationships,
({rowID, relationshipType, sourceEntity, targetEntity}) => ({
id: rowID,
sourceBbid: _.get(sourceEntity, 'bbid'),
targetBbid: _.get(targetEntity, 'bbid'),
typeId: relationshipType.id
})
);
}
/**
* Returns the index of the default alias if defined in the aliasSet.
* If there is no defaultAliasId, return the first alias where default = true.
* Returns null if there are no aliases in the set.
* @param {Object} aliasSet - The entity's aliasSet returned by the ORM
* @param {Object[]} aliasSet.aliases - The array of aliases contained in the set
* @param {string} aliasSet.defaultAliasId - The id of the set's default alias
* @returns {?number} The index of the default alias, or 0; returns null if 0 aliases in set
*/
export function getDefaultAliasIndex(aliasSet) {
if (_.isNil(aliasSet)) {
return null;
}
const {aliases, defaultAliasId} = aliasSet;
if (!aliases || !aliases.length) {
return null;
}
let index;
if (!_.isNil(defaultAliasId) && isFinite(defaultAliasId)) {
let defaultAliasIdNumber = defaultAliasId;
if (_.isString(defaultAliasId)) {
defaultAliasIdNumber = Number(defaultAliasId);
}
index = aliases.findIndex((alias) => alias.id === defaultAliasIdNumber);
}
else {
index = aliases.findIndex((alias) => alias.default);
}
return index > 0 ? index : 0;
}
export function areaToOption(
area: {comment: string, id: number, name: string}
) {
if (!area) {
return null;
}
const {id} = area;
return {
disambiguation: area.comment,
id,
text: area.name,
type: 'area'
};
}
export function compareEntitiesByDate(a, b) {
const aDate = _.get(a, 'releaseEventSet.releaseEvents[0].date', null);
const bDate = _.get(b, 'releaseEventSet.releaseEvents[0].date', null);
if (_.isNull(aDate)) {
/*
* return a positive value,
* so that non-null dates always come before null dates.
*/
return 1;
}
if (_.isNull(bDate)) {
/*
* return a negative value,
* so that non-null dates always come before null dates.
*/
return -1;
}
return new Date(aDate).getTime() - new Date(bDate).getTime();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment