Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
const path = require('path');
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 errorController = require('./controller/error');

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(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'});
});
app.use(errorController.get404);

app.listen(3000);
5 changes: 5 additions & 0 deletions controller/error.js
Original file line number Diff line number Diff line change
@@ -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' });
};
27 changes: 27 additions & 0 deletions controller/products.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const Product = require("../model/product");

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) => {
const product = new Product(req.body.title);
product.save();

console.log("admin.js ", product);
res.redirect("/");
};

exports.getproduct = (req, res, next) => {
const products = Product.fetchAll();
res.render("shop", {
pageTitle: "Shop",
prods: products, path: "/"
});
};
1 change: 1 addition & 0 deletions data/products.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"title":"book"}]
89 changes: 89 additions & 0 deletions model/product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// no more array, as we will store all our products in a file
// const products = [];

const fs = require('fs');
const path = require('path');

const rootDir = require('../util/path');

module.exports = class Product {

constructor(t) {
this.title = t;
}
save() {
// no more pushing elements to array
// products.push(this);

// 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');

// we will store file in JSON format
const p = path.join(rootDir, 'data', 'products.json')

// 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

});
})
}

static fetchAll() {
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);
});

// running the server, we get
// Cannot read property 'length' of undefined
// this error can be hard to debug
}
}
40 changes: 2 additions & 38 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -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.



<link rel="stylesheet" href="/public/css/main.css">
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
7.097
controller/products.js
19 changes: 6 additions & 13 deletions routes/admin.js
Original file line number Diff line number Diff line change
@@ -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;
module.exports = routes;
12 changes: 2 additions & 10 deletions routes/shop.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

10 changes: 0 additions & 10 deletions views/shop.ejs
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
<!-- ejs doesnt use concepts of layouts, where there will be one main file and other files can render it -->
<!-- so we use partials, ie some html files which can be used any where in other html files -->

<!-- to render html code from the file, we use "<%- " -->
<!-- if we will use "<%=" then it will render html code as text, instead of html code -->
<%- include('./includes/head.ejs') %>
<link rel="stylesheet" href="/css/product.css">

<%- include('./includes/navigation.ejs') %>
<main>
<!-- if condition -->
<!-- as if is condtion, we are not ooutput any dynamic content, thus no "=" sign after "%" sign -->
<!-- uses same vanialla js syntax, opening and closing braces -->
<% if (prods.length > 0) { %>
<div class="grid">
<!-- for loop -->
<% for (let product of prods) { %>
<article class="card product-item">
<header class="card__header">
<!-- accces the product titile -->
<!-- here as we are assessing the title of product dynamicaly, we are using "=" sign after "%" sign -->
<h1 class="product__title"><%= product.title %></h1>
</header>
<div class="card__image">
Expand Down