Cleaned up old code and updated readme
parent
219e6b02fc
commit
8ce3074ba0
41
README.md
41
README.md
|
@ -19,13 +19,13 @@ Keeping expressCart running after closing the terminal can be done in a few ways
|
||||||
|
|
||||||
## Admin
|
## Admin
|
||||||
|
|
||||||
Visit: [http://127.0.0.1:1111/admin](http://127.0.0.1:1111/admin)
|
Visit: [http://127.0.0.1:1111/admin](http://127.0.0.1:1111/admin)
|
||||||
|
|
||||||
A new user form will be shown where a user can be created.
|
A new user form will be shown where a user can be created.
|
||||||
|
|
||||||
### Styling
|
### Styling
|
||||||
|
|
||||||
Adding your own custom style is done by accessing the `Admin` panel then selecting `General settings`.
|
Adding your own custom style is done by accessing the `Admin` panel then selecting `General settings`.
|
||||||
|
|
||||||
###### CSS
|
###### CSS
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ Set this value to a full 2 decimal value with no commas or currency symbols.
|
||||||
|
|
||||||
##### Permalink
|
##### Permalink
|
||||||
|
|
||||||
A permalink is a nice link to your product which is normally shown in search engine rankings. By default, if you Permalink value is set when adding a product,
|
A permalink is a nice link to your product which is normally shown in search engine rankings. By default, if you Permalink value is set when adding a product,
|
||||||
one will be generated using the Product title with spaces replaced by dashes.
|
one will be generated using the Product title with spaces replaced by dashes.
|
||||||
|
|
||||||
##### Options
|
##### Options
|
||||||
|
|
||||||
You may want to set product options such as 'Size', 'Color' etc.
|
You may want to set product options such as 'Size', 'Color' etc.
|
||||||
|
|
||||||
Below is an explanation of the fields and what they do
|
Below is an explanation of the fields and what they do
|
||||||
|
|
||||||
|
@ -67,23 +67,12 @@ Tags are used when indexing the products for search. It's advised to set tags (k
|
||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
By default `expressCart` uses an embedded database for easy setup and backup. `expressCart` also supports a MongoDB connection and it's recommended if you expect high traffic to your website.
|
`expressCart` uses a MongoDB for storing all the data. Setting of the database connection string is done through the `/config/settings.json` file. There are two properties relating to the database connection:
|
||||||
|
|
||||||
Setting of the database is done through the `/config/settings.json` file. There are two properties relating to the database connection:
|
|
||||||
|
|
||||||
Example embedded DB configuration:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"databaseType": "embedded"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Example MongoDB configuration:
|
Example MongoDB configuration:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"databaseType": "mongodb",
|
|
||||||
"databaseConnectionString": "mongodb://localhost:27017/expresscart"
|
"databaseConnectionString": "mongodb://localhost:27017/expresscart"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -94,7 +83,7 @@ Note: The `databaseConnectionString` property requires a full connection string.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
All settings are managed from the admin panel ([http://127.0.0.1:1111/admin](http://127.0.0.1:1111/admin)) except the Payment gateway and database settings.
|
All settings are managed from the admin panel ([http://127.0.0.1:1111/admin](http://127.0.0.1:1111/admin)) except the Payment gateway and database settings.
|
||||||
|
|
||||||
##### Cart name and Cart description
|
##### Cart name and Cart description
|
||||||
|
|
||||||
|
@ -144,7 +133,6 @@ to ensure the `Products per page` is a multiple of 3 for the best look.
|
||||||
|
|
||||||
This is the number of products displayed per row on your website. You can select anywhere up to 4 `Products per row`.
|
This is the number of products displayed per row on your website. You can select anywhere up to 4 `Products per row`.
|
||||||
|
|
||||||
|
|
||||||
##### Menu enabled
|
##### Menu enabled
|
||||||
|
|
||||||
Enables/disable the menu setup in `/admin/settings/menu`.
|
Enables/disable the menu setup in `/admin/settings/menu`.
|
||||||
|
@ -193,7 +181,7 @@ Note: The `secretKey` and `publicKey` is obtained from your Stripe account dashb
|
||||||
|
|
||||||
You will need to configure your SMTP details for expressCart to send email receipts to your customers.
|
You will need to configure your SMTP details for expressCart to send email receipts to your customers.
|
||||||
|
|
||||||
You will need to consult your email provider for the relevant details.
|
You will need to consult your email provider for the relevant details.
|
||||||
|
|
||||||
##### Gmail settings
|
##### Gmail settings
|
||||||
|
|
||||||
|
@ -223,8 +211,8 @@ You can use the `Send test email` button to ensure your email settings are corre
|
||||||
|
|
||||||
## Menu
|
## Menu
|
||||||
|
|
||||||
Although expressCart is a search based shopping cart, you can also group your products into categories using tags. You can then setup menu Items to "filter" based on
|
Although `expressCart` is a search based shopping cart, you can also group your products into categories using tags. You can then setup menu Items to "filter" based on
|
||||||
keywords (tags) to make it easier for your customers.
|
keywords (tags) to make it easier for your customers.
|
||||||
|
|
||||||
Setting of menu items is done via `/admin/settings/menu`.
|
Setting of menu items is done via `/admin/settings/menu`.
|
||||||
|
|
||||||
|
@ -240,12 +228,3 @@ You can re-order menu items by clicking and dragging the arrows icon and placing
|
||||||
You may want to create a static page to show contact details, about us, shipping information etc.
|
You may want to create a static page to show contact details, about us, shipping information etc.
|
||||||
|
|
||||||
New static pages are setup via `/admin/settings/pages`.
|
New static pages are setup via `/admin/settings/pages`.
|
||||||
|
|
||||||
## Upgrade from embedded DB to MongoDB
|
|
||||||
|
|
||||||
If you start using an embedded DB and decide your website is needing a dedicated MongoDB server you can simply upgrade by following these steps:
|
|
||||||
|
|
||||||
1. **IMPORTANT** Backup your `/data` folder
|
|
||||||
2. Ensure the MongoDB settings in the `/config/settings.json` file are added and are correct
|
|
||||||
3. Run `npm run dbUpgrade`
|
|
||||||
4. All done!
|
|
|
@ -95,15 +95,10 @@ router.get('/orders/filter/:search', common.restrict, (req, res, next) => {
|
||||||
let db = req.app.db;
|
let db = req.app.db;
|
||||||
let searchTerm = req.params.search;
|
let searchTerm = req.params.search;
|
||||||
let ordersIndex = req.app.ordersIndex;
|
let ordersIndex = req.app.ordersIndex;
|
||||||
let config = common.getConfig();
|
|
||||||
|
|
||||||
let lunrIdArray = [];
|
let lunrIdArray = [];
|
||||||
ordersIndex.search(searchTerm).forEach((id) => {
|
ordersIndex.search(searchTerm).forEach((id) => {
|
||||||
if(config.databaseType !== 'embedded'){
|
lunrIdArray.push(common.getId(id.ref));
|
||||||
lunrIdArray.push(common.getId(id.ref));
|
|
||||||
}else{
|
|
||||||
lunrIdArray.push(id.ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// we search on the lunr indexes
|
// we search on the lunr indexes
|
||||||
|
@ -317,17 +312,12 @@ router.post('/product/emptycart', (req, res, next) => {
|
||||||
// Admin section
|
// Admin section
|
||||||
router.get('/products/filter/:search', common.restrict, (req, res, next) => {
|
router.get('/products/filter/:search', common.restrict, (req, res, next) => {
|
||||||
let db = req.app.db;
|
let db = req.app.db;
|
||||||
let config = common.getConfig();
|
|
||||||
let searchTerm = req.params.search;
|
let searchTerm = req.params.search;
|
||||||
let productsIndex = req.app.productsIndex;
|
let productsIndex = req.app.productsIndex;
|
||||||
|
|
||||||
let lunrIdArray = [];
|
let lunrIdArray = [];
|
||||||
productsIndex.search(searchTerm).forEach((id) => {
|
productsIndex.search(searchTerm).forEach((id) => {
|
||||||
if(config.databaseType !== 'embedded'){
|
lunrIdArray.push(common.getId(id.ref));
|
||||||
lunrIdArray.push(common.getId(id.ref));
|
|
||||||
}else{
|
|
||||||
lunrIdArray.push(id.ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// we search on the lunr indexes
|
// we search on the lunr indexes
|
||||||
|
@ -422,10 +412,7 @@ router.post('/product/insert', common.restrict, (req, res) => {
|
||||||
res.redirect('/admin/product/new');
|
res.redirect('/admin/product/new');
|
||||||
}else{
|
}else{
|
||||||
// get the new ID
|
// get the new ID
|
||||||
let newId = newDoc._id;
|
let newId = newDoc.insertedIds;
|
||||||
if(config.databaseType !== 'embedded'){
|
|
||||||
newId = newDoc.insertedIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to lunr index
|
// add to lunr index
|
||||||
common.indexProducts(req.app)
|
common.indexProducts(req.app)
|
||||||
|
|
|
@ -381,11 +381,7 @@ exports.orderMenu = function(req, res){
|
||||||
|
|
||||||
// gets the correct type of index ID
|
// gets the correct type of index ID
|
||||||
exports.getId = function(id){
|
exports.getId = function(id){
|
||||||
let config = exports.getConfig();
|
|
||||||
let ObjectID = require('mongodb').ObjectID;
|
let ObjectID = require('mongodb').ObjectID;
|
||||||
if(config.databaseType === 'embedded'){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
if(id){
|
if(id){
|
||||||
if(id.length !== 24){
|
if(id.length !== 24){
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -247,11 +247,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
|
||||||
|
|
||||||
let lunrIdArray = [];
|
let lunrIdArray = [];
|
||||||
productsIndex.search(searchTerm).forEach((id) => {
|
productsIndex.search(searchTerm).forEach((id) => {
|
||||||
if(config.databaseType !== 'embedded'){
|
lunrIdArray.push(common.getId(id.ref));
|
||||||
lunrIdArray.push(common.getId(id.ref));
|
|
||||||
}else{
|
|
||||||
lunrIdArray.push(id.ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let pageNum = 1;
|
let pageNum = 1;
|
||||||
|
@ -296,11 +292,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
|
||||||
|
|
||||||
let lunrIdArray = [];
|
let lunrIdArray = [];
|
||||||
productsIndex.search(searchTerm).forEach((id) => {
|
productsIndex.search(searchTerm).forEach((id) => {
|
||||||
if(config.databaseType !== 'embedded'){
|
lunrIdArray.push(common.getId(id.ref))
|
||||||
lunrIdArray.push(common.getId(id.ref));
|
|
||||||
}else{
|
|
||||||
lunrIdArray.push(id.ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let menuLink = _.find(common.getMenu().items, (obj) => { return obj.link === searchTerm; });
|
let menuLink = _.find(common.getMenu().items, (obj) => { return obj.link === searchTerm; });
|
||||||
|
@ -488,23 +480,13 @@ const getData = function (req, page, query, cb){
|
||||||
console.error(colors.red('Error getting total product count', err));
|
console.error(colors.red('Error getting total product count', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.databaseType === 'embedded'){
|
db.products.find(query).skip(skip).limit(parseInt(numberProducts)).toArray((err, results) => {
|
||||||
db.products.find(query).skip(skip).limit(parseInt(numberProducts)).exec((err, results) => {
|
if(err){
|
||||||
if(err){
|
cb(new Error('Error retrieving products'), null);
|
||||||
cb(new Error('Error retrieving products'), null);
|
}else{
|
||||||
}else{
|
cb(null, {data: results, totalProducts: totalProducts});
|
||||||
cb(null, {data: results, totalProducts: totalProducts});
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}else{
|
|
||||||
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});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -74,35 +74,30 @@ router.get('/checkout_return', (req, res, next) => {
|
||||||
if(err){
|
if(err){
|
||||||
console.info(err.stack);
|
console.info(err.stack);
|
||||||
}
|
}
|
||||||
let lunrDoc = {
|
|
||||||
orderLastname: order.orderLastname,
|
|
||||||
orderEmail: order.orderEmail,
|
|
||||||
orderPostcode: order.orderPostcode,
|
|
||||||
id: order._id
|
|
||||||
};
|
|
||||||
|
|
||||||
// add to lunr index
|
// add to lunr index
|
||||||
req.app.ordersIndex.add(lunrDoc);
|
common.indexOrders(req.app)
|
||||||
|
.then(() => {
|
||||||
|
// set the results
|
||||||
|
req.session.messageType = 'success';
|
||||||
|
req.session.message = paymentMessage;
|
||||||
|
req.session.paymentEmailAddr = order.orderEmail;
|
||||||
|
req.session.paymentApproved = paymentApproved;
|
||||||
|
req.session.paymentDetails = paymentDetails;
|
||||||
|
|
||||||
// set the results
|
let paymentResults = {
|
||||||
req.session.messageType = 'success';
|
message: req.session.message,
|
||||||
req.session.message = paymentMessage;
|
messageType: req.session.messageType,
|
||||||
req.session.paymentEmailAddr = order.orderEmail;
|
paymentEmailAddr: req.session.paymentEmailAddr,
|
||||||
req.session.paymentApproved = paymentApproved;
|
paymentApproved: req.session.paymentApproved,
|
||||||
req.session.paymentDetails = paymentDetails;
|
paymentDetails: req.session.paymentDetails
|
||||||
|
};
|
||||||
|
|
||||||
let paymentResults = {
|
// send the email with the response
|
||||||
message: req.session.message,
|
common.sendEmail(req.session.paymentEmailAddr, 'Your payment with ' + config.cartTitle, common.getEmailTemplate(paymentResults));
|
||||||
messageType: req.session.messageType,
|
|
||||||
paymentEmailAddr: req.session.paymentEmailAddr,
|
|
||||||
paymentApproved: req.session.paymentApproved,
|
|
||||||
paymentDetails: req.session.paymentDetails
|
|
||||||
};
|
|
||||||
|
|
||||||
// send the email with the response
|
res.redirect('/payment/' + order._id);
|
||||||
common.sendEmail(req.session.paymentEmailAddr, 'Your payment with ' + config.cartTitle, common.getEmailTemplate(paymentResults));
|
});
|
||||||
|
|
||||||
res.redirect('/payment/' + order._id);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -194,11 +189,9 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the new ID
|
// get the new ID
|
||||||
let newId = newDoc._id;
|
let newId = '';
|
||||||
if(config.databaseType !== 'embedded'){
|
if(newDoc.insertedIds.length > 0){
|
||||||
if(newDoc.insertedIds.length > 0){
|
newId = newDoc.insertedIds[0].toString();
|
||||||
newId = newDoc.insertedIds[0].toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the order ID in the session
|
// set the order ID in the session
|
||||||
|
|
|
@ -60,60 +60,50 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the new ID
|
// get the new ID
|
||||||
let newId = newDoc._id;
|
let newId = newDoc.insertedIds;
|
||||||
if(config.databaseType !== 'embedded'){
|
|
||||||
newId = newDoc.insertedIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create order to add to index
|
|
||||||
let lunrDoc = {
|
|
||||||
orderLastname: orderDoc.orderLastname,
|
|
||||||
orderEmail: orderDoc.orderEmail,
|
|
||||||
orderPostcode: orderDoc.orderPostcode,
|
|
||||||
id: newId
|
|
||||||
};
|
|
||||||
|
|
||||||
// add to lunr index
|
// add to lunr index
|
||||||
req.app.ordersIndex.add(lunrDoc);
|
common.indexOrders(req.app)
|
||||||
|
.then(() => {
|
||||||
|
// if approved, send email etc
|
||||||
|
if(charge.paid === true){
|
||||||
|
// set the results
|
||||||
|
req.session.messageType = 'success';
|
||||||
|
req.session.message = 'Your payment was successfully completed';
|
||||||
|
req.session.paymentEmailAddr = newDoc.orderEmail;
|
||||||
|
req.session.paymentApproved = true;
|
||||||
|
req.session.paymentDetails = '<p><strong>Order ID: </strong>' + newId + '</p><p><strong>Transaction ID: </strong>' + charge.id + '</p>';
|
||||||
|
|
||||||
// if approved, send email etc
|
// set payment results for email
|
||||||
if(charge.paid === true){
|
let paymentResults = {
|
||||||
// set the results
|
message: req.session.message,
|
||||||
req.session.messageType = 'success';
|
messageType: req.session.messageType,
|
||||||
req.session.message = 'Your payment was successfully completed';
|
paymentEmailAddr: req.session.paymentEmailAddr,
|
||||||
req.session.paymentEmailAddr = newDoc.orderEmail;
|
paymentApproved: true,
|
||||||
req.session.paymentApproved = true;
|
paymentDetails: req.session.paymentDetails
|
||||||
req.session.paymentDetails = '<p><strong>Order ID: </strong>' + newId + '</p><p><strong>Transaction ID: </strong>' + charge.id + '</p>';
|
};
|
||||||
|
|
||||||
// set payment results for email
|
// clear the cart
|
||||||
let paymentResults = {
|
if(req.session.cart){
|
||||||
message: req.session.message,
|
req.session.cart = null;
|
||||||
messageType: req.session.messageType,
|
req.session.orderId = null;
|
||||||
paymentEmailAddr: req.session.paymentEmailAddr,
|
req.session.totalCartAmount = 0;
|
||||||
paymentApproved: true,
|
}
|
||||||
paymentDetails: req.session.paymentDetails
|
|
||||||
};
|
|
||||||
|
|
||||||
// clear the cart
|
// send the email with the response
|
||||||
if(req.session.cart){
|
common.sendEmail(req.session.paymentEmailAddr, 'Your payment with ' + config.cartTitle, common.getEmailTemplate(paymentResults));
|
||||||
req.session.cart = null;
|
|
||||||
req.session.orderId = null;
|
// redirect to outcome
|
||||||
req.session.totalCartAmount = 0;
|
res.redirect('/payment/' + newId);
|
||||||
|
}else{
|
||||||
|
// redirect to failure
|
||||||
|
req.session.messageType = 'danger';
|
||||||
|
req.session.message = 'Your payment has declined. Please try again';
|
||||||
|
req.session.paymentApproved = false;
|
||||||
|
req.session.paymentDetails = '<p><strong>Order ID: </strong>' + newId + '</p><p><strong>Transaction ID: </strong>' + charge.id + '</p>';
|
||||||
|
res.redirect('/payment/' + newId);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// send the email with the response
|
|
||||||
common.sendEmail(req.session.paymentEmailAddr, 'Your payment with ' + config.cartTitle, common.getEmailTemplate(paymentResults));
|
|
||||||
|
|
||||||
// redirect to outcome
|
|
||||||
res.redirect('/payment/' + newId);
|
|
||||||
}else{
|
|
||||||
// redirect to failure
|
|
||||||
req.session.messageType = 'danger';
|
|
||||||
req.session.message = 'Your payment has declined. Please try again';
|
|
||||||
req.session.paymentApproved = false;
|
|
||||||
req.session.paymentDetails = '<p><strong>Order ID: </strong>' + newId + '</p><p><strong>Transaction ID: </strong>' + charge.id + '</p>';
|
|
||||||
res.redirect('/payment/' + newId);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue