1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-07-19 21:29:41 +02:00

refactor createMenuTree (#44)

* refactor createmenutree

* Update src/routes/middlewares/pages.js

Co-Authored-By: khaydarov <murod.haydarov@inbox.ru>

* push migration

* update

* remove migration and order is optional

* eslint fixes
This commit is contained in:
Murod Khaydarov 2019-02-19 17:29:45 +03:00 committed by GitHub
parent 529aca5e29
commit 7890d17255
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 65 deletions

View file

@ -23,6 +23,15 @@ class PagesOrder {
return order; return order;
} }
/**
* Returns all records about page's order
*
* @returns {Promise<PagesOrder[]>}
*/
static async getAll() {
return Model.getAll();
}
/** /**
* Pushes the child page to the parent's order list * Pushes the child page to the parent's order list
* *
@ -65,10 +74,15 @@ class PagesOrder {
* @return {Page[]} * @return {Page[]}
*/ */
static async getOrderedChildren(pages, currentPageId, parentPageId, ignoreSelf = false) { static async getOrderedChildren(pages, currentPageId, parentPageId, ignoreSelf = false) {
const children = await PagesOrder.get(parentPageId); const children = await Model.get(parentPageId);
const unordered = pages.filter(page => page._parent === parentPageId).map(page => page._id);
// Create unique array with ordered and unordered pages id
const ordered = [ ...new Set([...children.order, ...unordered]) ];
const result = []; const result = [];
children.order.forEach(pageId => { ordered.forEach(pageId => {
pages.forEach(page => { pages.forEach(page => {
if (page._id === pageId && (pageId !== currentPageId || !ignoreSelf)) { if (page._id === pageId && (pageId !== currentPageId || !ignoreSelf)) {
result.push(page); result.push(page);
@ -80,13 +94,16 @@ class PagesOrder {
} }
/** /**
* @param {string[]} unordered
* @param {string} currentPageId - page's id that changes the order * @param {string} currentPageId - page's id that changes the order
* @param {string} parentPageId - parent page's id that contains both two pages * @param {string} parentPageId - parent page's id that contains both two pages
* @param {string} putAbovePageId - page's id above which we put the target page * @param {string} putAbovePageId - page's id above which we put the target page
*/ */
static async update(currentPageId, parentPageId, putAbovePageId) { static async update(unordered, currentPageId, parentPageId, putAbovePageId) {
const pageOrder = await Model.get(parentPageId); const pageOrder = await Model.get(parentPageId);
// Create unique array with ordered and unordered pages id
pageOrder.order = [ ...new Set([...pageOrder.order, ...unordered]) ];
pageOrder.putAbove(currentPageId, putAbovePageId); pageOrder.putAbove(currentPageId, putAbovePageId);
await pageOrder.save(); await pageOrder.save();
} }

View file

@ -34,6 +34,18 @@ class PageOrder {
return new PageOrder(data); return new PageOrder(data);
} }
/**
* Find all pages which match passed query object
*
* @param {Object} query
* @returns {Promise<Page[]>}
*/
static async getAll(query = {}) {
const docs = await db.find(query);
return Promise.all(docs.map(doc => new PageOrder(doc)));
}
/** /**
* @constructor * @constructor
* *
@ -154,6 +166,13 @@ class PageOrder {
return this.order[currentPageInOrder + 1]; return this.order[currentPageInOrder + 1];
} }
/**
* @param {string[]} order - define new order
*/
set order(order) {
this._order = order;
}
/** /**
* Returns ordered list * Returns ordered list
* *

View file

@ -3,7 +3,6 @@ const router = express.Router();
const multer = require('multer')(); const multer = require('multer')();
const Pages = require('../../controllers/pages'); const Pages = require('../../controllers/pages');
const PagesOrder = require('../../controllers/pagesOrder'); const PagesOrder = require('../../controllers/pagesOrder');
const Aliases = require("../../controllers/aliases");
/** /**
* GET /page/:id * GET /page/:id
* *
@ -81,13 +80,15 @@ router.post('/page/:id', multer.any(), async (req, res) => {
try { try {
const {title, body, parent, putAbovePageId, uri} = req.body; const {title, body, parent, putAbovePageId, uri} = req.body;
const pages = await Pages.getAll();
let page = await Pages.get(id); let page = await Pages.get(id);
if (page._parent !== parent) { if (page._parent !== parent) {
await PagesOrder.move(page._parent, parent, id); await PagesOrder.move(page._parent, parent, id);
} else { } else {
if (putAbovePageId && putAbovePageId !== '0') { if (putAbovePageId && putAbovePageId !== '0') {
await PagesOrder.update(page._id, page._parent, putAbovePageId); const unordered = pages.filter( _page => _page._parent === page._parent).map(_page => _page._id);
await PagesOrder.update(unordered, page._id, page._parent, putAbovePageId);
} }
} }

View file

@ -4,44 +4,49 @@ const asyncMiddleware = require('../../utils/asyncMiddleware');
/** /**
* Process one-level pages list to parent-children list * Process one-level pages list to parent-children list
* @param {string[]} pages - list of all available pages *
* @param {string} parentPageId - parent page id
* @param {Page[]} pages - list of all available pages
* @param {PagesOrder[]} pagesOrder - list of pages order
* @param {number} level * @param {number} level
* @param {number} currentLevel * @param {number} currentLevel
* *
* @return {Page[]} * @return {Page[]}
*/ */
async function createMenuTree(pages, level = 1, currentLevel = 1) { function createMenuTree(parentPageId, pages, pagesOrder, level = 1, currentLevel = 1) {
return await Promise.all(pages.map(async pageId => { const childrenOrder = pagesOrder.find(order => order.data.page === parentPageId);
const parent = await Pages.get(pageId);
/** /**
* By default we accept that deepestChildren is empty Array * branch is a page children in tree
* @type {Array} * if we got some children order on parents tree, then we push found pages in order sequence
* otherwise just find all pages includes parent tree
*/ */
let deepestChildren = []; let ordered = [];
if (childrenOrder) {
/** ordered = childrenOrder.order.map( pageId => {
* Here we try to check parent's children order return pages.find( page => page._id === pageId);
* If we got something, pluck to found Page deeper and get its children order });
*/
try {
/**
* Go deeper until we didn't get the deepest level
* On each 'currentLevel' create new Menu Tree with ordered Page ids
*/
if (currentLevel !== level) {
const children = await PagesOrder.get(pageId);
deepestChildren = await createMenuTree(children.order, level, currentLevel + 1)
} }
} catch (e) {}
const unordered = pages.filter( page => page._parent === parentPageId);
const branch = [...new Set([...ordered, ...unordered])];
/** /**
* Assign parent's children with found Menu Tree * stop recursion when we got the passed max level
*/ */
if (currentLevel === level + 1) {
return [];
}
/**
* Each parents children can have subbranches
*/
return branch.filter(page => page && page._id).map( page => {
return Object.assign({ return Object.assign({
children: deepestChildren children: createMenuTree(page._id, pages, pagesOrder, level, currentLevel + 1)
}, parent.data); }, page.data);
})); });
} }
/** /**
@ -57,8 +62,9 @@ module.exports = asyncMiddleware(async function (req, res, next) {
*/ */
const parentIdOfRootPages = '0'; const parentIdOfRootPages = '0';
try { try {
const rootPages = await PagesOrder.get(parentIdOfRootPages); const pages = await Pages.getAll();
res.locals.menu = await createMenuTree(rootPages.order, 2); const pagesOrder = await PagesOrder.getAll();
res.locals.menu = createMenuTree(parentIdOfRootPages, pages, pagesOrder, 2);
} catch (error) { } catch (error) {
console.log('Can not load menu:', error); console.log('Can not load menu:', error);
} }

View file

@ -1,34 +1,5 @@
const Datastore = require('nedb'); const Datastore = require('nedb');
const config = require('../../../config'); const config = require('../../../config');
const db = new Datastore({filename: `./${config.database}/pagesOrder.db`, autoload: true}); const db = new Datastore({filename: `./${config.database}/pagesOrder.db`, autoload: true});
/**
* Current DataStore preparation
* Add initial row for RootPage
*/
(async function() {
const parentIdOfRootPages = '0';
const cbk = (resolve, reject) => (err, doc) => {
if (err) {
reject(err);
}
resolve(doc);
};
const order = await new Promise((resolve, reject) => {
db.findOne({page: parentIdOfRootPages}, cbk(resolve, reject));
});
if (!order) {
const initialData = {
page: '0',
order: []
};
await db.insert(initialData);
}
}());
module.exports = db; module.exports = db;