├── README.md ├── .idea ├── .gitignore ├── modules.xml └── project.iml ├── models ├── db.js └── employee.model.js ├── package.json ├── index.js ├── node.txt ├── views ├── layouts │ └── mainLayout.hbs └── employee │ ├── list.hbs │ └── addOrEdit.hbs └── controllers └── employeeController.js /README.md: -------------------------------------------------------------------------------- 1 | # full-stack-app 2 | NodeJS ExpressJS MongoDB 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /models/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | mongoose.connect('mongodb://localhost:27017/node', { useNewUrlParser: true }, (err) => { 4 | if (!err) { 5 | console.log('Mongo DB connected successfully') 6 | }else{ 7 | console.log('Error in db connection: ' + err) 8 | } 9 | }) 10 | 11 | require('./employee.model') -------------------------------------------------------------------------------- /.idea/project.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "body-parser": "^1.18.3", 4 | "express": "^4.16.4", 5 | "express-handlebars": "^3.0.0", 6 | "mongoose": "^5.3.4" 7 | }, 8 | "name": "project", 9 | "version": "1.0.0", 10 | "main": "index.js", 11 | "devDependencies": { 12 | "nodemon": "^2.0.7" 13 | }, 14 | "scripts": { 15 | "start": "node index.js", 16 | "dev": "nodemon index.js" 17 | }, 18 | "keywords": [], 19 | "author": "Samar Badriddinov", 20 | "license": "ISC", 21 | "description": "" 22 | } 23 | -------------------------------------------------------------------------------- /models/employee.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const employeeSchema = new mongoose.Schema({ 4 | fullName: { 5 | type: String, 6 | required: 'This field is required' 7 | }, 8 | email: { 9 | type: String 10 | }, 11 | mobile: { 12 | type: String 13 | }, 14 | city: { 15 | type: String 16 | } 17 | }) 18 | 19 | // Custom validation for email 20 | employeeSchema.path('email').validate((val) => { 21 | emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 22 | return emailRegex.test(val); 23 | }, 'Invalid e-mail.'); 24 | 25 | mongoose.model('Employee', employeeSchema) -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./models/db'); 2 | 3 | const express = require('express'); 4 | const path = require('path'); 5 | const exphbs = require('express-handlebars'); 6 | const bodyparser = require('body-parser'); 7 | 8 | const employeeController = require('./controllers/employeeController'); 9 | 10 | let app = express(); 11 | app.use(bodyparser.urlencoded({ 12 | extended: true 13 | })); 14 | app.use(bodyparser.json()); 15 | app.set('views', path.join(__dirname, '/views/')); 16 | app.engine('hbs', exphbs({ extname: 'hbs', defaultLayout: 'mainLayout', layoutsDir: __dirname + '/views/layouts/' })); 17 | app.set('view engine', 'hbs'); 18 | 19 | app.listen(5000, () => { 20 | console.log('Express server started at port : 5000'); 21 | }); 22 | 23 | app.use('/employee', employeeController); -------------------------------------------------------------------------------- /node.txt: -------------------------------------------------------------------------------- 1 | npm i --s express@4.16.4 mongoose@5.3.4 express-handlebars@3.0.0 body-parser@1.18.3 2 | 3 | Bootstrap CDN 4 | 5 | Fontawesome CDN 6 | 7 | 8 | Custom validation for email 9 | employeeSchema.path('email').validate((val) => { 10 | emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 11 | return emailRegex.test(val); 12 | }, 'Invalid e-mail.'); 13 | -------------------------------------------------------------------------------- /views/layouts/mainLayout.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | CRUD 9 | 10 | 11 | 12 | 13 |
14 |
15 | {{{body}}} 16 |
17 |
18 | 19 | -------------------------------------------------------------------------------- /views/employee/list.hbs: -------------------------------------------------------------------------------- 1 |

