Moved menu to the DB and started modernizing old code

react_convert
Mark Moffat 2018-01-14 18:02:10 +01:00
parent ceb23e1ce1
commit ecef3b8224
7 changed files with 222 additions and 195 deletions

View File

@ -6,7 +6,7 @@
"promise" "promise"
], ],
"parserOptions": { "parserOptions": {
"ecmaVersion": 6 "ecmaVersion": 2017
}, },
"globals": { "globals": {
"$": true "$": true

18
app.js
View File

@ -260,16 +260,22 @@ app.use((err, req, res, next) => {
}); });
}); });
// Nodejs version check
if(parseInt(process.version.split('.')[0].replace('v', '')) <= 7){
console.log(colors.red('Please use Node.js version 7.x or above'));
process.exit(2);
}
app.on('uncaughtException', (err) => { app.on('uncaughtException', (err) => {
console.error(colors.red(err.stack)); console.error(colors.red(err.stack));
process.exit(); process.exit(2);
}); });
MongoClient.connect(config.databaseConnectionString, {}, (err, client) => { MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
// On connection error we display then exit // On connection error we display then exit
if(err){ if(err){
console.log(colors.red('Error connecting to MongoDB: ' + err)); console.log(colors.red('Error connecting to MongoDB: ' + err));
process.exit(); process.exit(2);
} }
// select DB // select DB
@ -281,22 +287,22 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
db.products = db.collection('products'); db.products = db.collection('products');
db.orders = db.collection('orders'); db.orders = db.collection('orders');
db.pages = db.collection('pages'); db.pages = db.collection('pages');
db.menu = db.collection('menu');
// add db to app for routes // add db to app for routes
app.db = db; app.db = db;
// add indexing // add indexing
common.runIndexing(app) common.runIndexing(app)
.then(common.testData(db)) .then(common.testData(db, app))
.then(app.listen(app.get('port')))
.then(() => { .then(() => {
// lift the app // lift the app
app.listen(app.get('port'), () => {
console.log(colors.green('expressCart running on host: http://localhost:' + app.get('port'))); console.log(colors.green('expressCart running on host: http://localhost:' + app.get('port')));
});
}) })
.catch(() => { .catch(() => {
console.error(colors.red('Error setting up indexes:' + err)); console.error(colors.red('Error setting up indexes:' + err));
process.exit(); process.exit(2);
}); });
}); });

View File

@ -1,4 +1,5 @@
[ {
"products":[
{ {
"productPermalink": "duckworth-jacket", "productPermalink": "duckworth-jacket",
"productTitle": "Duckworth Woolfill Jacket", "productTitle": "Duckworth Woolfill Jacket",
@ -64,4 +65,19 @@
"productImage": "/uploads/scout-backpack/scout-backpack_a035275d-8975-4a05-8456-5e1ec35f020f_grande.jpg", "productImage": "/uploads/scout-backpack/scout-backpack_a035275d-8975-4a05-8456-5e1ec35f020f_grande.jpg",
"productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Navy\",\"Moss\",\"Nutmeg\",\"Khaki\"]}}" "productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Navy\",\"Moss\",\"Nutmeg\",\"Khaki\"]}}"
} }
],
"menu": {
"items": [
{
"title" : "Backpacks",
"link" : "backpack",
"order" : 0
},
{
"title" : "Boots",
"link" : "boots",
"order" : 1
}
] ]
}
}

View File

