Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BB-394 fix(display): Deleted work not shown in the edition anymore. #347

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/client/components/pages/entities/work-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {kebabCase as _kebabCase} from 'lodash';


const {Button, Table} = bootstrap;

const {getEntityDisambiguation} = entityHelper;
Expand Down Expand Up @@ -63,13 +64,11 @@ function WorkTable({entity, works}) {
</tr>
</thead>
<tbody>
{
works.map((work) => (
<WorkTableRow
key={work.bbid}
work={work}
/>
))}
{works.map((work) => (work.typeId ?
<WorkTableRow
key={work.bbid}
work={work}
/> : null))}
</tbody>
</Table>
<Button
Expand Down
180 changes: 115 additions & 65 deletions src/server/routes/entity/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,71 +250,6 @@ export function addNoteToRevision(req: PassportRequest, res: $Response) {
return handler.sendPromiseResult(res, revisionNotePromise);
}

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) => {
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({transacting}));

// Add the previous revision as a parent of this revision.
const parentAddedPromise =
revisionParentsPromise.then(
(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}));

return Promise.join(
editorUpdatePromise, newRevisionPromise, notePromise,
newEntityRevisionPromise, entityHeaderPromise, parentAddedPromise,
search.deleteEntity(entity)
);
});

return handler.sendPromiseResult(res, entityDeletePromise);
}

type ProcessEditionSetsBody = {
languages: Array<Language>,
publishers: Array<Publisher>,
Expand Down Expand Up @@ -773,6 +708,121 @@ export function handleCreateOrEditEntity(
);
}


async function deleteEntityRelationships(orm, transacting, mainEntity) {
const mainEntityBBID = mainEntity.get('bbid');
let allEntities = [];
const relationshipSet = await mainEntity.relationshipSet()
.fetch({require: false, transacting, withRelated: 'relationships'});
if (!relationshipSet) {
return allEntities;
}
const relationships = relationshipSet.related('relationships').toJSON();

const otherEntitiesToFetch = relationships
.reduce((accumulator, relationship) => {
if (relationship.sourceBbid === mainEntityBBID) {
accumulator.push(relationship.targetBbid);
}
else if (relationship.targetBbid === mainEntityBBID) {
accumulator.push(relationship.sourceBbid);
}
return accumulator;
}, []);

await Promise.all(otherEntitiesToFetch.map(
async (bbid) => {
const otherEntity = await getEntityByBBID(orm, transacting, bbid);

const otherEntityRelationshipSet = await otherEntity.relationshipSet()
.fetch({require: false, transacting, withRelated: 'relationships'});
if (!otherEntityRelationshipSet) {
return;
}
const otherEntityRelationships = otherEntityRelationshipSet.related('relationships').toJSON();

// Remove relationships with entity being deleted
const cleanedUpRelationships = otherEntityRelationships
.filter(({sourceBbid, targetBbid}) =>
mainEntityBBID !== sourceBbid &&
mainEntityBBID !== targetBbid);

// If there's a difference, apply the new relationships array.
if (cleanedUpRelationships.length !== otherEntityRelationships.length) {
const {RelationshipSet} = orm;

// This is what I came up with, there is no sample code I can find that
// creates a new Relationship set without a new ID. Is it also working
// through a trigger?
Comment on lines +754 to +756
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's what I did with that for the merging tool:
a448238#diff-0eaa45e02a38b45e1429cfb72db6b17eR709-R715 (lines 709-715)

The new RelationshipSet is created by the ORM helper function updateRelationshipSets (https://github.com/bookbrainz/bookbrainz-data-js/blob/1d36915dcd5b895c6860048d8051a79784618967/src/func/relationship.js#L88)

const newRelationshipSet = new RelationshipSet();

await newRelationshipSet.save(null, {transacting});

await orm.func.relationship.updateRelationshipSets(
orm, transacting, newRelationshipSet, cleanedUpRelationships
);

otherEntity.set(
'relationshipSetId',
newRelationshipSet.get('id')
);
// List of BBID of all the affected entities
allEntities = _.unionBy(allEntities, [otherEntity], 'id');
}
}
));

return allEntities;
}

export function handleDelete(
orm: any, req: PassportRequest, res: $Response, HeaderModel: any,
RevisionModel: any
) {
const {entity: mainEntityJSON}: {entity: any} = res.locals;
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(async (transacting) => {
const mainEntity = await getEntityByBBID(orm, transacting, mainEntityJSON.bbid);

const newRevision = new Revision({authorId: editorJSON.id});

await newRevision.save(null, {transacting});

const newEntityRevision = new RevisionModel({
bbid: mainEntity.get('bbid'),
dataId: null,
id: newRevision.get('id')
});

await newEntityRevision.save(null, {
method: 'insert',
transacting
});

const entityHeaderModel = new HeaderModel({
bbid: mainEntity.get('bbid'),
masterRevisionId: newEntityRevision.get('id')
});

await entityHeaderModel.save(null, {transacting});

const allEntities = await deleteEntityRelationships(orm, transacting, mainEntity);

await saveEntitiesAndFinishRevision(
orm, transacting, false, newRevision, mainEntity, allEntities,
editorJSON.id, body.note
);

return search.deleteEntity(entity).catch(err => { log.error(err); });
});

return handler.sendPromiseResult(res, entityDeletePromise);
}

type AliasEditorT = {
language: ?number,
name: string,
Expand Down