2 | Create New 3 | Employee List 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{#each list}} 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | {{/each}} 29 | 30 |
Full NameEmailMobileCity
{{this.fullName}}{{this.email}}{{this.mobile}}{{this.city}} 24 | 25 | 26 |
-------------------------------------------------------------------------------- /views/employee/addOrEdit.hbs: -------------------------------------------------------------------------------- 1 |

{{viewTitle}}

2 |
3 | 4 |
5 | 6 | 7 |
8 | {{employee.fullNameError}} 9 |
10 |
11 |
12 | 13 | 14 |
15 | {{employee.emailError}} 16 |
17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 |
27 |
28 |
29 | 30 | View All 31 |
32 |
-------------------------------------------------------------------------------- /controllers/employeeController.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router() 3 | const mongoose = require('mongoose') 4 | const Employee = mongoose.model('Employee') 5 | 6 | router.get('/', (req, res) => { 7 | res.render('employee/addOrEdit', { 8 | viewTitle: 'Insert Employee' 9 | }) 10 | }) 11 | 12 | router.post('/', (req, res) => { 13 | if (req.body._id === ""){ 14 | insertRecord(req, res) 15 | }else{ 16 | updateRecord(req, res) 17 | } 18 | }) 19 | 20 | function insertRecord(req, res) { 21 | let employee = new Employee(); 22 | employee.fullName = req.body.fullName 23 | employee.email = req.body.email 24 | employee.mobile = req.body.mobile 25 | employee.city = req.body.city 26 | employee.save((err, doc) => { 27 | if (!err) 28 | res.redirect('employee/list') 29 | else{ 30 | if (err.name === 'ValidationError'){ 31 | handleValidationError(err, req.body) 32 | res.render('employee/addOrEdit', { 33 | viewTitle: 'Insert Employee', 34 | employee: req.body 35 | }) 36 | } 37 | else{ 38 | console.log('Error during record ' + err) 39 | } 40 | } 41 | }) 42 | } 43 | 44 | function updateRecord(req, res) { 45 | Employee.findOneAndUpdate({ _id: req.body._id }, req.body, { new: true }, (err, doc) => { 46 | if (!err) { 47 | res.redirect('employee/list') 48 | }else{ 49 | if (err.name === "ValidationError") { 50 | handleValidationError(err, req.body) 51 | res.render('employee/addOrEdit', { 52 | viewTitle: 'Update Employee', 53 | employee: doc 54 | }) 55 | }else { 56 | console.log('Error during record update: ' + err) 57 | } 58 | } 59 | }) 60 | } 61 | 62 | router.get('/list', (req, res) => { 63 | Employee.find((err, docs) => { 64 | if (!err) { 65 | res.render('employee/list', { 66 | list: docs 67 | }) 68 | }else{ 69 | console.log('Error in employee list: '+ err) 70 | } 71 | }).lean() 72 | }) 73 | 74 | function handleValidationError(err, body) { 75 | for (field in err.errors){ 76 | switch (err.errors[field].path) { 77 | case 'fullName': 78 | body['fullNameError'] = err.errors[field].message 79 | break 80 | case 'email': 81 | body['emailError'] = err.errors[field].message 82 | break 83 | default: 84 | break 85 | } 86 | } 87 | } 88 | 89 | router.get('/:id', (req, res) => { 90 | Employee.findById(req.params.id, (err, doc) => { 91 | if(!err) { 92 | res.render('employee/addOrEdit', { 93 | viewTitle: 'Изменит работника', 94 | employee: doc 95 | }) 96 | } 97 | }).lean() 98 | }) 99 | 100 | router.get('/delete/:id', (req, res) => { 101 | Employee.findByIdAndRemove(req.params.id, (err, doc) => { 102 | if (!err) { 103 | res.redirect('/employee/list') 104 | }else{ 105 | console.log('Error in processing delete: '+ err) 106 | } 107 | }) 108 | }) 109 | 110 | module.exports = router --------------------------------------------------------------------------------