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/models/Atlas.js
2016-07-06 21:36:50 -07:00

158 lines
4.0 KiB
JavaScript

import {
DataTypes,
sequelize,
} from '../sequelize';
import _isEqual from 'lodash/isEqual';
import Document from './Document';
const allowedAtlasTypes = [['atlas', 'journal']];
const Atlas = sequelize.define('atlas', {
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true },
name: DataTypes.STRING,
description: DataTypes.STRING,
type: { type: DataTypes.STRING, validate: { isIn: allowedAtlasTypes }},
/* type: atlas */
navigationTree: DataTypes.JSONB,
}, {
tableName: 'atlases',
hooks: {
// beforeValidate: (doc) => {
// doc.urlId = randomstring.generate(15);
// },
// beforeCreate: (doc) => {
// doc.html = convertToMarkdown(doc.text);
// doc.preview = truncateMarkdown(doc.text, 160);
// },
// beforeUpdate: (doc) => {
// doc.html = convertToMarkdown(doc.text);
// doc.preview = truncateMarkdown(doc.text, 160);
// },
},
instanceMethods: {
async getStructure() {
if (this.navigationTree) {
return this.navigationTree;
}
const getNodeForDocument = async (document) => {
const children = await Document.findAll({ where: {
parentDocumentId: document.id,
atlasId: this.id,
}});
let childNodes = []
await Promise.all(children.map(async (child) => {
childNodes.push(await getNodeForDocument(child));
}));
return {
title: document.title,
id: document.id,
url: document.getUrl(),
children: childNodes,
};
}
const rootDocument = await Document.findOne({
where: {
parentDocumentId: null,
atlasId: this.id,
}
});
if (rootDocument) {
return await getNodeForDocument(rootDocument);
} else {
return; // TODO should create a root doc
}
},
async updateNavigationTree(tree = this.navigationTree) {
let nodeIds = [];
nodeIds.push(tree.id);
const rootDocument = await Document.findOne({
where: {
id: tree.id,
atlasId: this.id,
},
});
if (!rootDocument) throw new Error;
let newTree = {
id: tree.id,
title: rootDocument.title,
url: rootDocument.getUrl(),
children: [],
};
const getIdsForChildren = async (children) => {
const childNodes = [];
for (const child of children) {
const childDocument = await Document.findOne({
where: {
id: child.id,
atlasId: this.id,
},
});
if (childDocument) {
childNodes.push({
id: childDocument.id,
title: childDocument.title,
url: childDocument.getUrl(),
children: await getIdsForChildren(child.children),
})
nodeIds.push(child.id);
}
}
return childNodes;
};
newTree.children = await getIdsForChildren(tree.children);
const documents = await Document.findAll({
attributes: ['id'],
where: {
atlasId: this.id,
}
});
const documentIds = documents.map(doc => doc.id);
if (!_isEqual(nodeIds.sort(), documentIds.sort())) {
throw new Error('Invalid navigation tree');
}
this.navigationTree = newTree;
await this.save();
return newTree;
},
async addNodeToNavigationTree(document) {
const newNode = {
id: document.id,
title: document.title,
url: document.getUrl(),
children: [],
}
const insertNode = (node) => {
if (document.parentDocumentId === node.id) {
node.children.push(newNode);
} else {
node.children = node.children.map(childNode => {
return insertNode(childNode);
})
}
return node;
};
this.navigationTree = insertNode(this.navigationTree);
}
}
});
Atlas.hasMany(Document, { as: 'documents', foreignKey: 'atlasId' });
export default Atlas;