From 04635f9ddf3e9dfc0c934189dba3f18080467440 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Tue, 14 Jan 2020 01:12:16 +0530 Subject: [PATCH 1/5] adding controllers --- app.js | 7 ++----- controller/products.js | 16 ++++++++++++++++ routes/admin.js | 19 ++++++------------- routes/shop.js | 12 ++---------- views/shop.ejs | 10 ---------- 5 files changed, 26 insertions(+), 38 deletions(-) create mode 100644 controller/products.js diff --git a/app.js b/app.js index d6a0724..436b9d6 100644 --- a/app.js +++ b/app.js @@ -3,27 +3,24 @@ const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); -const adminData = require('./routes/admin'); +const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); const app = express(); -// no need to register the engin, as exoress auto register it app.set('view engine', 'ejs'); app.set('views', 'views'); app.use(bodyParser.urlencoded({extended : true})); app.use(express.static(path.join(rootDir, 'public'))); -app.use('/admin',adminData.routes); +app.use('/admin', adminRoutes); app.use(shopRoutes); app.use((req, res, next) => { res.status(404); res.setHeader('Content-type','text/html'); - // passing the argument to templating engine doesnt change, it remains the same - // "path: 'Error'" we passed becasue ejs engin will check "path" argument in naviagation bar logic of template. if we will not provide, we will get an error res.render('404', {pageTitle: "404", path: 'Error'}); }); diff --git a/controller/products.js b/controller/products.js new file mode 100644 index 0000000..2b3323e --- /dev/null +++ b/controller/products.js @@ -0,0 +1,16 @@ +const products = []; + +exports.getAddProduct = (req, res, next) => { + res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) +}; + +exports.postAddProduct = (req, res, next) => { + products.push({'title' : req.body.title}); + console.log('admin.js ', products); + res.redirect('/'); +}; + +exports.getproduct = (req, res, next) => { + res.render('shop', {pageTitle: 'Shop', prods : products, path : '/'}); + // console.log('shop.js ', products); +}; \ No newline at end of file diff --git a/routes/admin.js b/routes/admin.js index 259e70e..c3fe8e1 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -1,22 +1,15 @@ - const path = require('path'); const express = require('express'); -const rootDir = require('../util/path'); +// no more using html pages, as we are using ejs engine +// const rootDir = require('../util/path'); +const productsController = require('../controller/products'); const routes = express.Router(); -const products = []; -routes.get('/add-product', (req, res, next) => { - res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) -}); +routes.get('/add-product', productsController.getAddProduct); -routes.post('/add-product', (req, res, next) => { - products.push({'title' : req.body.title}); - console.log('admin.js ', products); - res.redirect('/'); -}); +routes.post('/add-product', productsController.postAddProduct); -module.exports.routes = routes; -module.exports.productArr = products; \ No newline at end of file +module.exports = routes; diff --git a/routes/shop.js b/routes/shop.js index a558eea..fb40926 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -2,18 +2,10 @@ const path = require('path'); const express = require('express'); -const adminData = require('./admin'); +const productsController = require('../controller/products'); const routes = express.Router(); -routes.get('/', (req, res, next) => { - // "layout: false" is speacial keyword which is understood by handlerbars which tells us that we are not using anhy layouts. thus no error regarding layouts will pop up. - // res.render('shop', {pageTitle: 'Shop', prods : adminData.productArr, path : '/', hasProducts : adminData.productArr.length > 0, layout: false}); - - res.render('shop', {pageTitle: 'Shop', prods : adminData.productArr, path : '/', hasProducts : adminData.productArr.length > 0, activeShop: true, productCSS: true}); - - console.log('shop.js ', adminData.productArr); -}); +routes.get('/', productsController.getproduct); module.exports = routes; - diff --git a/views/shop.ejs b/views/shop.ejs index ca4ba38..4a09fce 100644 --- a/views/shop.ejs +++ b/views/shop.ejs @@ -1,24 +1,14 @@ - - - - <%- include('./includes/head.ejs') %> <%- include('./includes/navigation.ejs') %>
- - - <% if (prods.length > 0) { %>
- <% for (let product of prods) { %>
- -

<%= product.title %>

From 3b3ca6333a31aef6472fffb0b5a07d9698c61704 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Tue, 14 Jan 2020 19:18:42 +0530 Subject: [PATCH 2/5] added error controller --- app.js | 7 ++----- controller/error.js | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 controller/error.js diff --git a/app.js b/app.js index 436b9d6..9d9f444 100644 --- a/app.js +++ b/app.js @@ -6,6 +6,7 @@ const bodyParser = require('body-parser'); const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); +const errorController = require('./controller/error'); const app = express(); @@ -18,10 +19,6 @@ app.use(express.static(path.join(rootDir, 'public'))); app.use('/admin', adminRoutes); app.use(shopRoutes); -app.use((req, res, next) => { - res.status(404); - res.setHeader('Content-type','text/html'); - res.render('404', {pageTitle: "404", path: 'Error'}); -}); +app.use(errorController.get404); app.listen(3000); \ No newline at end of file diff --git a/controller/error.js b/controller/error.js new file mode 100644 index 0000000..45d2ef3 --- /dev/null +++ b/controller/error.js @@ -0,0 +1,5 @@ +exports.get404 = (req, res, next) => { + res.status(404); + res.setHeader('Content-type','text/html'); + res.render('404', {pageTitle: "404", path: 'Error'}); +}; \ No newline at end of file From 73b9acfd4d06b3e3259fdec67883d64f9b9249c6 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 09:30:38 +0530 Subject: [PATCH 3/5] adding product model --- app.js | 4 ++-- controller/error.js | 4 ++-- controller/products.js | 38 +++++++++++++++++++++++++++++++------- model/product.js | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 model/product.js diff --git a/app.js b/app.js index 9d9f444..a99b7ef 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -const path = require('path'); +const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); @@ -13,7 +13,7 @@ const app = express(); app.set('view engine', 'ejs'); app.set('views', 'views'); -app.use(bodyParser.urlencoded({extended : true})); +app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); app.use('/admin', adminRoutes); diff --git a/controller/error.js b/controller/error.js index 45d2ef3..5d3d895 100644 --- a/controller/error.js +++ b/controller/error.js @@ -1,5 +1,5 @@ exports.get404 = (req, res, next) => { res.status(404); - res.setHeader('Content-type','text/html'); - res.render('404', {pageTitle: "404", path: 'Error'}); + res.setHeader('Content-type', 'text/html'); + res.render('404', { pageTitle: "404", path: 'Error' }); }; \ No newline at end of file diff --git a/controller/products.js b/controller/products.js index 2b3323e..26334b4 100644 --- a/controller/products.js +++ b/controller/products.js @@ -1,16 +1,40 @@ -const products = []; +// no need of this, we have our "model" file +// const products = []; + +// Product(P is uppercase), this is because it is convention to use class variable with upper case +const Product = require("../model/product"); + +// now we willcreate a new object based on class blueprint exports.getAddProduct = (req, res, next) => { - res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) + res.render("addProduct", { + path: "admin/add-product", + pageTitle: "Add Products", + activeAddProduct: true, + formsCSS: true, + productCSS: true + }); }; exports.postAddProduct = (req, res, next) => { - products.push({'title' : req.body.title}); - console.log('admin.js ', products); - res.redirect('/'); + // no use, we will create new object to the class and pass the value to it + // products.push({'title' : req.body.title}); + + // in form field of 'addProduct.ejs' , there "name= title". thus writing "req.body.title" + const product = new Product(req.body.title); + product.save(); + + // after craeting the new product object, we need to save that by calling save() method of the clas + console.log("admin.js ", product); + res.redirect("/"); }; exports.getproduct = (req, res, next) => { - res.render('shop', {pageTitle: 'Shop', prods : products, path : '/'}); + // we are just calling static method and not craeting any object with dummy text, as we alraedy have an product array in 'model' where we are storing all the products + const products = Product.fetchAll(); + res.render("shop", { + pageTitle: "Shop", + prods: products, path: "/" + }); // console.log('shop.js ', products); -}; \ No newline at end of file +}; diff --git a/model/product.js b/model/product.js new file mode 100644 index 0000000..8aa8fb2 --- /dev/null +++ b/model/product.js @@ -0,0 +1,39 @@ +// ES5 way +// module.exports = function Product() {} + + +const products = []; + +// ES6 : using concept of classes +module.exports = class Product { + + // constructor is used to give shape to the product + constructor(t) { + // creating a property within a class "title" + // this allows us to create an object based in this class where we can pass the ttitle to the constructor, which we call with new and then this will get stored in created object + // but we dont only create the object + this.title = t; + } + + // but we want to store the product to our array product and fetch it when nessary + + // "save" is special function without a 'function' keyword + // save method is avaliable in the class where we will save the products + + // "save()" should be called on instatited object pased on object + save() { + // "this" will reffer to the object created within a class, and that object we want to push to the product array + products.push(this); + } + + // after saving, we should able to retrive the products from the array product + // "fetchAll" method is like utility function. this is not called on single instance of the product because because it should fetch all products and we dont want to create new object with new keyword with some dummy title, just to fech all existence product. + // thus we will add "static " keyword, which make sure that we call this method directly on the class itself and no on any instanttiated object + static fetchAll() { + // "this.product" will return the current product and not the full array of products + // return this.product; + + // we should return whole product array + return products; + } +} \ No newline at end of file From 865cba4cb7aed8f7453453ced4bb4c72f4cdb7b8 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 11:25:56 +0530 Subject: [PATCH 4/5] storing data in a file via model --- controller/products.js | 13 ------ data/products.json | 1 + model/product.js | 94 ++++++++++++++++++++++++++++++++---------- 3 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 data/products.json diff --git a/controller/products.js b/controller/products.js index 26334b4..6ae5786 100644 --- a/controller/products.js +++ b/controller/products.js @@ -1,11 +1,5 @@ -// no need of this, we have our "model" file -// const products = []; - -// Product(P is uppercase), this is because it is convention to use class variable with upper case const Product = require("../model/product"); -// now we willcreate a new object based on class blueprint - exports.getAddProduct = (req, res, next) => { res.render("addProduct", { path: "admin/add-product", @@ -17,24 +11,17 @@ exports.getAddProduct = (req, res, next) => { }; exports.postAddProduct = (req, res, next) => { - // no use, we will create new object to the class and pass the value to it - // products.push({'title' : req.body.title}); - - // in form field of 'addProduct.ejs' , there "name= title". thus writing "req.body.title" const product = new Product(req.body.title); product.save(); - // after craeting the new product object, we need to save that by calling save() method of the clas console.log("admin.js ", product); res.redirect("/"); }; exports.getproduct = (req, res, next) => { - // we are just calling static method and not craeting any object with dummy text, as we alraedy have an product array in 'model' where we are storing all the products const products = Product.fetchAll(); res.render("shop", { pageTitle: "Shop", prods: products, path: "/" }); - // console.log('shop.js ', products); }; diff --git a/data/products.json b/data/products.json new file mode 100644 index 0000000..8b086a0 --- /dev/null +++ b/data/products.json @@ -0,0 +1 @@ +[{"title":"book"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index 8aa8fb2..40bc28c 100644 --- a/model/product.js +++ b/model/product.js @@ -1,39 +1,89 @@ -// ES5 way -// module.exports = function Product() {} +// no more array, as we will store all our products in a file +// const products = []; +const fs = require('fs'); +const path = require('path'); -const products = []; +const rootDir = require('../util/path'); -// ES6 : using concept of classes module.exports = class Product { - // constructor is used to give shape to the product constructor(t) { - // creating a property within a class "title" - // this allows us to create an object based in this class where we can pass the ttitle to the constructor, which we call with new and then this will get stored in created object - // but we dont only create the object this.title = t; } + save() { + // no more pushing elements to array + // products.push(this); - // but we want to store the product to our array product and fetch it when nessary + // creating a file + // if u dont want to use, "path" file which is in util folder, directly use the command, which we have provided in "path" file of util folder + // const p = path.join(path.dirname(process.mainModule.filename), 'data', 'products.json'); - // "save" is special function without a 'function' keyword - // save method is avaliable in the class where we will save the products + // we will store file in JSON format + const p = path.join(rootDir, 'data', 'products.json') - // "save()" should be called on instatited object pased on object - save() { - // "this" will reffer to the object created within a class, and that object we want to push to the product array - products.push(this); + // to store the new product, first we need to get existing products and then store new product at the end + // so, first we read the file + // for large file, we will not read file.ie, not putting the file in memory. we will be reading as a stream + // fs.createReadStream() + + // but our file will be shorter, we will read the file + // function in second argument will be executed when reading of file is done + fs.readFile(p, (err, fileContent) => { + // console.log(fileContent); + + //if we run the server, we will get + // ReferenceError: products is not defined at "shop.js" + // we got an error because, we dont have any file... so no content + + // now, if we see error + // console.log(err); + // in console, we can see + // "undefined" + // [Error: ENOENT: no such file or directory, open 'D:\My\vscode\node\5.express\data\products.json'] { + // errno: -4058, + // code: 'ENOENT', + // syscall: 'open', + // path: 'D:\\My\\vscode\\node\\5.express\\data\\products.json' + // } + + + let products = []; + if (!err) { + // parse method will takes incoming JSON data and gives back js array or object or whatever is there in a file + products = JSON.parse(fileContent); + } + // as we are using arrow function, it will reffer to the class. if we will use "function"(es5), it will losse its context and will not reffer to the class + // "this" refferes to the current object of the class + products.push(this); + + // after pushing to array, now we should save it to the file + // "stringify" method will take js object/arary and convert it into JSON format + fs.writeFile(p, JSON.stringify(products), (err) => { + console.log(err); + // we will still get an error, as we are not outputting anything. but we get + // "null" + // but in data folder, "products.json" is craeted where we can see the one object created in form of JSON + + }); + }) } - // after saving, we should able to retrive the products from the array product - // "fetchAll" method is like utility function. this is not called on single instance of the product because because it should fetch all products and we dont want to create new object with new keyword with some dummy title, just to fech all existence product. - // thus we will add "static " keyword, which make sure that we call this method directly on the class itself and no on any instanttiated object static fetchAll() { - // "this.product" will return the current product and not the full array of products - // return this.product; + const p = path.join(rootDir, 'data', 'products.json') + + // after stroing it in file, we should reterive the data + fs.readFile(p, (err, fileContent) => { + if(err) { + // if error is there, it will simply gives empty array and comes out of function + return []; + } + // convert json to JS form and pront it out + return JSON.parse(fileContent); + }); - // we should return whole product array - return products; + // running the server, we get + // Cannot read property 'length' of undefined + // this error can be hard to debug } } \ No newline at end of file From 0e4f8488afe50c3203e267c272addbe4eb1e9a26 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 13:08:18 +0530 Subject: [PATCH 5/5] 097 Storing Data in Files Via the Model --- notes.txt | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/notes.txt b/notes.txt index d5bb9e7..a6a7e17 100644 --- a/notes.txt +++ b/notes.txt @@ -1,38 +1,2 @@ -express js is all about middleware -ie, incoming request will passthrough bunch of functions -thus, there will be more than request handler. - it helps in code segreation - - - -we can have same url for more then one webpage till the time method ccessing that webpages are different -eg: /admin/add-products => GET - /admin/add-products => POST - routes.get('/add-products', (req, res, next) => { - routes.post('/add-products', (req, res, next) => { - - - -res.sendFile('/views/addProducts.html'); -this will cause error, as node will check for a file from root directory of and not from -root directory of the project -thus, "path" module will be used to specify the path to html files. - - - - -this will not work as node will not allow us to acces us the internal files on the browser -ie, localhost:300/public/css/main.css - -to access these static files, we have to modify our main app.js file -we need to serve files statically and stically simply means that its not handles by -router or expressjs or any other middleware. -but should be directly forwarded to file sysytem - - -installing templating engines -npm install --save ejs pug express-handlebars - - -pug: -html syntax is different but if we inspect page, it will shows us proper html code \ No newline at end of file +7.097 +controller/products.js \ No newline at end of file