Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IDHalverson's Solution' #12

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
node_modules/
config/
config/sequelize.json
config/mongo.json
.env
17 changes: 17 additions & 0 deletions .sequelizerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var path = require('path');

// Set options
var config = {
"config": "./config/sequelize.json",
"migrations-path": "./migrations/sequelize",
"seeders-path": "./seeds/sequelize",
"models-path": "./models/sequelize"
};

// Resolve paths to absolute paths
Object.keys(config).forEach((key) => {
config[key] = path.resolve(config[key]);
});

// Export like any normal module
module.exports = config;
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# project_mimirs_market
A Viking eCommerce store for Thunder Gods that like to buy "Antique Wooden Pizzas"

Name: Ian Halverson
88 changes: 88 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//Express app
const express = require("express");
const app = express();

//Production environment variables
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}

//Modules
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const cookieSession = require("cookie-session");
const methodOverride = require("method-override");
const getPostSupport = require("express-method-override-get-post-support");
const morgan = require("morgan");
const morganToolkit = require("morgan-toolkit")(morgan);
const expressHandlebars = require("express-handlebars");
const hbs = expressHandlebars.create({
partialsDir: "views/partials",
defaultLayout: "application"
});
const { STRIPE_SK, STRIPE_PK } = process.env;
const stripe = require("stripe")(STRIPE_SK);

//Custom middleware modules
const mdw = require("./lib/middleware");

//Database models
const { Product } = require("./models/sequelize");

//Routers
const productsRouter = require("./routers/products");
const cartRouter = require("./routers/cart");
const checkoutRouter = require("./routers/checkout");
const adminRouter = require("./routers/admin");

//View engine
app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");

//Middleware from modules
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(`${__dirname}/public`));
app.use(morgan("tiny"));
app.use(morganToolkit());
app.use(
cookieSession({
name: "session",
keys: ["asdfqwerfdsarewq"]
})
);
app.use(
methodOverride(
getPostSupport.callback,
getPostSupport.options // { methods: ['POST', 'GET'] }
)
);

//Initial redirect
app.get("/", (req, res) => {
return res.redirect("/products");
});

//Middleware from files
app.use(mdw.setBackUrl);
app.use(mdw.mongooseReady);
app.use(mdw.retainSortField);
app.use(mdw.cartFiller);

//Routes
app.use("/products", productsRouter);
app.use("/cart", cartRouter);
app.use("/checkout", checkoutRouter);
app.use("/admin", adminRouter);

//Set up and start server
const port = process.env.PORT || process.argv[2] || 3000;
const host = "localhost";
let args;
process.env.NODE_ENV === "production" ? (args = [port]) : (args = [port, host]);
args.push(() => {
console.log(`Listening: http://${host}:${port}`);
});
app.listen.apply(app, args);

module.exports = app;
13 changes: 13 additions & 0 deletions config/mongo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"development": {
"database": "mimirs_market_development",
"host": "localhost"
},
"test": {
"database": "mimirs_market_test",
"host": "localhost"
},
"production": {
"use_env_variable": "MONGODB_URI"
}
}
20 changes: 20 additions & 0 deletions config/sequelize.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"development": {
"username": "IanDavid",
"password": null,
"database": "mimirs_market_development",
"host": "127.0.0.1",
"dialect": "postgres"
},
"test": {
"username": "IanDavid",
"password": null,
"database": "mimirs_market_test",
"host": "127.0.0.1",
"dialect": "postgres"
},
"production": {
"use_env_variable": "DATABASE_URL",
"dialect": "postgres"
}
}
9 changes: 9 additions & 0 deletions lib/checkifincart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = function checkIfInCart(req, res, products) {
let cart = req.session.cart.map(i => i.id);
products.forEach((p, i) => {
if (cart.includes(p.id.toString())) {
products[i].inCart = true;
}
});
return products;
};
56 changes: 56 additions & 0 deletions lib/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const mongoose = require("mongoose");
const { Product, Category } = require("../models/sequelize");

const mdw = {
//set redirect to "/" unless referer
setBackUrl: (req, res, next) => {
req.session.backUrl = req.header("Referer") || "/";
next();
},

//check mongoose connection, reconnect if needed
mongooseReady: (req, res, next) => {
if (mongoose.connection.readyState) {
next();
} else {
require("../mongo")().then(() => next());
}
},

//retain sort option input field (negated on some routes)
retainSortField: (req, res, next) => {
res.cookie("selectedSortOption", "id-ASC");
next();
},

// hoist cart if needed, find items,
// make available to view engine, hoist inCart object
cartFiller: (req, res, next) => {
let total = 0;
req.session.cart = req.session.cart || [];
let cart = req.session.cart.map(i => i.id);
Product.findAll({
where: { id: { $in: cart } },
include: [{ all: true, nested: true }]
})
.then(r => {
r.forEach((p, pix) => {
req.session.cart.forEach((i, cix) => {
if (p.id * 1 === i.id * 1) {
p.quantity = i.quantity;
total += i.quantity * p.price;
}
});
});
return r;
})
.then(r => {
res.locals.items = r;
res.locals.total = total;
res.locals.inCart = true;
next();
});
}
};

module.exports = mdw;
32 changes: 32 additions & 0 deletions migrations/sequelize/20170809155208-create-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("States", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.CHAR
},
abbreviation: {
type: Sequelize.CHAR
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("States");
}
};
32 changes: 32 additions & 0 deletions migrations/sequelize/20170809155228-create-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("Users", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.CHAR
},
email: {
type: Sequelize.CHAR
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("Users");
}
};
29 changes: 29 additions & 0 deletions migrations/sequelize/20170809155307-create-category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("Categories", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.CHAR
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("Categories");
}
};
44 changes: 44 additions & 0 deletions migrations/sequelize/20170809155314-create-product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("Products", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.CHAR
},
description: {
type: Sequelize.CHAR
},
imageUrl: {
type: Sequelize.CHAR
},
price: {
type: Sequelize.INTEGER
},
sku: {
type: Sequelize.INTEGER
},
categoryId: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("Products");
}
};
32 changes: 32 additions & 0 deletions migrations/sequelize/20170809162905-create-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("States", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.CHAR
},
abbreviation: {
type: Sequelize.CHAR
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("States");
}
};
Loading