Moved menu to the DB and started modernizing old code
parent
ceb23e1ce1
commit
ecef3b8224
|
@ -6,7 +6,7 @@
|
||||||
"promise"
|
"promise"
|
||||||
],
|
],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 6
|
"ecmaVersion": 2017
|
||||||
},
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
"$": true
|
"$": true
|
||||||
|
|
20
app.js
20
app.js
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,67 +1,83 @@
|
||||||
[
|
{
|
||||||
{
|
"products":[
|
||||||
"productPermalink": "duckworth-jacket",
|
{
|
||||||
"productTitle": "Duckworth Woolfill Jacket",
|
"productPermalink": "duckworth-jacket",
|
||||||
"productPrice": "188.00",
|
"productTitle": "Duckworth Woolfill Jacket",
|
||||||
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">Inspired by the timeless, functional style of your grandfather's work coat, the Foraker features brass buttons and 4 patch pockets. Crafted in Bristol, Tennessee, our 10oz organic duck canvas is light enough for an early summer morning, but rugged enough to handle your days work.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">100% Organic Duck Canvas.<\/li><\/ul>",
|
"productPrice": "188.00",
|
||||||
"productPublished": "true",
|
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">Inspired by the timeless, functional style of your grandfather's work coat, the Foraker features brass buttons and 4 patch pockets. Crafted in Bristol, Tennessee, our 10oz organic duck canvas is light enough for an early summer morning, but rugged enough to handle your days work.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">100% Organic Duck Canvas.<\/li><\/ul>",
|
||||||
"productAddedDate": {
|
"productPublished": "true",
|
||||||
"$date": "2016-05-01T11:22:49.442Z"
|
"productAddedDate": {
|
||||||
|
"$date": "2016-05-01T11:22:49.442Z"
|
||||||
|
},
|
||||||
|
"productTags": "organic, jacket",
|
||||||
|
"productOptions": "{\"Size\":{\"optName\":\"Size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"S\",\"M\",\"L\",\"XL\"]},\"Colour\":{\"optName\":\"Colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Harvest\",\"Navy\"]}}",
|
||||||
|
"productImage": "/uploads/duckworth-jacket/woolfill-jacket_6c39ae23-c0c8-4821-85f4-4b5d64333c62_grande.jpg"
|
||||||
},
|
},
|
||||||
"productTags": "organic, jacket",
|
{
|
||||||
"productOptions": "{\"Size\":{\"optName\":\"Size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"S\",\"M\",\"L\",\"XL\"]},\"Colour\":{\"optName\":\"Colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Harvest\",\"Navy\"]}}",
|
"productPermalink": "5-panel-cap",
|
||||||
"productImage": "/uploads/duckworth-jacket/woolfill-jacket_6c39ae23-c0c8-4821-85f4-4b5d64333c62_grande.jpg"
|
"productTitle": "5 Panel Camp Cap",
|
||||||
},
|
"productPrice": "48",
|
||||||
{
|
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">A classic 5 panel hat with our United By Blue logo on the front and an adjustable strap to keep fit and secure. Made with recycled polyester and organic cotton mix.<\/p><ul style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">Made in New Jersey<\/li><li style=\"margin-bottom: 0px;\">7oz Eco-Twill fabric: 35% organic cotton, 65% recycled PET (plastic water and soda bottles) <\/li><li style=\"margin-bottom: 0px;\">Embossed leather patch<\/li><\/ul><ul class=\"tabs\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility; color: rgb(28, 29, 29); font-family: Arapey, serif; line-height: 25.008px;\"><\/ul>",
|
||||||
"productPermalink": "5-panel-cap",
|
"productPublished": "true",
|
||||||
"productTitle": "5 Panel Camp Cap",
|
"productAddedDate": {
|
||||||
"productPrice": "48",
|
"$date": "2016-07-10T05:01:15.744Z"
|
||||||
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">A classic 5 panel hat with our United By Blue logo on the front and an adjustable strap to keep fit and secure. Made with recycled polyester and organic cotton mix.<\/p><ul style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">Made in New Jersey<\/li><li style=\"margin-bottom: 0px;\">7oz Eco-Twill fabric: 35% organic cotton, 65% recycled PET (plastic water and soda bottles) <\/li><li style=\"margin-bottom: 0px;\">Embossed leather patch<\/li><\/ul><ul class=\"tabs\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility; color: rgb(28, 29, 29); font-family: Arapey, serif; line-height: 25.008px;\"><\/ul>",
|
},
|
||||||
"productPublished": "true",
|
"productTags": "panel, cap",
|
||||||
"productAddedDate": {
|
"productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Heather green\",\"Burnt orange\",\"Slate grey\",\"Navy blue\"]}}",
|
||||||
"$date": "2016-07-10T05:01:15.744Z"
|
"productImage": "/uploads/5-panel-cap/5-panel-hat_4ee20a27-8d5a-490e-a2fc-1f9c3beb7bf5_grande.jpg"
|
||||||
},
|
},
|
||||||
"productTags": "panel, cap",
|
{
|
||||||
"productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Heather green\",\"Burnt orange\",\"Slate grey\",\"Navy blue\"]}}",
|
"productPermalink": "ranger-boot",
|
||||||
"productImage": "/uploads/5-panel-cap/5-panel-hat_4ee20a27-8d5a-490e-a2fc-1f9c3beb7bf5_grande.jpg"
|
"productTitle": "Red Wing Iron Ranger Boot",
|
||||||
},
|
"productPrice": "310",
|
||||||
{
|
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">The Mesabi Iron Range lies in northern Minnesota, a rugged and remote area known for its iron mines. The local residents who work these mines are proudly known as Iron Rangers, individuals with a sense of adventure and a determined personality. Originally designed to be worn in the iron mines, Iron Ranger work boots had to be as tough as the people who wore them in demanding conditions. Iron Ranger boots are built with a double layer of leaver over the toe to provide an extra measure of safety.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">6 inch, Amber Harness leather with Nitrile Cork sole.<\/li><\/ul>",
|
||||||
"productPermalink": "ranger-boot",
|
"productPublished": "true",
|
||||||
"productTitle": "Red Wing Iron Ranger Boot",
|
"productAddedDate": {
|
||||||
"productPrice": "310",
|
"$date": "2016-07-10T05:29:04.941Z"
|
||||||
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">The Mesabi Iron Range lies in northern Minnesota, a rugged and remote area known for its iron mines. The local residents who work these mines are proudly known as Iron Rangers, individuals with a sense of adventure and a determined personality. Originally designed to be worn in the iron mines, Iron Ranger work boots had to be as tough as the people who wore them in demanding conditions. Iron Ranger boots are built with a double layer of leaver over the toe to provide an extra measure of safety.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">6 inch, Amber Harness leather with Nitrile Cork sole.<\/li><\/ul>",
|
},
|
||||||
"productPublished": "true",
|
"productTags": "ranger, boot, leather",
|
||||||
"productAddedDate": {
|
"productImage": "/uploads/ranger-boot/boot_grande.jpg",
|
||||||
"$date": "2016-07-10T05:29:04.941Z"
|
"productOptions": "{\"size\":{\"optName\":\"size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"7.5\",\"8\",\"8.5\",\"9\",\"9.5\",\"10\",\"10.5\",\"11\"]}}"
|
||||||
},
|
},
|
||||||
"productTags": "ranger, boot, leather",
|
{
|
||||||
"productImage": "/uploads/ranger-boot/boot_grande.jpg",
|
"productPermalink": "whitney-pullover",
|
||||||
"productOptions": "{\"size\":{\"optName\":\"size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"7.5\",\"8\",\"8.5\",\"9\",\"9.5\",\"10\",\"10.5\",\"11\"]}}"
|
"productTitle": "Whitney pullover",
|
||||||
},
|
"productPrice": "138",
|
||||||
{
|
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">Buttons are fussy. Sometimes you just want to roll out of bed, put on the pull over and get to the days work. Julie is 5'8\" and wearing a size small.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">100% Wool, Heavy 4 gauge thickness<\/li><li style=\"margin-bottom: 0px;\">Handmade in Nepal.<\/li><\/ul>",
|
||||||
"productPermalink": "whitney-pullover",
|
"productPublished": "true",
|
||||||
"productTitle": "Whitney pullover",
|
"productAddedDate": {
|
||||||
"productPrice": "138",
|
"$date": "2016-05-01T11:23:08.374Z"
|
||||||
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">Buttons are fussy. Sometimes you just want to roll out of bed, put on the pull over and get to the days work. Julie is 5'8\" and wearing a size small.<\/p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">100% Wool, Heavy 4 gauge thickness<\/li><li style=\"margin-bottom: 0px;\">Handmade in Nepal.<\/li><\/ul>",
|
},
|
||||||
"productPublished": "true",
|
"productImage": "/uploads/whitney-pullover/WhitneyPullover_Full_58e7b8d6-b939-4701-9e1d-9d853dff60ed_grande.jpeg",
|
||||||
"productAddedDate": {
|
"productTags": "whitney, pullover",
|
||||||
"$date": "2016-05-01T11:23:08.374Z"
|
"productOptions": "{\"size\":{\"optName\":\"size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"S\",\"M\",\"L\",\"XL\"]}}"
|
||||||
},
|
},
|
||||||
"productImage": "/uploads/whitney-pullover/WhitneyPullover_Full_58e7b8d6-b939-4701-9e1d-9d853dff60ed_grande.jpeg",
|
{
|
||||||
"productTags": "whitney, pullover",
|
"productPermalink": "scout-backpack",
|
||||||
"productOptions": "{\"size\":{\"optName\":\"size\",\"optLabel\":\"Select size\",\"optType\":\"select\",\"optOptions\":[\"S\",\"M\",\"L\",\"XL\"]}}"
|
"productTitle": "Scout Backpack",
|
||||||
},
|
"productPrice": "128.00",
|
||||||
{
|
"productDescription": "<p><span style=\"line-height: 1.42857;\">This durable backpack is ready for any adventure, large or small. Features adjustable and padded shoulder pads for comfort. Designed with a storm flap and a secured by two snap-button closure. Made with a waxed downpour proof exterior canvas and a soft cotton interior lining. Finished with brass hardware and genuine leather trimmings.<\/span><\/p><ul><li><span style=\"line-height: 1.42857;\">100% organic waxed 18 oz canvas<\/span><\/li><li><span style=\"line-height: 1.42857;\">Full grain genuine leather accents<\/span><\/li><li>Adjustable shoulder straps<\/li><li>Lifetime&nbsp;Guarantee<\/li><\/ul>",
|
||||||
"productPermalink": "scout-backpack",
|
"productPublished": "true",
|
||||||
"productTitle": "Scout Backpack",
|
"productTags": "backpack, organic",
|
||||||
"productPrice": "128.00",
|
"productAddedDate": {
|
||||||
"productDescription": "<p><span style=\"line-height: 1.42857;\">This durable backpack is ready for any adventure, large or small. Features adjustable and padded shoulder pads for comfort. Designed with a storm flap and a secured by two snap-button closure. Made with a waxed downpour proof exterior canvas and a soft cotton interior lining. Finished with brass hardware and genuine leather trimmings.<\/span><\/p><ul><li><span style=\"line-height: 1.42857;\">100% organic waxed 18 oz canvas<\/span><\/li><li><span style=\"line-height: 1.42857;\">Full grain genuine leather accents<\/span><\/li><li>Adjustable shoulder straps<\/li><li>Lifetime&nbsp;Guarantee<\/li><\/ul>",
|
"$date": "2016-07-10T05:46:26.974Z"
|
||||||
"productPublished": "true",
|
},
|
||||||
"productTags": "backpack, organic",
|
"productImage": "/uploads/scout-backpack/scout-backpack_a035275d-8975-4a05-8456-5e1ec35f020f_grande.jpg",
|
||||||
"productAddedDate": {
|
"productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Navy\",\"Moss\",\"Nutmeg\",\"Khaki\"]}}"
|
||||||
"$date": "2016-07-10T05:46:26.974Z"
|
}
|
||||||
},
|
],
|
||||||
"productImage": "/uploads/scout-backpack/scout-backpack_a035275d-8975-4a05-8456-5e1ec35f020f_grande.jpg",
|
"menu": {
|
||||||
"productOptions": "{\"colour\":{\"optName\":\"colour\",\"optLabel\":\"Select colour\",\"optType\":\"select\",\"optOptions\":[\"Navy\",\"Moss\",\"Nutmeg\",\"Khaki\"]}}"
|
"items": [
|
||||||
|
{
|
||||||
|
"title" : "Backpacks",
|
||||||
|
"link" : "backpack",
|
||||||
|
"order" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title" : "Boots",
|
||||||
|
"link" : "boots",
|
||||||
|
"order" : 1
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
}
|
|
@ -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
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
164
routes/common.js
164
routes/common.js
|
@ -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 = {
|
||||||
|
title: req.body.navMenu,
|
||||||
|
link: req.body.navLink,
|
||||||
|
order: Object.keys(menu.items).length + 1
|
||||||
|
};
|
||||||
|
|
||||||
let newNav = {
|
menu.items.push(newNav);
|
||||||
title: req.body.navMenu,
|
return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
|
||||||
link: req.body.navLink,
|
.then(() => {
|
||||||
order: Object.keys(menuFile.items).length + 1
|
return true;
|
||||||
};
|
});
|
||||||
|
})
|
||||||
// add new menu item
|
.catch((err) => {
|
||||||
menuFile.items.push(newNav);
|
console.log('Error creating new menu', err);
|
||||||
|
|
||||||
// write file
|
|
||||||
try{
|
|
||||||
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
|
|
||||||
return true;
|
|
||||||
}catch(e){
|
|
||||||
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
|
return true;
|
||||||
try{
|
});
|
||||||
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
|
})
|
||||||
return true;
|
.catch(() => {
|
||||||
}catch(e){
|
|
||||||
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
|
||||||
|
let menuIndex = _.findIndex(menu.items, ['title', req.body.navId]);
|
||||||
// find menu item and update it
|
menu.items[menuIndex].title = req.body.navMenu;
|
||||||
let menuIndex = _.findIndex(menuFile.items, ['title', req.body.navId]);
|
menu.items[menuIndex].link = req.body.navLink;
|
||||||
menuFile.items[menuIndex].title = req.body.navMenu;
|
return db.menu.updateOne({}, {$set: {items: menu.items}}, {upsert: true})
|
||||||
menuFile.items[menuIndex].link = req.body.navLink;
|
.then(() => {
|
||||||
|
return true;
|
||||||
// write file
|
});
|
||||||
try{
|
})
|
||||||
fs.writeFileSync(path.join(__dirname, '../config/menu.json'), JSON.stringify(menuFile));
|
.catch(() => {
|
||||||
return true;
|
|
||||||
}catch(e){
|
|
||||||
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));
|
||||||
|
|
|
@ -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))
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}}">
|
||||||
|
|
Loading…
Reference in New Issue