2018-02-05 23:20:44 +10:00
|
|
|
const express = require('express');
|
2018-02-06 04:20:30 +10:00
|
|
|
const common = require('../lib/common');
|
2019-06-15 14:46:08 +10:00
|
|
|
const { restrict, checkAccess } = require('../lib/auth');
|
2018-02-05 23:20:44 +10:00
|
|
|
const colors = require('colors');
|
|
|
|
const rimraf = require('rimraf');
|
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
|
|
|
const router = express.Router();
|
|
|
|
|
2019-06-15 14:46:08 +10:00
|
|
|
router.get('/admin/products', restrict, (req, res, next) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
// get the top results
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.find({}).sort({ 'productAddedDate': -1 }).limit(10).toArray((err, topResults) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
res.render('products', {
|
|
|
|
title: 'Cart',
|
|
|
|
top_results: topResults,
|
|
|
|
session: req.session,
|
|
|
|
admin: true,
|
2018-02-23 03:41:24 +10:00
|
|
|
config: req.app.config,
|
2018-02-05 23:20:44 +10:00
|
|
|
message: common.clearSessionValue(req.session, 'message'),
|
|
|
|
messageType: common.clearSessionValue(req.session, 'messageType'),
|
|
|
|
helpers: req.handlebars.helpers
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-02-06 04:33:40 +10:00
|
|
|
router.get('/admin/products/filter/:search', (req, res, next) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
let searchTerm = req.params.search;
|
|
|
|
let productsIndex = req.app.productsIndex;
|
|
|
|
|
|
|
|
let lunrIdArray = [];
|
|
|
|
productsIndex.search(searchTerm).forEach((id) => {
|
|
|
|
lunrIdArray.push(common.getId(id.ref));
|
|
|
|
});
|
|
|
|
|
|
|
|
// we search on the lunr indexes
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.find({ _id: { $in: lunrIdArray } }).toArray((err, results) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.error(colors.red('Error searching', err));
|
|
|
|
}
|
|
|
|
res.render('products', {
|
|
|
|
title: 'Results',
|
|
|
|
results: results,
|
|
|
|
admin: true,
|
2018-02-23 03:41:24 +10:00
|
|
|
config: req.app.config,
|
2018-02-05 23:20:44 +10:00
|
|
|
session: req.session,
|
|
|
|
searchTerm: searchTerm,
|
|
|
|
message: common.clearSessionValue(req.session, 'message'),
|
|
|
|
messageType: common.clearSessionValue(req.session, 'messageType'),
|
|
|
|
helpers: req.handlebars.helpers
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// insert form
|
2019-06-15 14:46:08 +10:00
|
|
|
router.get('/admin/product/new', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
res.render('product_new', {
|
|
|
|
title: 'New product',
|
|
|
|
session: req.session,
|
|
|
|
productTitle: common.clearSessionValue(req.session, 'productTitle'),
|
|
|
|
productDescription: common.clearSessionValue(req.session, 'productDescription'),
|
|
|
|
productPrice: common.clearSessionValue(req.session, 'productPrice'),
|
|
|
|
productPermalink: common.clearSessionValue(req.session, 'productPermalink'),
|
|
|
|
message: common.clearSessionValue(req.session, 'message'),
|
|
|
|
messageType: common.clearSessionValue(req.session, 'messageType'),
|
|
|
|
editor: true,
|
|
|
|
admin: true,
|
|
|
|
helpers: req.handlebars.helpers,
|
2018-02-23 03:41:24 +10:00
|
|
|
config: req.app.config
|
2018-02-05 23:20:44 +10:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// insert new product form action
|
2019-06-15 14:46:08 +10:00
|
|
|
router.post('/admin/product/insert', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
|
|
|
let doc = {
|
|
|
|
productPermalink: req.body.frmProductPermalink,
|
2018-12-11 23:35:35 +10:00
|
|
|
productTitle: common.cleanHtml(req.body.frmProductTitle),
|
2018-02-05 23:20:44 +10:00
|
|
|
productPrice: req.body.frmProductPrice,
|
2018-12-11 23:31:56 +10:00
|
|
|
productDescription: common.cleanHtml(req.body.frmProductDescription),
|
2018-02-05 23:20:44 +10:00
|
|
|
productPublished: req.body.frmProductPublished,
|
|
|
|
productTags: req.body.frmProductTags,
|
2018-12-11 23:31:56 +10:00
|
|
|
productOptions: common.cleanHtml(req.body.productOptJson),
|
2018-10-05 21:54:42 +10:00
|
|
|
productComment: common.checkboxBool(req.body.frmProductComment),
|
2019-02-09 20:46:41 +10:00
|
|
|
productAddedDate: new Date(),
|
|
|
|
productStock: req.body.frmProductStock ? parseInt(req.body.frmProductStock) : null
|
2018-02-05 23:20:44 +10:00
|
|
|
};
|
|
|
|
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.count({ 'productPermalink': req.body.frmProductPermalink }, (err, product) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
if(product > 0 && req.body.frmProductPermalink !== ''){
|
|
|
|
// permalink exits
|
|
|
|
req.session.message = 'Permalink already exists. Pick a new one.';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
|
|
|
|
// keep the current stuff
|
|
|
|
req.session.productTitle = req.body.frmProductTitle;
|
|
|
|
req.session.productDescription = req.body.frmProductDescription;
|
|
|
|
req.session.productPrice = req.body.frmProductPrice;
|
|
|
|
req.session.productPermalink = req.body.frmProductPermalink;
|
|
|
|
req.session.productPermalink = req.body.productOptJson;
|
2018-10-05 21:54:42 +10:00
|
|
|
req.session.productComment = common.checkboxBool(req.body.frmProductComment);
|
2018-02-05 23:20:44 +10:00
|
|
|
req.session.productTags = req.body.frmProductTags;
|
2019-02-09 20:46:41 +10:00
|
|
|
req.session.productStock = req.body.frmProductStock ? parseInt(req.body.frmProductStock) : null;
|
2018-02-05 23:20:44 +10:00
|
|
|
|
|
|
|
// redirect to insert
|
|
|
|
res.redirect('/admin/insert');
|
|
|
|
}else{
|
|
|
|
db.products.insert(doc, (err, newDoc) => {
|
|
|
|
if(err){
|
|
|
|
console.log(colors.red('Error inserting document: ' + err));
|
|
|
|
|
|
|
|
// keep the current stuff
|
|
|
|
req.session.productTitle = req.body.frmProductTitle;
|
|
|
|
req.session.productDescription = req.body.frmProductDescription;
|
|
|
|
req.session.productPrice = req.body.frmProductPrice;
|
|
|
|
req.session.productPermalink = req.body.frmProductPermalink;
|
|
|
|
req.session.productPermalink = req.body.productOptJson;
|
2018-10-05 21:54:42 +10:00
|
|
|
req.session.productComment = common.checkboxBool(req.body.frmProductComment);
|
2018-02-05 23:20:44 +10:00
|
|
|
req.session.productTags = req.body.frmProductTags;
|
2019-02-09 20:46:41 +10:00
|
|
|
req.session.productStock = req.body.frmProductStock ? parseInt(req.body.frmProductStock) : null;
|
2018-02-05 23:20:44 +10:00
|
|
|
|
|
|
|
req.session.message = 'Error: Inserting product';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
|
|
|
|
// redirect to insert
|
|
|
|
res.redirect('/admin/product/new');
|
|
|
|
}else{
|
|
|
|
// get the new ID
|
|
|
|
let newId = newDoc.insertedIds[0];
|
|
|
|
|
|
|
|
// add to lunr index
|
|
|
|
common.indexProducts(req.app)
|
|
|
|
.then(() => {
|
|
|
|
req.session.message = 'New product successfully created';
|
|
|
|
req.session.messageType = 'success';
|
|
|
|
|
|
|
|
// redirect to new doc
|
|
|
|
res.redirect('/admin/product/edit/' + newId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// render the editor
|
2019-06-15 14:46:08 +10:00
|
|
|
router.get('/admin/product/edit/:id', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
|
|
|
common.getImages(req.params.id, req, res, (images) => {
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.findOne({ _id: common.getId(req.params.id) }, (err, result) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
let options = {};
|
|
|
|
if(result.productOptions){
|
|
|
|
options = JSON.parse(result.productOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
res.render('product_edit', {
|
|
|
|
title: 'Edit product',
|
|
|
|
result: result,
|
|
|
|
images: images,
|
|
|
|
options: options,
|
|
|
|
admin: true,
|
|
|
|
session: req.session,
|
|
|
|
message: common.clearSessionValue(req.session, 'message'),
|
|
|
|
messageType: common.clearSessionValue(req.session, 'messageType'),
|
2018-02-23 03:41:24 +10:00
|
|
|
config: req.app.config,
|
2018-02-05 23:20:44 +10:00
|
|
|
editor: true,
|
|
|
|
helpers: req.handlebars.helpers
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Update an existing product form action
|
2019-06-15 14:46:08 +10:00
|
|
|
router.post('/admin/product/update', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.findOne({ _id: common.getId(req.body.frmProductId) }, (err, product) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
req.session.message = 'Failed updating product.';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
res.redirect('/admin/product/edit/' + req.body.frmProductId);
|
|
|
|
return;
|
|
|
|
}
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.count({ 'productPermalink': req.body.frmProductPermalink, _id: { $ne: common.getId(product._id) } }, (err, count) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
req.session.message = 'Failed updating product.';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
res.redirect('/admin/product/edit/' + req.body.frmProductId);
|
|
|
|
return;
|
|
|
|
}
|
2018-12-11 23:31:56 +10:00
|
|
|
|
2018-02-05 23:20:44 +10:00
|
|
|
if(count > 0 && req.body.frmProductPermalink !== ''){
|
|
|
|
// permalink exits
|
|
|
|
req.session.message = 'Permalink already exists. Pick a new one.';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
|
|
|
|
// keep the current stuff
|
|
|
|
req.session.productTitle = req.body.frmProductTitle;
|
|
|
|
req.session.productDescription = req.body.frmProductDescription;
|
|
|
|
req.session.productPrice = req.body.frmProductPrice;
|
|
|
|
req.session.productPermalink = req.body.frmProductPermalink;
|
|
|
|
req.session.productTags = req.body.frmProductTags;
|
|
|
|
req.session.productOptions = req.body.productOptJson;
|
2018-10-05 21:54:42 +10:00
|
|
|
req.session.productComment = common.checkboxBool(req.body.frmProductComment);
|
2019-02-09 14:07:02 +10:00
|
|
|
req.session.productStock = req.body.frmProductStock ? req.body.frmProductStock : null;
|
2018-02-05 23:20:44 +10:00
|
|
|
|
|
|
|
// redirect to insert
|
|
|
|
res.redirect('/admin/product/edit/' + req.body.frmProductId);
|
|
|
|
}else{
|
|
|
|
common.getImages(req.body.frmProductId, req, res, (images) => {
|
|
|
|
let productDoc = {
|
2018-12-11 23:35:35 +10:00
|
|
|
productTitle: common.cleanHtml(req.body.frmProductTitle),
|
2018-12-11 23:31:56 +10:00
|
|
|
productDescription: common.cleanHtml(req.body.frmProductDescription),
|
2018-02-05 23:20:44 +10:00
|
|
|
productPublished: req.body.frmProductPublished,
|
|
|
|
productPrice: req.body.frmProductPrice,
|
|
|
|
productPermalink: req.body.frmProductPermalink,
|
2018-12-11 23:31:56 +10:00
|
|
|
productTags: common.cleanHtml(req.body.frmProductTags),
|
|
|
|
productOptions: common.cleanHtml(req.body.productOptJson),
|
2019-02-09 14:07:02 +10:00
|
|
|
productComment: common.checkboxBool(req.body.frmProductComment),
|
|
|
|
productStock: req.body.frmProductStock ? parseInt(req.body.frmProductStock) : null
|
2018-02-05 23:20:44 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
// if no featured image
|
|
|
|
if(!product.productImage){
|
|
|
|
if(images.length > 0){
|
|
|
|
productDoc['productImage'] = images[0].path;
|
|
|
|
}else{
|
|
|
|
productDoc['productImage'] = '/uploads/placeholder.png';
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
productDoc['productImage'] = product.productImage;
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.update({ _id: common.getId(req.body.frmProductId) }, { $set: productDoc }, {}, (err, numReplaced) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.error(colors.red('Failed to save product: ' + err));
|
|
|
|
req.session.message = 'Failed to save. Please try again';
|
|
|
|
req.session.messageType = 'danger';
|
|
|
|
res.redirect('/admin/product/edit/' + req.body.frmProductId);
|
|
|
|
}else{
|
|
|
|
// Update the index
|
|
|
|
common.indexProducts(req.app)
|
|
|
|
.then(() => {
|
|
|
|
req.session.message = 'Successfully saved';
|
|
|
|
req.session.messageType = 'success';
|
|
|
|
res.redirect('/admin/product/edit/' + req.body.frmProductId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// delete product
|
2019-06-15 14:46:08 +10:00
|
|
|
router.get('/admin/product/delete/:id', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
|
|
|
// remove the article
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.remove({ _id: common.getId(req.params.id) }, {}, (err, numRemoved) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
// delete any images and folder
|
|
|
|
rimraf('public/uploads/' + req.params.id, (err) => {
|
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove the index
|
|
|
|
common.indexProducts(req.app)
|
|
|
|
.then(() => {
|
|
|
|
// redirect home
|
|
|
|
req.session.message = 'Product successfully deleted';
|
|
|
|
req.session.messageType = 'success';
|
|
|
|
res.redirect('/admin/products');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// update the published state based on an ajax call from the frontend
|
2019-06-15 14:46:08 +10:00
|
|
|
router.post('/admin/product/published_state', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.update({ _id: common.getId(req.body.id) }, { $set: { productPublished: req.body.state } }, { multi: false }, (err, numReplaced) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.error(colors.red('Failed to update the published state: ' + err));
|
2018-02-06 05:51:04 +10:00
|
|
|
res.status(400).json('Published state not updated');
|
2018-02-05 23:20:44 +10:00
|
|
|
}else{
|
2018-02-06 05:51:04 +10:00
|
|
|
res.status(200).json('Published state updated');
|
2018-02-05 23:20:44 +10:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// set as main product image
|
2019-06-15 14:46:08 +10:00
|
|
|
router.post('/admin/product/setasmainimage', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
|
|
|
// update the productImage to the db
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.update({ _id: common.getId(req.body.product_id) }, { $set: { productImage: req.body.productImage } }, { multi: false }, (err, numReplaced) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(400).json({ message: 'Unable to set as main image. Please try again.' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}else{
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(200).json({ message: 'Main image successfully set' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// deletes a product image
|
2019-06-15 14:46:08 +10:00
|
|
|
router.post('/admin/product/deleteimage', restrict, checkAccess, (req, res) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
const db = req.app.db;
|
|
|
|
|
|
|
|
// get the productImage from the db
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.findOne({ _id: common.getId(req.body.product_id) }, (err, product) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
if(req.body.productImage === product.productImage){
|
|
|
|
// set the produt_image to null
|
2019-06-15 14:46:08 +10:00
|
|
|
db.products.update({ _id: common.getId(req.body.product_id) }, { $set: { productImage: null } }, { multi: false }, (err, numReplaced) => {
|
2018-02-05 23:20:44 +10:00
|
|
|
if(err){
|
|
|
|
console.info(err.stack);
|
|
|
|
}
|
|
|
|
// remove the image from disk
|
|
|
|
fs.unlink(path.join('public', req.body.productImage), (err) => {
|
|
|
|
if(err){
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(400).json({ message: 'Image not removed, please try again.' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}else{
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(200).json({ message: 'Image successfully deleted' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}else{
|
|
|
|
// remove the image from disk
|
|
|
|
fs.unlink(path.join('public', req.body.productImage), (err) => {
|
|
|
|
if(err){
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(400).json({ message: 'Image not removed, please try again.' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}else{
|
2019-06-15 14:46:08 +10:00
|
|
|
res.status(200).json({ message: 'Image successfully deleted' });
|
2018-02-05 23:20:44 +10:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = router;
|