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:
parent
529aca5e29
commit
7890d17255
5 changed files with 79 additions and 65 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue