From 3c39b5e5c54bbb33f1090ff1ed7be56f80e9b2c9 Mon Sep 17 00:00:00 2001 From: Mark Moffat Date: Sun, 14 Jan 2018 22:11:22 +0100 Subject: [PATCH] Cleaning up code --- README.md | 2 + app.js | 2 +- routes/common.js | 97 +++++++++++++++++++++++----------------- routes/index.js | 112 +++++++++++++++++++++-------------------------- 4 files changed, 108 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index 3cebb90..663694b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ Keeping expressCart running after closing the terminal can be done in a few ways 4. Save the PM2 config: `pm2 save` 5. To start/stop: `pm2 start expressCart` / `pm2 stop expressCart` +> Note: Node.js version 7.x or greater is needed. + ## Admin Visit: [http://127.0.0.1:1111/admin](http://127.0.0.1:1111/admin) diff --git a/app.js b/app.js index 1313e35..21337d8 100644 --- a/app.js +++ b/app.js @@ -184,7 +184,7 @@ handlebars = handlebars.create({ } }); -// var session store +// session store let store = new MongoStore({ uri: config.databaseConnectionString, collection: 'sessions' diff --git a/routes/common.js b/routes/common.js index d286abc..35d3d40 100644 --- a/routes/common.js +++ b/routes/common.js @@ -2,12 +2,17 @@ const _ = require('lodash'); const uglifycss = require('uglifycss'); const colors = require('colors'); const lunr = require('lunr'); +const cheerio = require('cheerio'); const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); +const async = require('async'); +const nodemailer = require('nodemailer'); const escape = require('html-entities').AllHtmlEntities; let ObjectId = require('mongodb').ObjectID; // common functions -exports.checkLogin = function(req, res, next){ +exports.checkLogin = (req, res, next) => { // if not protecting we check for public pages and don't checkLogin if(req.session.needsSetup === true){ res.redirect('/setup'); @@ -21,7 +26,7 @@ exports.checkLogin = function(req, res, next){ res.redirect('/login'); }; -exports.showCartCloseBtn = function(page){ +exports.showCartCloseBtn = (page) => { let showCartCloseButton = true; if(page === 'checkout' || page === 'pay'){ showCartCloseButton = false; @@ -31,9 +36,9 @@ exports.showCartCloseBtn = function(page){ }; // adds products to sitemap.xml -exports.addSitemapProducts = function(req, res, cb){ +exports.addSitemapProducts = (req, res, cb) => { let db = req.app.db; - let async = require('async'); + let config = exports.getConfig(); let hostname = config.baseUrl; @@ -59,11 +64,11 @@ exports.addSitemapProducts = function(req, res, cb){ }); }; -exports.restrict = function(req, res, next){ +exports.restrict = (req, res, next) => { exports.checkLogin(req, res, next); }; -exports.clearSessionValue = function(session, sessionVar){ +exports.clearSessionValue = (session, sessionVar) => { let temp; if(session){ temp = session[sessionVar]; @@ -72,7 +77,7 @@ exports.clearSessionValue = function(session, sessionVar){ return temp; }; -exports.updateTotalCartAmount = function(req, res){ +exports.updateTotalCartAmount = (req, res) => { let config = exports.getConfig(); req.session.totalCartAmount = 0; @@ -90,8 +95,7 @@ exports.updateTotalCartAmount = function(req, res){ } }; -exports.checkDirectorySync = function (directory){ - let fs = require('fs'); +exports.checkDirectorySync = (directory) => { try{ fs.statSync(directory); }catch(e){ @@ -99,16 +103,12 @@ exports.checkDirectorySync = function (directory){ } }; -exports.getThemes = function (){ - let fs = require('fs'); - let path = require('path'); +exports.getThemes = () => { return fs.readdirSync(path.join('public', 'themes')).filter(file => fs.statSync(path.join(path.join('public', 'themes'), file)).isDirectory()); }; -exports.getImages = function (dir, req, res, callback){ +exports.getImages = (dir, req, res, callback) => { let db = req.app.db; - let glob = require('glob'); - let fs = require('fs'); db.products.findOne({_id: exports.getId(dir)}, (err, product) => { if(err){ @@ -144,10 +144,7 @@ exports.getImages = function (dir, req, res, callback){ }); }; -exports.getConfig = function(){ - let fs = require('fs'); - let path = require('path'); - +exports.getConfig = () => { let config = JSON.parse(fs.readFileSync(path.join(__dirname, '../config', 'settings.json'), 'utf8')); config.customCss = typeof config.customCss !== 'undefined' ? escape.decode(config.customCss) : null; config.footerHtml = typeof config.footerHtml !== 'undefined' ? escape.decode(config.footerHtml) : null; @@ -171,9 +168,7 @@ exports.getConfig = function(){ return config; }; -exports.getPaymentConfig = function(){ - let fs = require('fs'); - let path = require('path'); +exports.getPaymentConfig = () => { let siteConfig = this.getConfig(); let config = []; @@ -184,9 +179,7 @@ exports.getPaymentConfig = function(){ return config; }; -exports.updateConfig = function(fields){ - let fs = require('fs'); - let path = require('path'); +exports.updateConfig = (fields) => { let settingsFile = JSON.parse(fs.readFileSync(path.join(__dirname, '../config/settings.json'), 'utf8')); _.forEach(fields, (value, key) => { @@ -230,12 +223,12 @@ exports.updateConfig = function(fields){ } }; -exports.getMenu = function(db){ +exports.getMenu = (db) => { return db.menu.findOne({}); }; // creates a new menu item -exports.newMenu = function(req, res){ +exports.newMenu = (req, res) => { const db = req.app.db; return exports.getMenu(db) .then((menu) => { @@ -263,7 +256,7 @@ exports.newMenu = function(req, res){ }; // delete a menu item -exports.deleteMenu = function(req, res, menuIndex){ +exports.deleteMenu = (req, res, menuIndex) => { const db = req.app.db; return exports.getMenu(db) .then((menu) => { @@ -280,7 +273,7 @@ exports.deleteMenu = function(req, res, menuIndex){ }; // updates and existing menu item -exports.updateMenu = function(req, res){ +exports.updateMenu = (req, res) => { const db = req.app.db; return exports.getMenu(db) .then((menu) => { @@ -298,7 +291,7 @@ exports.updateMenu = function(req, res){ }); }; -exports.sortMenu = function(menu){ +exports.sortMenu = (menu) => { if(menu && menu.items){ menu.items = _.sortBy(menu.items, 'order'); return menu; @@ -307,7 +300,7 @@ exports.sortMenu = function(menu){ }; // orders the menu -exports.orderMenu = function(req, res){ +exports.orderMenu = (req, res) => { const db = req.app.db; return exports.getMenu(db) .then((menu) => { @@ -325,11 +318,8 @@ exports.orderMenu = function(req, res){ }); }; -exports.getEmailTemplate = function(result){ - let cheerio = require('cheerio'); +exports.getEmailTemplate = (result) => { let config = this.getConfig(); - let fs = require('fs'); - let path = require('path'); let template = fs.readFileSync(path.join(__dirname, '../public/email_template.html'), 'utf8'); @@ -347,9 +337,8 @@ exports.getEmailTemplate = function(result){ return $.html(); }; -exports.sendEmail = function(to, subject, body){ +exports.sendEmail = (to, subject, body) => { let config = this.getConfig(); - let nodemailer = require('nodemailer'); let emailSettings = { host: config.emailHost, @@ -384,7 +373,7 @@ exports.sendEmail = function(to, subject, body){ }; // gets the correct type of index ID -exports.getId = function(id){ +exports.getId = (id) => { if(id){ if(id.length !== 24){ return id; @@ -394,7 +383,7 @@ exports.getId = function(id){ }; // run the DB query -exports.dbQuery = function(db, query, sort, limit, callback){ +exports.dbQuery = (db, query, sort, limit, callback) => { if(sort && limit){ db.find(query).sort(sort).limit(parseInt(limit)).toArray((err, results) => { if(err){ @@ -412,6 +401,32 @@ exports.dbQuery = function(db, query, sort, limit, callback){ } }; +exports.getData = async (req, page, query) => { + let db = req.app.db; + let config = exports.getConfig(); + let numberProducts = config.productsPerPage ? config.productsPerPage : 6; + + let skip = 0; + if(page > 1){ + skip = (page - 1) * numberProducts; + } + + query['productPublished'] = 'true'; + + // Run our queries + return Promise.all([ + db.products.find(query).skip(skip).limit(parseInt(numberProducts)).toArray(), + db.products.count(query) + ]) + .then((result) => { + const returnData = {data: result[0], totalProducts: result[1]}; + return returnData; + }) + .catch((err) => { + throw new Error('Error retrieving products'); + }); +}; + exports.indexProducts = (app) => { // index all products in lunr on startup return new Promise((resolve, reject) => { @@ -422,7 +437,7 @@ exports.indexProducts = (app) => { } // setup lunr indexing - const productsIndex = lunr(function (){ + const productsIndex = lunr(function(){ this.field('productTitle', {boost: 10}); this.field('productTags', {boost: 5}); this.field('productDescription'); @@ -458,7 +473,7 @@ exports.indexOrders = (app, cb) => { } // setup lunr indexing - const ordersIndex = lunr(function (){ + const ordersIndex = lunr(function(){ this.field('orderEmail', {boost: 10}); this.field('orderLastname', {boost: 5}); this.field('orderPostcode'); diff --git a/routes/index.js b/routes/index.js index 2824668..9abbea2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -13,7 +13,7 @@ router.get('/payment/:orderId', async (req, res, next) => { if(err){ console.info(err.stack); } - res.render(config.themeViews + 'payment_complete', { + res.render(`${config.themeViews}payment_complete`, { title: 'Payment complete', config: common.getConfig(), session: req.session, @@ -40,7 +40,7 @@ router.get('/checkout', async (req, res, next) => { } // render the checkout - res.render(config.themeViews + 'checkout', { + res.render(`${config.themeViews}checkout`, { title: 'Checkout', config: common.getConfig(), session: req.session, @@ -66,7 +66,7 @@ router.get('/pay', async (req, res, next) => { } // render the payment page - res.render(config.themeViews + 'pay', { + res.render(`${config.themeViews}pay`, { title: 'Pay', config: common.getConfig(), paymentConfig: common.getPaymentConfig(), @@ -112,7 +112,7 @@ router.get('/product/:id', (req, res) => { // show the view common.getImages(result._id, req, res, async (images) => { - res.render(config.themeViews + 'product', { + res.render(`${config.themeViews}product`, { title: result.productTitle, result: result, productOptions: productOptions, @@ -254,13 +254,12 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => { pageNum = req.params.pageNum; } - // we search on the lunr indexes - getData(req, pageNum, {_id: {$in: lunrIdArray}}, async (err, results) => { - if(err){ - console.error(colors.red('Error searching for products', err)); - } - - res.render(config.themeViews + 'index', { + Promise.all([ + common.getData(req, pageNum, {_id: {$in: lunrIdArray}}), + common.getMenu(db) + ]) + .then(([results, menu]) => { + res.render(`${config.themeViews}index`, { title: 'Results', results: results.data, filtered: true, @@ -275,10 +274,13 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => { pageNum: pageNum, paginateUrl: 'search', config: config, - menu: common.sortMenu(await common.getMenu(db)), + menu: common.sortMenu(menu), helpers: req.handlebars.helpers, showFooter: 'showFooter' }); + }) + .catch((err) => { + console.error(colors.red('Error searching for products', err)); }); }); @@ -300,13 +302,14 @@ router.get('/category/:cat/:pageNum?', (req, res) => { pageNum = req.params.pageNum; } - // we search on the lunr indexes - getData(req, pageNum, {_id: {$in: lunrIdArray}}, async (err, results) => { - if(err){ - console.error(colors.red('Error getting products for category', err)); - } + Promise.all([ + common.getData(req, pageNum, {_id: {$in: lunrIdArray}}), + common.getMenu(db) + ]) + .then(([results, menu]) => { + const sortedMenu = common.sortMenu(menu); - res.render(config.themeViews + 'index', { + res.render(`${config.themeViews}index`, { title: 'Category', results: results.data, filtered: true, @@ -319,13 +322,16 @@ router.get('/category/:cat/:pageNum?', (req, res) => { productsPerPage: numberProducts, totalProductCount: results.totalProducts, pageNum: pageNum, - menuLink: _.find(common.sortMenu(await common.getMenu(db)).items, (obj) => { return obj.link === searchTerm; }), + menuLink: _.find(sortedMenu.items, (obj) => { return obj.link === searchTerm; }), paginateUrl: 'category', config: config, - menu: common.sortMenu(await common.getMenu(db)), + menu: sortedMenu, helpers: req.handlebars.helpers, showFooter: 'showFooter' }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for category', err)); }); }); @@ -367,12 +373,12 @@ router.get('/page/:pageNum', (req, res, next) => { let config = common.getConfig(); let numberProducts = config.productsPerPage ? config.productsPerPage : 6; - getData(req, req.params.pageNum, {}, async (err, results) => { - if(err){ - console.error(colors.red('Error getting products for page', err)); - } - - res.render(config.themeViews + 'index', { + Promise.all([ + common.getData(req, req.params.pageNum), + common.getMenu(db) + ]) + .then(([results, menu]) => { + res.render(`${config.themeViews}index`, { title: 'Shop', results: results.data, session: req.session, @@ -387,11 +393,15 @@ router.get('/page/:pageNum', (req, res, next) => { paginateUrl: 'page', helpers: req.handlebars.helpers, showFooter: 'showFooter', - menu: common.sortMenu(await common.getMenu(db)) + menu: common.sortMenu(menu) }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for page', err)); }); }); +// The main entry point of the shop router.get('/:page?', (req, res, next) => { let db = req.app.db; let config = common.getConfig(); @@ -399,13 +409,13 @@ router.get('/:page?', (req, res, next) => { // if no page is specified, just render page 1 of the cart if(!req.params.page){ - getData(req, 1, {}, async (err, results) => { - if(err){ - console.error(colors.red('Error getting products for page', err)); - } - - res.render(config.themeViews + 'index', { - title: 'Shop', + Promise.all([ + common.getData(req, 1, {}), + common.getMenu(db) + ]) + .then(([results, menu]) => { + res.render(`${config.themeViews}index`, { + title: `${config.cartTitle} - Shop`, theme: config.theme, results: results.data, session: req.session, @@ -419,8 +429,11 @@ router.get('/:page?', (req, res, next) => { paginateUrl: 'page', helpers: req.handlebars.helpers, showFooter: 'showFooter', - menu: common.sortMenu(await common.getMenu(db)) + menu: common.sortMenu(menu) }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for page', err)); }); }else{ if(req.params.page === 'admin'){ @@ -434,7 +447,7 @@ router.get('/:page?', (req, res, next) => { } // if we have a page lets render it, else throw 404 if(page){ - res.render(config.themeViews + 'page', { + res.render(`${config.themeViews}page`, { title: page.pageName, page: page, session: req.session, @@ -461,31 +474,4 @@ router.get('/:page?', (req, res, next) => { } }); -const getData = function (req, page, query, cb){ - let db = req.app.db; - let config = common.getConfig(); - let numberProducts = config.productsPerPage ? config.productsPerPage : 6; - - let skip = 0; - if(page > 1){ - skip = (page - 1) * numberProducts; - } - - query['productPublished'] = 'true'; - - db.products.count(query, (err, totalProducts) => { - if(err){ - console.error(colors.red('Error getting total product count', err)); - } - - db.products.find(query).skip(skip).limit(parseInt(numberProducts)).toArray((err, results) => { - if(err){ - cb(new Error('Error retrieving products'), null); - }else{ - cb(null, {data: results, totalProducts: totalProducts}); - } - }); - }); -}; - module.exports = router;