@ -359,7 +359,6 @@ router.get('/product/new', common.restrict, (req, res) => {
// insert new product form action // insert new product form action
router.post('/product/insert', common.restrict, (req, res) => { router.post('/product/insert', common.restrict, (req, res) => {
let db = req.app.db; let db = req.app.db;
let config = common.getConfig();
let doc = { let doc = {
productPermalink: req.body.frmProductPermalink, productPermalink: req.body.frmProductPermalink,
@ -852,7 +851,8 @@ router.post('/settings/option/remove', common.restrict, (req, res) => {
}); });
// settings update // settings update
router.get('/settings/menu', common.restrict, (req, res) => { router.get('/settings/menu', common.restrict, async (req, res) => {
let db = req.app.db;
res.render('settings_menu', { res.render('settings_menu', {
title: 'Cart menu', title: 'Cart menu',
session: req.session, session: req.session,
@ -861,17 +861,18 @@ router.get('/settings/menu', common.restrict, (req, res) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
config: common.getConfig(), config: common.getConfig(),
menu: common.getMenu().items menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
// settings page list // settings page list
router.get('/settings/pages', common.restrict, (req, res) => { router.get('/settings/pages', common.restrict, (req, res) => {
let db = req.app.db; let db = req.app.db;
common.dbQuery(db.pages, {}, null, null, (err, pages) => { common.dbQuery(db.pages, {}, null, null, async (err, pages) => {
if(err){ if(err){
console.info(err.stack); console.info(err.stack);
} }
res.render('settings_pages', { res.render('settings_pages', {
title: 'Static pages', title: 'Static pages',
pages: pages, pages: pages,
@ -881,13 +882,15 @@ router.get('/settings/pages', common.restrict, (req, res) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
config: common.getConfig(), config: common.getConfig(),
menu: common.getMenu().items menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
}); });
// settings pages new // settings pages new
router.get('/settings/pages/new', common.restrict, (req, res) => { router.get('/settings/pages/new', common.restrict, async (req, res) => {
let db = req.app.db;
res.render('settings_page_edit', { res.render('settings_page_edit', {
title: 'Static pages', title: 'Static pages',
session: req.session, session: req.session,
@ -897,18 +900,19 @@ router.get('/settings/pages/new', common.restrict, (req, res) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
config: common.getConfig(), config: common.getConfig(),
menu: common.getMenu().items menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
// settings pages editor // settings pages editor
router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { router.get('/settings/pages/edit/:page', common.restrict, (req, res) => {
let db = req.app.db; let db = req.app.db;
db.pages.findOne({_id: common.getId(req.params.page)}, (err, page) => { db.pages.findOne({_id: common.getId(req.params.page)}, async (err, page) => {
if(err){ if(err){
console.info(err.stack); console.info(err.stack);
} }
// page found // page found
const menu = common.sortMenu(await common.getMenu(db));
if(page){ if(page){
res.render('settings_page_edit', { res.render('settings_page_edit', {
title: 'Static pages', title: 'Static pages',
@ -920,7 +924,7 @@ router.get('/settings/pages/edit/:page', common.restrict, (req, res) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
config: common.getConfig(), config: common.getConfig(),
menu: common.getMenu().items menu
}); });
}else{ }else{
// 404 it! // 404 it!
@ -930,9 +934,8 @@ router.get('/settings/pages/edit/:page', common.restrict, (req, res) => {
message: '404 Error - Page not found', message: '404 Error - Page not found',
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu
} });
);
} }
}); });
}); });

View File

@ -4,6 +4,7 @@ const colors = require('colors');
const lunr = require('lunr'); const lunr = require('lunr');
const fs = require('fs'); const fs = require('fs');
const escape = require('html-entities').AllHtmlEntities; const escape = require('html-entities').AllHtmlEntities;
let ObjectId = require('mongodb').ObjectID;
// common functions // common functions
exports.checkLogin = function(req, res, next){ exports.checkLogin = function(req, res, next){
@ -229,77 +230,99 @@ exports.updateConfig = function(fields){
} }
}; };
exports.getMenu = function(){ exports.getMenu = function(db){
let fs = require('fs'); return db.menu.findOne({});
let path = require('path');
let menuFile = JSON.parse(fs.readFileSync(path.join(__dirname, '../config/menu.json'), 'utf8'));
menuFile.items = _.sortBy(menuFile.items, 'order');
return menuFile;
}; };
// creates a new menu item // creates a new menu item
exports.newMenu = function(req, res){ exports.newMenu = function(req, res){
let fs = require('fs'); const db = req.app.db;
let path = require('path'); return exports.getMenu(db)
let menuJson = '../config/menu.json'; .then((menu) => {
let menuFile = require(menuJson); // if no menu present
if(!menu){
menu = {};
menu.items = [];
}
let newNav = { let newNav = {
title: req.body.navMenu, title: req.body.navMenu,
link: req.body.navLink, link: req.body.navLink,
order: Object.keys(menuFile.items).length + 1 order: Object.keys(menu.items).length + 1
}; };
// add new menu item menu.items.push(newNav);
menuFile.items.push(newNav); return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
.then(() => {
// write file
try{
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
return true; return true;
}catch(e){ });
})
.catch((err) => {
console.log('Error creating new menu', err);
return false; return false;
} });
}; };
// delete a menu item // delete a menu item
exports.deleteMenu = function(req, res, menuIndex){ exports.deleteMenu = function(req, res, menuIndex){
let fs = require('fs'); const db = req.app.db;
let path = require('path'); return exports.getMenu(db)
let menuJson = '../config/menu.json'; .then((menu) => {
let menuFile = require(menuJson); // Remove menu item
menu.items.splice(menuIndex, 1);
delete menuFile.items[menuIndex]; return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
.then(() => {
// write file
try{
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
return true; return true;
}catch(e){ });
})
.catch(() => {
return false; return false;
} });
}; };
// updates and existing menu item // updates and existing menu item
exports.updateMenu = function(req, res){ exports.updateMenu = function(req, res){
let fs = require('fs'); const db = req.app.db;
let path = require('path'); return exports.getMenu(db)
let menuJson = '../config/menu.json'; .then((menu) => {
let menuFile = require(menuJson);
// find menu item and update it // find menu item and update it
let menuIndex = _.findIndex(menuFile.items, ['title', req.body.navId]); let menuIndex = _.findIndex(menu.items, ['title', req.body.navId]);
menuFile.items[menuIndex].title = req.body.navMenu; menu.items[menuIndex].title = req.body.navMenu;
menuFile.items[menuIndex].link = req.body.navLink; menu.items[menuIndex].link = req.body.navLink;
return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
// write file .then(() => {
try{
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
return true; return true;
}catch(e){ });
})
.catch(() => {
return false; return false;
});
};
exports.sortMenu = function(menu){
if(menu && menu.items){
menu.items = _.sortBy(menu.items, 'order');
return menu;
} }
return{};
};
// orders the menu
exports.orderMenu = function(req, res){
const db = req.app.db;
return exports.getMenu(db)
.then((menu) => {
// update the order
for(let i = 0; i < req.body.navId.length; i++){
_.find(menu.items, ['title', req.body.navId[i]]).order = i;
}
return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
.then(() => {
return true;
});
})
.catch(() => {
return false;
});
}; };
exports.getEmailTemplate = function(result){ exports.getEmailTemplate = function(result){
@ -360,36 +383,14 @@ exports.sendEmail = function(to, subject, body){
}); });
}; };
// orders the menu
exports.orderMenu = function(req, res){
let fs = require('fs');
let path = require('path');
let menuJson = '../config/menu.json';
let menuFile = require(menuJson);
// update the order
for(let i = 0; i < req.body.navId.length; i++){
_.find(menuFile.items, ['title', req.body.navId[i]]).order = i;
}
// write file
try{
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
return true;
}catch(e){
return false;
}
};
// gets the correct type of index ID // gets the correct type of index ID
exports.getId = function(id){ exports.getId = function(id){
let ObjectID = require('mongodb').ObjectID;
if(id){ if(id){
if(id.length !== 24){ if(id.length !== 24){
return id; return id;
} }
} }
return ObjectID(id); return ObjectId(id);
}; };
// run the DB query // run the DB query
@ -496,7 +497,7 @@ exports.runIndexing = (app) => {
}); });
}; };
exports.testData = (db) => { exports.testData = (db, app) => {
db.products.count({}) db.products.count({})
.then((products) => { .then((products) => {
if(products > 0){ if(products > 0){
@ -505,9 +506,12 @@ exports.testData = (db) => {
console.info(colors.cyan('No products, inserting test data')); console.info(colors.cyan('No products, inserting test data'));
const testdata = fs.readFileSync('./bin/testdata.json', 'utf-8'); const testData = fs.readFileSync('./bin/testdata.json', 'utf-8');
const jsonData = JSON.parse(testData);
return Promise.all([ return Promise.all([
db.products.insertMany(JSON.parse(testdata)) db.products.insertMany(jsonData.products),
db.menu.insertOne(jsonData.menu),
exports.runIndexing(app)
]) ])
.catch((err) => { .catch((err) => {
console.info(colors.red('Error inserting test data. Check `/bin/testdata.json` is correctly formatted.', err)); console.info(colors.red('Error inserting test data. Check `/bin/testdata.json` is correctly formatted.', err));

View File

@ -4,12 +4,12 @@ const colors = require('colors');
const _ = require('lodash'); const _ = require('lodash');
const common = require('./common'); const common = require('./common');
router.get('/payment/:orderId', (req, res, next) => { router.get('/payment/:orderId', async (req, res, next) => {
let db = req.app.db; let db = req.app.db;
let config = common.getConfig(); let config = common.getConfig();
// render the payment complete message // render the payment complete message
db.orders.findOne({_id: common.getId(req.params.orderId)}, (err, result) => { db.orders.findOne({_id: common.getId(req.params.orderId)}, async (err, result) => {
if(err){ if(err){
console.info(err.stack); console.info(err.stack);
} }
@ -23,12 +23,12 @@ router.get('/payment/:orderId', (req, res, next) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
}); });
router.get('/checkout', (req, res, next) => { router.get('/checkout', async (req, res, next) => {
let config = common.getConfig(); let config = common.getConfig();
// if there is no items in the cart then render a failure // if there is no items in the cart then render a failure
@ -50,12 +50,11 @@ router.get('/checkout', (req, res, next) => {
message: common.clearSessionValue(req.session, 'message'), message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter'
menu: common.getMenu()
}); });
}); });
router.get('/pay', (req, res, next) => { router.get('/pay', async (req, res, next) => {
let config = common.getConfig(); let config = common.getConfig();
// if there is no items in the cart then render a failure // if there is no items in the cart then render a failure
@ -78,8 +77,7 @@ router.get('/pay', (req, res, next) => {
message: common.clearSessionValue(req.session, 'message'), message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter'
menu: common.getMenu()
}); });
}); });
@ -113,7 +111,7 @@ router.get('/product/:id', (req, res) => {
} }
// show the view // show the view
common.getImages(result._id, req, res, (images) => { common.getImages(result._id, req, res, async (images) => {
res.render(config.themeViews + 'product', { res.render(config.themeViews + 'product', {
title: result.productTitle, title: result.productTitle,
result: result, result: result,
@ -129,7 +127,7 @@ router.get('/product/:id', (req, res) => {
messageType: common.clearSessionValue(req.session, 'messageType'), messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
} }
@ -240,6 +238,7 @@ router.post('/login_action', (req, res) => {
// search products // search products
router.get('/search/:searchTerm/:pageNum?', (req, res) => { router.get('/search/:searchTerm/:pageNum?', (req, res) => {
let db = req.app.db;
let searchTerm = req.params.searchTerm; let searchTerm = req.params.searchTerm;
let productsIndex = req.app.productsIndex; let productsIndex = req.app.productsIndex;
let config = common.getConfig(); let config = common.getConfig();
@ -256,7 +255,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
} }
// we search on the lunr indexes // we search on the lunr indexes
getData(req, pageNum, {_id: {$in: lunrIdArray}}, (err, results) => { getData(req, pageNum, {_id: {$in: lunrIdArray}}, async (err, results) => {
if(err){ if(err){
console.error(colors.red('Error searching for products', err)); console.error(colors.red('Error searching for products', err));
} }
@ -276,7 +275,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
pageNum: pageNum, pageNum: pageNum,
paginateUrl: 'search', paginateUrl: 'search',
config: config, config: config,
menu: common.getMenu(), menu: common.sortMenu(await common.getMenu(db)),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter' showFooter: 'showFooter'
}); });
@ -285,6 +284,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
// search products // search products
router.get('/category/:cat/:pageNum?', (req, res) => { router.get('/category/:cat/:pageNum?', (req, res) => {
let db = req.app.db;
let searchTerm = req.params.cat; let searchTerm = req.params.cat;
let productsIndex = req.app.productsIndex; let productsIndex = req.app.productsIndex;
let config = common.getConfig(); let config = common.getConfig();
@ -292,18 +292,16 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
let lunrIdArray = []; let lunrIdArray = [];
productsIndex.search(searchTerm).forEach((id) => { productsIndex.search(searchTerm).forEach((id) => {
lunrIdArray.push(common.getId(id.ref)) lunrIdArray.push(common.getId(id.ref));
}); });
let menuLink = _.find(common.getMenu().items, (obj) => { return obj.link === searchTerm; });
let pageNum = 1; let pageNum = 1;
if(req.params.pageNum){ if(req.params.pageNum){
pageNum = req.params.pageNum; pageNum = req.params.pageNum;
} }
// we search on the lunr indexes // we search on the lunr indexes
getData(req, pageNum, {_id: {$in: lunrIdArray}}, (err, results) => { getData(req, pageNum, {_id: {$in: lunrIdArray}}, async (err, results) => {
if(err){ if(err){
console.error(colors.red('Error getting products for category', err)); console.error(colors.red('Error getting products for category', err));
} }
@ -321,10 +319,10 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
productsPerPage: numberProducts, productsPerPage: numberProducts,
totalProductCount: results.totalProducts, totalProductCount: results.totalProducts,
pageNum: pageNum, pageNum: pageNum,
menuLink: menuLink, menuLink: _.find(common.sortMenu(await common.getMenu(db)).items, (obj) => { return obj.link === searchTerm; }),
paginateUrl: 'category', paginateUrl: 'category',
config: config, config: config,
menu: common.getMenu(), menu: common.sortMenu(await common.getMenu(db)),
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter' showFooter: 'showFooter'
}); });
@ -365,10 +363,11 @@ router.get('/sitemap.xml', (req, res, next) => {
}); });
router.get('/page/:pageNum', (req, res, next) => { router.get('/page/:pageNum', (req, res, next) => {
let db = req.app.db;
let config = common.getConfig(); let config = common.getConfig();
let numberProducts = config.productsPerPage ? config.productsPerPage : 6; let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
getData(req, req.params.pageNum, {}, (err, results) => { getData(req, req.params.pageNum, {}, async (err, results) => {
if(err){ if(err){
console.error(colors.red('Error getting products for page', err)); console.error(colors.red('Error getting products for page', err));
} }
@ -388,7 +387,7 @@ router.get('/page/:pageNum', (req, res, next) => {
paginateUrl: 'page', paginateUrl: 'page',
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
}); });
@ -400,7 +399,7 @@ router.get('/:page?', (req, res, next) => {
// if no page is specified, just render page 1 of the cart // if no page is specified, just render page 1 of the cart
if(!req.params.page){ if(!req.params.page){
getData(req, 1, {}, (err, results) => { getData(req, 1, {}, async (err, results) => {
if(err){ if(err){
console.error(colors.red('Error getting products for page', err)); console.error(colors.red('Error getting products for page', err));
} }
@ -420,7 +419,7 @@ router.get('/:page?', (req, res, next) => {
paginateUrl: 'page', paginateUrl: 'page',
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
}); });
}); });
}else{ }else{
@ -429,7 +428,7 @@ router.get('/:page?', (req, res, next) => {
return; return;
} }
// lets look for a page // lets look for a page
db.pages.findOne({pageSlug: req.params.page, pageEnabled: 'true'}, (err, page) => { db.pages.findOne({pageSlug: req.params.page, pageEnabled: 'true'}, async (err, page) => {
if(err){ if(err){
console.error(colors.red('Error getting page', err)); console.error(colors.red('Error getting page', err));
} }
@ -446,7 +445,7 @@ router.get('/:page?', (req, res, next) => {
metaDescription: common.getConfig().cartTitle + ' - ' + page, metaDescription: common.getConfig().cartTitle + ' - ' + page,
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
}); });
}else{ }else{
res.status(404).render('error', { res.status(404).render('error', {
@ -455,9 +454,8 @@ router.get('/:page?', (req, res, next) => {
message: '404 Error - Page not found', message: '404 Error - Page not found',
helpers: req.handlebars.helpers, helpers: req.handlebars.helpers,
showFooter: 'showFooter', showFooter: 'showFooter',
menu: common.getMenu() menu: common.sortMenu(await common.getMenu(db))
} });
);
} }
}); });
} }

View File

@ -10,7 +10,7 @@
<th>Link</th> <th>Link</th>
<th></th> <th></th>
<tbody id="draggable_list"> <tbody id="draggable_list">
{{#each menu}} {{#each menu.items}}
<tr class="drag-row"> <tr class="drag-row">
<form method="post" action="/admin/settings/menu/update"> <form method="post" action="/admin/settings/menu/update">
<input type="hidden" class="navId" name="navId" value="{{title}}"> <input type="hidden" class="navId" name="navId" value="{{title}}">