This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
outline/server/services/backlinks.js
Tom Moor 091e542406 feat: Backlinks (#979)
* feat: backlinks

* feat: add backlinkDocumentId to documents.list

* chore: refactor
fix: create and delete backlink handling

* fix: guard against self links

* feat: basic frontend
fix: race condition

* styling

* test: fix parse ids

* self review

* linting

* feat: Improved link styling

* fix: Increase clickable area at bottom of doc / between references

* perf: global styles are SLOW
2019-07-07 19:25:45 -07:00

98 lines
2.9 KiB
JavaScript

// @flow
import { difference } from 'lodash';
import type { DocumentEvent } from '../events';
import { Document, Revision, Backlink } from '../models';
import parseDocumentIds from '../../shared/utils/parseDocumentIds';
export default class Backlinks {
async on(event: DocumentEvent) {
switch (event.name) {
case 'documents.publish': {
const document = await Document.findByPk(event.modelId);
const linkIds = parseDocumentIds(document.text);
await Promise.all(
linkIds.map(async linkId => {
const linkedDocument = await Document.findByPk(linkId);
if (linkedDocument.id === event.modelId) return;
await Backlink.findOrCreate({
where: {
documentId: linkedDocument.id,
reverseDocumentId: event.modelId,
},
defaults: {
userId: document.lastModifiedById,
},
});
})
);
break;
}
case 'documents.update': {
// no-op for now
if (event.autosave) return;
// no-op for drafts
const document = await Document.findByPk(event.modelId);
if (!document.publishedAt) return;
const [currentRevision, previsionRevision] = await Revision.findAll({
where: { documentId: event.modelId },
order: [['createdAt', 'desc']],
limit: 2,
});
const previousLinkIds = parseDocumentIds(previsionRevision.text);
const currentLinkIds = parseDocumentIds(currentRevision.text);
const addedLinkIds = difference(currentLinkIds, previousLinkIds);
const removedLinkIds = difference(previousLinkIds, currentLinkIds);
await Promise.all(
addedLinkIds.map(async linkId => {
const linkedDocument = await Document.findByPk(linkId);
if (linkedDocument.id === event.modelId) return;
await Backlink.findOrCreate({
where: {
documentId: linkedDocument.id,
reverseDocumentId: event.modelId,
},
defaults: {
userId: currentRevision.userId,
},
});
})
);
await Promise.all(
removedLinkIds.map(async linkId => {
const document = await Document.findByPk(linkId);
await Backlink.destroy({
where: {
documentId: document.id,
reverseDocumentId: event.modelId,
},
});
})
);
break;
}
case 'documents.delete': {
await Backlink.destroy({
where: {
reverseDocumentId: event.modelId,
},
});
await Backlink.destroy({
where: {
documentId: event.modelId,
},
});
break;
}
default:
}
}
}