Added revisions

This commit is contained in:
Jori Lallo
2016-06-26 11:23:03 -07:00
parent 2bcf37fd83
commit 0026b092d2
5 changed files with 149 additions and 11 deletions

View File

@ -62,7 +62,7 @@ router.post('documents.create', auth(), async (ctx) => {
if (!ownerAtlas) throw httpErrors.BadRequest(); if (!ownerAtlas) throw httpErrors.BadRequest();
let parentDocumentObj; let parentDocumentObj = {};
if (parentDocument && ownerAtlas.type === 'atlas') { if (parentDocument && ownerAtlas.type === 'atlas') {
parentDocumentObj = await Document.findOne({ parentDocumentObj = await Document.findOne({
where: { where: {
@ -77,13 +77,17 @@ router.post('documents.create', auth(), async (ctx) => {
atlasId: ownerAtlas.id, atlasId: ownerAtlas.id,
teamId: user.teamId, teamId: user.teamId,
userId: user.id, userId: user.id,
lastModifiedById: user.id,
title: title, title: title,
text: text, text: text,
}); });
await document.createRevision();
// TODO: Move to afterSave hook if possible with imports // TODO: Move to afterSave hook if possible with imports
if (parentDocument && ownerAtlas.type === 'atlas') {
ownerAtlas.addNodeToNavigationTree(document); ownerAtlas.addNodeToNavigationTree(document);
await ownerAtlas.save(); await ownerAtlas.save();
}
ctx.body = { ctx.body = {
data: await presentDocument(document, true), data: await presentDocument(document, true),
@ -112,7 +116,9 @@ router.post('documents.update', auth(), async (ctx) => {
document.title = title; document.title = title;
document.text = text; document.text = text;
document.lastModifiedById = user.id;
await document.save(); await document.save();
await document.createRevision();
ctx.body = { ctx.body = {
data: await presentDocument(document, true), data: await presentDocument(document, true),

View File

@ -0,0 +1,80 @@
'use strict';
module.exports = {
up: function (queryInterface, Sequelize) {
queryInterface.createTable('revisions', {
id: {
type: 'UUID',
allowNull: false,
primaryKey: true
},
title:
{ type: 'CHARACTER VARYING',
allowNull: false,
},
text:
{ type: 'TEXT',
allowNull: true,
},
html:
{ type: 'TEXT',
allowNull: true,
},
preview:
{ type: 'TEXT',
allowNull: true,
},
createdAt:
{ type: 'TIMESTAMP WITH TIME ZONE',
allowNull: false,
},
updatedAt:
{ type: 'TIMESTAMP WITH TIME ZONE',
allowNull: false,
},
userId: {
type: 'UUID',
allowNull: false,
references: {
model: 'users',
}
},
documentId: {
type: 'UUID',
allowNull: false,
references: {
model: 'documents',
onDelete: 'CASCADE',
}
},
});
queryInterface.addColumn(
'documents',
'lastModifiedById',
{
type: 'UUID',
allowNull: false,
references: {
model: 'users',
}
}
);
queryInterface.addColumn(
'documents',
'revisionCount',
{
type: 'INTEGER',
defaultValue: 0
}
);
},
down: function (queryInterface, Sequelize) {
queryInterface.dropTable('revisions');
queryInterface.removeColumn('documents', 'lastModifiedById');
queryInterface.removeColumn('documents', 'revisionCount');
}
};

View File

@ -11,6 +11,7 @@ import {
truncateMarkdown, truncateMarkdown,
} from '../utils/truncate'; } from '../utils/truncate';
import User from './User'; import User from './User';
import Revision from './Revision';
slug.defaults.mode ='rfc3986'; slug.defaults.mode ='rfc3986';
@ -19,6 +20,13 @@ const generateSlug = (title, urlId) => {
return `${slugifiedTitle}-${urlId}`; return `${slugifiedTitle}-${urlId}`;
}; };
const documentBeforeSave = (doc) => {
doc.html = convertToMarkdown(doc.text);
doc.preview = truncateMarkdown(doc.text, 160);
doc.revisionCount = doc.revisionCount + 1;
return doc;
};
const Document = sequelize.define('document', { const Document = sequelize.define('document', {
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true },
urlId: { type: DataTypes.STRING, primaryKey: true }, urlId: { type: DataTypes.STRING, primaryKey: true },
@ -27,21 +35,23 @@ const Document = sequelize.define('document', {
text: DataTypes.TEXT, text: DataTypes.TEXT,
html: DataTypes.TEXT, html: DataTypes.TEXT,
preview: DataTypes.TEXT, preview: DataTypes.TEXT,
revisionCount: { type: DataTypes.INTEGER, defaultValue: 0, },
parentDocumentId: DataTypes.UUID, parentDocumentId: DataTypes.UUID,
lastModifiedById: {
type: 'UUID',
allowNull: false,
references: {
model: 'users',
}
},
}, { }, {
hooks: { hooks: {
beforeValidate: (doc) => { beforeValidate: (doc) => {
doc.urlId = randomstring.generate(15); doc.urlId = randomstring.generate(15);
}, },
beforeCreate: (doc) => { beforeCreate: documentBeforeSave,
doc.html = convertToMarkdown(doc.text); beforeUpdate: documentBeforeSave,
doc.preview = truncateMarkdown(doc.text, 160);
},
beforeUpdate: (doc) => {
doc.html = convertToMarkdown(doc.text);
doc.preview = truncateMarkdown(doc.text, 160);
},
}, },
instanceMethods: { instanceMethods: {
buildUrl() { buildUrl() {
@ -51,6 +61,17 @@ const Document = sequelize.define('document', {
getUrl() { getUrl() {
return `/documents/${ this.id }`; return `/documents/${ this.id }`;
}, },
async createRevision() {
// Create revision of the current (latest)
await Revision.create({
title: this.title,
text: this.text,
html: this.html,
preview: this.preview,
userId: this.lastModifiedById,
documentId: this.id,
});
},
} }
}); });

31
server/models/Revision.js Normal file
View File

@ -0,0 +1,31 @@
import {
DataTypes,
sequelize,
} from '../sequelize';
const Revision = sequelize.define('revision', {
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true },
title: DataTypes.STRING,
text: DataTypes.TEXT,
html: DataTypes.TEXT,
preview: DataTypes.TEXT,
userId: {
type: 'UUID',
allowNull: false,
references: {
model: 'users',
}
},
documentId: {
type: 'UUID',
allowNull: false,
references: {
model: 'documents',
onDelete: 'CASCADE',
}
},
});
export default Revision;