diff --git a/app.js b/app.js new file mode 100644 index 0000000..e641a7e --- /dev/null +++ b/app.js @@ -0,0 +1,31 @@ +'use strict' +const express = require('express'); +const app = express(); +const bodyParser = require('body-parser') +const routesIndex = require('./routes/index.js') + +// Controller +const Student = require('./controller').Student +// Student.methods(){} + +// TEMPLATE ENGINE +app.set('view engine', 'ejs') + +// PARSER +app.use(bodyParser.urlencoded({ extended: false })); + +// PUBLIC FOLDER +app.use(express.static('public')) + +// ROUTER INDEX SET +app.use('/', routesIndex) + + +// STUDENTS CRUD CALL +let argv = process.argv; +// Controller. + +// RUN +app.listen(3003, ()=>{ + console.log('listening on PORT 3003'); +}) diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..8a35464 --- /dev/null +++ b/config/config.json @@ -0,0 +1,23 @@ +{ + "development": { + "username": "werkbau", + "password": "pokemon", + "database": "express", + "host": "127.0.0.1", + "dialect": "postgres" + }, + "test": { + "username": "werkbau", + "password": "pokemon", + "database": "database_test", + "host": "127.0.0.1", + "dialect": "postgres" + }, + "production": { + "username": "werkbau", + "password": "pokemon", + "database": "database_production", + "host": "127.0.0.1", + "dialect": "postgres" + } +} diff --git a/controller/index.js b/controller/index.js new file mode 100644 index 0000000..d02d022 --- /dev/null +++ b/controller/index.js @@ -0,0 +1,13 @@ +const Student = require('./studentCRUD.js') +const Teacher = require('./teacherCRUD.js') +const Subject = require('./subjectCRUD.js') +// const User = require('./userCRUD.js') + + + + +module.exports = { + Student : Student, + Teacher : Teacher, + Subject : Subject +} diff --git a/controller/studentCRUD.js b/controller/studentCRUD.js new file mode 100644 index 0000000..6d32661 --- /dev/null +++ b/controller/studentCRUD.js @@ -0,0 +1,165 @@ +'use strict' +const db = require('../models/index.js'); +const View = require('../views/index.js'); +const express = require('express'); + +class Student { + constructor() { + + } + + static readCommands(argv){ + // node app.js + let target = argv[2]; + let command = argv[3]; + let options = argv.slice(4); + + if (target.toLowerCase() == "students") { + switch (command.toLowerCase()) { + case 'add': + Student.addStudent(options); + break; + case 'read': + Student.readStudent(options); + break; + case 'update': + Student.updateStudent(options); + break; + case 'delete': + Student.deleteStudent(options); + break; + default: console.log('command invalid'); + + } + } else { + console.log('target invalid'); + } + } + + // CRUD + static addStudent(options, res){ + db.Student.create({ + first_name: options[0], + last_name: options[1], + createdAt: new Date(), + updatedAt: new Date(), + email: options[2] + }).then(newStudent => { + if (res) { + Student.tableResponse(res, newStudent, 'added') + } else { + View.displayAddData(newStudent); + } + + }).catch(err=>{ + console.log('-----',err.message); + }) + } + + static readStudent(options){ + if (options[0]) { + db.Student.findOne({ + where:{ + id: options[0] + } + }).then(foundStudent => { + View.displayOneFound(foundStudent); + }); + } else { + db.Student.findAll({ + // attributes + }).then(foundStudents => { + View.displayManyFound(foundStudents); + }); + } + } + + static updateStudent(options, res){ + db.Student.findOne({ + where:{id:options[0]} + }).then(foundStudent => { + if (res) { + let updateData = { + first_name: options[1], + last_name: options[2], + email: options[3] + }; + foundStudent.update(updateData).then(()=>{ + // Student.tableResponse(res, foundStudent, 'Edited') + View.redirect(res, `/students`); + }); + + } else { + let updateData = {}; + updateData[options[1]] = options[2]; + foundStudent.update(updateData).then(()=>{ + View.displayUpdate(foundStudent); + }); + } + }); + } + + static deleteStudent(options, res){ + db.Student.findOne({ + where:{id:options[0]} + }).then(foundStudent => { + if (res) { + return foundStudent.destroy().then(()=>{ + View.redirect(res, '/students'); + }) + } else { + View.displayDestroyed(foundStudent); + return foundStudent.destroy(); + } + }); + } + + // display table + static tableResponse(res, newData, method){ + db.Student.findAll({ + include:[{ + model: db.Subject + }], + attributes: ['id', ['first_name', 'First Name'], ['last_name', 'Last Name'], 'email'], + order:[['first_name', 'ASC']] + }).then(foundStudents => { + View.displayStudentTable(res, foundStudents, 'Students', newData, method); + }); + } + + static showSubjectAddForm(id, res){ + + + db.Student.findOne({ + where:{id:id} + }).then((foundStudent)=>{ + res.render('./students_view/formAddSubject.ejs', + { title:'Edit Student', + h1:'Add Subject to Student', + id: id, + path:'students', + foundStudent:foundStudent + }) + }) + } + + static updateSubject(studentData, StudentId, res){ + let Subject = studentData.Subject; + db.Subject.findOne({ + where:{ + subject_name: Subject + } + }).then(foundSubject=>{ + db.StudentSubject.create({ + score: null, + StudentId: StudentId, + SubjectId: foundSubject.id + }).then(newConjunct=>{ + View.redirect(res, '/students') + }) + }) + } + +} + +module.exports = Student; diff --git a/controller/subjectCRUD.js b/controller/subjectCRUD.js new file mode 100644 index 0000000..56bd972 --- /dev/null +++ b/controller/subjectCRUD.js @@ -0,0 +1,282 @@ +'use strict' +const db = require('../models/index.js'); +const View = require('../views/index.js'); +const express = require('express'); + +class Subject { + constructor() { + } + + static readCommands(argv){ + // node app.js + let target = argv[2]; + let command = argv[3]; + let options = argv.slice(4); + + if (target.toLowerCase() == "subjects") { + switch (command.toLowerCase()) { + case 'add': + Subject.addSubject(options); + break; + case 'read': + Subject.readSubject(options); + break; + case 'update': + Subject.updateSubject(options); + break; + case 'delete': + Subject.deleteSubject(options); + break; + default: console.log('command invalid'); + + } + } else { + console.log('target invalid'); + } + } + + // CRUD + static addSubject(options, res){ + db.Subject.create({ + subject_name: options[0], + createdAt: new Date(), + updatedAt: new Date() + }).then(newSubject => { + if (res) { + Subject.tableResponse(res, newSubject, 'added') + } else { + View.displayAddData(newSubject); + } + + }); + } + + static readSubject(options){ + if (options[0]) { + db.Subject.findOne({ + where:{ + id: options[0] + } + }).then(foundSubject => { + View.displayOneFound(foundSubject); + }); + } else { + db.Subject.findAll({ + // attributes + }).then(foundSubjects => { + View.displayManyFound(foundSubjects); + }); + } + } + + static updateSubject(options, res){ + db.Subject.findOne({ + where:{id:options[0]} + }).then(foundSubject => { + if (res) { + let updateData = { + subject_name: options[1] + }; + foundSubject.update(updateData).then(()=>{ + View.redirect(res, '/subjects'); + }) + } else { + let updateData = {}; + updateData[options[1]] = options[2]; + foundSubject.update(updateData); + View.displayUpdate(foundSubject); + } + }); + } + + static deleteSubject(options, res){ + db.Subject.findOne({ + where:{id:options[0]} + }).then(foundSubject => { + if (res) { + return foundSubject.destroy().then(()=>{ + View.redirect(res, '/subjects'); + }); + } else { + View.displayDestroyed(foundSubject); + return foundSubject.destroy(); + } + }); + } + + + // static tableResponse(res, newData, method){ + // db.Subject.findAll({ + // include:[{ + // model: db.Teacher , + // attributes: [['first_name', 'First Name'], ['last_name', 'Last Name']] + // }], + // attributes: ['id', ['subject_name', 'Subject Name']] + // }).then(foundSubjects => { + // View.displaySubjectTable(res, foundSubjects, 'Subjects', newData, method); + // }); + // } + + static tableResponse(req, res) { + db.Subject.findAll({ + include:[{ + model: db.Teacher , + attributes: [['first_name', 'First Name'], ['last_name', 'Last Name']] + }], + attributes: ['id', ['subject_name', 'Subject Name']] + }).then(foundSubjects => { + let props = Object.getOwnPropertyNames(foundSubjects[0].dataValues); + res.render('./subjects_view/tableSubject.ejs', { + title: 'Subjects', + h1: 'Subjects', + heads: props, + foundDatas: foundSubjects, + newData: 'newData', + method: 'method', + path: 'subjects' + }) + }); + } + + + static form(req,res){ + res.render('form.ejs', { + title:'Subject', + h1:'Subject Data', + path:'subjects', + err: null + }) + } + + static formPost(req,res){ + let subject_name = req.body.subject_name; + db.Subject.create({ + subject_name: subject_name, + createdAt: new Date(), + updatedAt: new Date() + }).then(newSubject => { + Subject.tableResponse(req, res) + }).catch(err=>{ + res.render('form.ejs', { + title:'Subject', + h1:'Subject Data', + path:'subjects', + err : err + }) + }) + } + + static editSubject(req,res){ + let id = req.params.id + res.render('formEdit.ejs', { + title:'Edit Subject', + h1:'Edit Subject Data', + id: id, + path:'subjects', + err: null + }) + } + + static editSubjectPost(req, res){ + let id = req.params.id + let subject_name = req.body.subject_name; + + db.Subject.findOne({ + where:{ + id:id + } + }).then(foundSubject => { + let updateData = { + subject_name: subject_name + }; + return foundSubject.update(updateData) + }).then(()=>{ + res.redirect('/subjects'); + }).catch(err =>{ + res.render('formEdit.ejs', { + title:'Edit Subject', + h1:'Edit Subject Data', + id: id, + path:'subjects', + err: err + }) + }); + } + + static deleteSubjectWeb(req,res){ + let id = req.params.id + db.Subject.findOne({ + where:{ + id:id + } + }).then(foundSubject => { + return foundSubject.destroy() + }).then(()=>{ + res.redirect('/subjects'); + }); + } + + static subjectStudentsList(req, res){ + let subjectId = req.params.subjectId + db.Subject.findOne({ + where:{id:subjectId}, + include:[{ + model: db.Student, + attributes: ['id',['first_name', 'First Name'], ['last_name', 'Last Name']] + }, + { + model: db.StudentSubject + }] + }).then(foundSubject=>{ + let params = { + title: 'Subjects', + foundDatas: foundSubject.Students, + StudentSubjects: foundSubject.StudentSubjects, + subject_name:foundSubject.subject_name, + path: 'subjects', + subjectId:subjectId + } + res.render('./subjects_view/subjectStudentsList.ejs', params) + }) + } + + static giveScore(req, res){ + db.Student.findOne({ + where:{ + id:req.params.studentId + }, + attributes:[ + 'id', + ['first_name', 'First Name'], + ['last_name', 'Last Name'] + ] + }).then(foundStudent => { + let params = { + subjectId: req.params.subjectId, + studentId: req.params.studentId, + foundStudent: foundStudent + } + res.render('./subjects_view/formGiveScore.ejs', params) + }) + + + } + + static submitScore(req, res){ + db.StudentSubject.update( + { + score:req.body.score + }, + { + where:{ + SubjectId: req.params.subjectId, + StudentId: req.params.studentId + } + }).then(()=>{ + res.redirect(`/subjects/${req.params.subjectId}/enrolledstudents`); + }) + } + +} + +module.exports = Subject; diff --git a/controller/teacherCRUD.js b/controller/teacherCRUD.js new file mode 100644 index 0000000..f9b32f3 --- /dev/null +++ b/controller/teacherCRUD.js @@ -0,0 +1,129 @@ +'use strict' +const db = require('../models/index.js'); +const View = require('../views/index.js'); + + +class Teacher { + constructor() { + + } + + static readCommands(argv){ + // node app.js + let target = argv[2]; + let command = argv[3]; + let options = argv.slice(4); + + if (target.toLowerCase() == "teachers") { + switch (command.toLowerCase()) { + case 'add': + Teacher.addTeacher(options); + break; + case 'read': + Teacher.readTeacher(options); + break; + case 'update': + Teacher.updateTeacher(options); + break; + case 'delete': + Teacher.deleteTeacher(options); + break; + default: console.log('command invalid'); + + } + } else { + console.log('target invalid'); + } + } + + // CRUD + static addTeacher(options, res){ + db.Teacher.create({ + first_name: options[0], + last_name: options[1], + createdAt: new Date(), + updatedAt: new Date(), + email: options[2] + }).then(newTeacher => { + if (res) { + Teacher.tableResponse(res, newTeacher, 'added'); + } else { + View.displayAddData(newTeacher); + } + }); + } + + static readTeacher(options){ + if (options[0]) { + db.Teacher.findOne({ + where:{ + id: options[0] + } + }).then(foundTeacher => { + View.displayOneFound(foundTeacher); + }); + } else { + db.Teacher.findAll({ + // attributes + }).then(foundTeachers => { + View.displayManyFound(foundTeachers); + }); + } + } + + static updateTeacher(options, res){ + db.Teacher.findOne({ + where:{id:options[0]} + }).then(foundTeacher => { + if (res) { + let updateData = { + first_name: options[1], + last_name: options[2], + email: options[3] + }; + foundTeacher.update(updateData).then(()=>{ + View.redirect(res, '/teachers') + }); + } else { + let updateData = {}; + updateData[options[1]] = options[2]; + foundTeacher.update(updateData); + View.displayUpdate(foundTeacher); + } + }); + } + + static deleteTeacher(options, res){ + db.Teacher.findOne({ + where:{id:options[0]} + }).then(foundTeacher => { + if (res) { + return foundTeacher.destroy().then(()=>{ + View.redirect(res, '/teachers') + }); + } else { + View.displayDestroyed(foundTeacher); + return foundTeacher.destroy(); + } + + }); + } + + // display table + static tableResponse(res, newData, method){ + db.Teacher.findAll({ + // attributes + include:[{ + model: db.Subject, + attributes: [['subject_name', 'Subject Name']] + }], + attributes: ['id', ['first_name', 'First Name'], ['last_name', 'Last Name'], 'email'], + order: [['first_name', 'ASC']] + }).then(foundTeachers => { + View.displayTeacherTable(res, foundTeachers, 'Teachers', newData, method); + }); + } + +} + +module.exports = Teacher; diff --git a/controller/userCRUD.js b/controller/userCRUD.js new file mode 100644 index 0000000..03296b7 --- /dev/null +++ b/controller/userCRUD.js @@ -0,0 +1,91 @@ +'use strict' +const db = require('../models/index.js'); +const View = require('../views/index.js') + +class User { + constructor() { + + } + + static readCommands(argv){ + // node app.js + let target = argv[2]; + let command = argv[3]; + let options = argv.slice(4); + + if (target.toLowerCase() == "users") { + switch (command.toLowerCase()) { + case 'add': + User.addUser(options); + break; + case 'read': + User.readUser(options); + break; + case 'update': + User.updateUser(options); + break; + case 'delete': + User.deleteUser(options); + break; + default: console.log('command invalid'); + + } + } else { + console.log('target invalid'); + } + } + + // CRUD + static addUser(options){ + db.User.create({ + first_name: options[0], + last_name: options[1], + createdAt: new Date(), + updatedAt: new Date(), + email: options[2] + }).then(newUser => { + View.displayAddData(newUser); + }); + } + + static readUser(options){ + if (options[0]) { + db.User.findOne({ + where:{ + id: options[0] + } + }).then(foundUser => { + View.displayOneFound(foundUser); + }); + } else { + db.User.findAll({ + // attributes + }).then(foundUsers => { + View.displayManyFound(foundUsers); + }); + } + } + + static updateUser(options){ + db.User.findOne({ + where:{id:options[0]} + }).then(foundUser => { + let updateData = {}; + updateData[options[1]] = options[2]; + foundUser.update(updateData); + View.displayUpdate(foundUser); + }); + } + + static deleteUser(options){ + db.User.findOne({ + where:{id:options[0]} + }).then(foundUser => { + View.displayDestroyed(foundUser); + return foundUser.destroy(); + }); + } + +} + +module.exports = User; diff --git a/migrations/20180224031707-create-teacher.js b/migrations/20180224031707-create-teacher.js new file mode 100644 index 0000000..e0ed651 --- /dev/null +++ b/migrations/20180224031707-create-teacher.js @@ -0,0 +1,30 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Teachers', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + first_name: { + type: Sequelize.STRING + }, + last_name: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Teachers'); + } +}; \ No newline at end of file diff --git a/migrations/20180224031945-Teacher_email.js b/migrations/20180224031945-Teacher_email.js new file mode 100644 index 0000000..ddbb481 --- /dev/null +++ b/migrations/20180224031945-Teacher_email.js @@ -0,0 +1,25 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return queryInterface.addColumn('Teachers', 'email', Sequelize.STRING) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + return queryInterface.removeColumn('Teachers', 'email'); + } +}; diff --git a/migrations/20180224033303-create-subject.js b/migrations/20180224033303-create-subject.js new file mode 100644 index 0000000..0963342 --- /dev/null +++ b/migrations/20180224033303-create-subject.js @@ -0,0 +1,27 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Subjects', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + subject_name: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Subjects'); + } +}; \ No newline at end of file diff --git a/migrations/20180224045703-create-student.js b/migrations/20180224045703-create-student.js new file mode 100644 index 0000000..93c8b69 --- /dev/null +++ b/migrations/20180224045703-create-student.js @@ -0,0 +1,33 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Students', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + first_name: { + type: Sequelize.STRING + }, + last_name: { + type: Sequelize.STRING + }, + email: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Students'); + } +}; \ No newline at end of file diff --git a/migrations/20180225070959-teacher_subject_relation.js b/migrations/20180225070959-teacher_subject_relation.js new file mode 100644 index 0000000..8ea8656 --- /dev/null +++ b/migrations/20180225070959-teacher_subject_relation.js @@ -0,0 +1,25 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return queryInterface.addColumn('Teachers', 'SubjectId', Sequelize.INTEGER) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + return queryInterface.removeColumn('Teachers', 'SubjectId') + } +}; diff --git a/migrations/20180225125804-create-student-subject.js b/migrations/20180225125804-create-student-subject.js new file mode 100644 index 0000000..fc807d3 --- /dev/null +++ b/migrations/20180225125804-create-student-subject.js @@ -0,0 +1,33 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('StudentSubjects', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + score: { + type: Sequelize.INTEGER + }, + StudentId: { + type: Sequelize.INTEGER + }, + SubjectId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('StudentSubjects'); + } +}; \ No newline at end of file diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..5662f10 --- /dev/null +++ b/models/index.js @@ -0,0 +1,36 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var Sequelize = require('sequelize'); +var basename = path.basename(__filename); +var env = process.env.NODE_ENV || 'development'; +var config = require(__dirname + '/../config/config.json')[env]; +var db = {}; + +if (config.use_env_variable) { + var sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + var sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(file => { + var model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/models/student.js b/models/student.js new file mode 100644 index 0000000..5d29134 --- /dev/null +++ b/models/student.js @@ -0,0 +1,26 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Student = sequelize.define('Student', { + first_name: DataTypes.STRING, + last_name: DataTypes.STRING, + email: { + type: DataTypes.STRING, + validate:{ + isEmail : true, + notEmpty : true + } + } + }, {}); + + Student.prototype.fullName = function(){ + return this.dataValues['First Name']+' '+this.dataValues['Last Name'] + } + + + Student.associate = function(db) { + // associations can be defined here + Student.belongsToMany(db.Subject, {through: 'StudentSubject', foreignKey:'StudentId'}) + Student.hasMany(db.StudentSubject); + }; + return Student; +}; diff --git a/models/studentsubject.js b/models/studentsubject.js new file mode 100644 index 0000000..3cdb0f3 --- /dev/null +++ b/models/studentsubject.js @@ -0,0 +1,14 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var StudentSubject = sequelize.define('StudentSubject', { + score: DataTypes.INTEGER, + StudentId: DataTypes.INTEGER, + SubjectId: DataTypes.INTEGER + }, {}); + StudentSubject.associate = function(db) { + db.StudentSubject.belongsTo(db.Student, {foreignKey:'StudentId'}) + db.StudentSubject.belongsTo(db.Subject, {foreignKey:'SubjectId'}) + + }; + return StudentSubject; +}; diff --git a/models/subject.js b/models/subject.js new file mode 100644 index 0000000..6b69a5f --- /dev/null +++ b/models/subject.js @@ -0,0 +1,18 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Subject = sequelize.define('Subject', { + subject_name: { + type:DataTypes.STRING, + validate: { + is: ["^[a-z]+$",'i'] + } + } + }, {}); + Subject.associate = function(db) { + // associations can be defined here + Subject.hasMany(db.Teacher, {foreignKey:'SubjectId'}) + Subject.belongsToMany(db.Student, {through: 'StudentSubject', foreignKey:'SubjectId'}) + Subject.hasMany(db.StudentSubject) + }; + return Subject; +}; diff --git a/models/teacher.js b/models/teacher.js new file mode 100644 index 0000000..28b1816 --- /dev/null +++ b/models/teacher.js @@ -0,0 +1,18 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Teacher = sequelize.define('Teacher', { + first_name: DataTypes.STRING, + last_name: DataTypes.STRING, + email: DataTypes.STRING + }, {}); + + Teacher.prototype.fullName = function(){ + return this.dataValues['First Name']+' '+this.dataValues['Last Name'] + } + + Teacher.associate = function(db) { + // associations can be defined here + Teacher.belongsTo(db.Subject, {foreignKey:'SubjectId'}) + }; + return Teacher; +}; diff --git a/notes.js b/notes.js new file mode 100644 index 0000000..c94583e --- /dev/null +++ b/notes.js @@ -0,0 +1,49 @@ +const express = require('express'); +const bodyParser = require('body-parser'); + +const app = express(); + +const PORT = 3000; + +// CONTOH SETTING TEMPLATE ENGINE +app.set('view engine', 'ejs'); + +// SETTING BODY PARSER +app.use(bodyParser.urlencoded({ extended: false })); + +// CONTOH BIKIN SETTING STATIC FILES +app.use(express.static('public')); + +// CONTOH ROUTES +app.get('/', (request, response) => { + let obj = { + title: 'welcome to my web', + name: 'udin', + products: ['mami koko', 'keju', 'baju'], + }; + + response.render('home.ejs', obj); +}); + +app.get('/halo', (request, response) => { + let obj = { + title: 'welcome to my bandung', + name: 'bandung', + products: [], + }; + + response.render('home.ejs', obj); +}); + +app.get('/form-pendaftaran', (req, res) => { + res.render('form-daftar.ejs'); +}); + +app.post('/daftar', (request, response) => { + console.log(request.body); + response.render('thanks.ejs', { email: request.body.email }); +}); + +app.listen(PORT, () => { + console.log(`app is running on port ${PORT}`); +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..abd3f44 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,626 @@ +{ + "name": "express-from-scratch", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/geojson": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", + "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" + }, + "@types/node": { + "version": "9.4.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.4.6.tgz", + "integrity": "sha512-CTUtLb6WqCCgp6P59QintjHWqzf4VL1uPA27bipLAPxFqrtK1gEYllePzTICGqQ8rYsCbpnsNypXjjDzGAAjEQ==" + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "buffer-writer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", + "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "1.0.2", + "shimmer": "1.2.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "dottie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.0.tgz", + "integrity": "sha1-2hkZgci41xPKARXViYzzl8Lw3dA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "1.3.1", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "generic-pool": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.4.2.tgz", + "integrity": "sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "moment": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + }, + "moment-timezone": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", + "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", + "requires": { + "moment": "2.20.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pg": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.1.tgz", + "integrity": "sha512-Pi5qYuXro5PAD9xXx8h7bFtmHgAQEG6/SCNyi7gS3rvb/ZQYDmxKchfB0zYtiSJNWq9iXTsYsHjrM+21eBcN1A==", + "requires": { + "buffer-writer": "1.0.1", + "js-string-escape": "1.0.1", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "2.0.3", + "pg-types": "1.12.1", + "pgpass": "1.0.2", + "semver": "4.3.2" + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" + }, + "pg-pool": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.3.tgz", + "integrity": "sha1-wCIDLIlJ8xKk+R+2QJzgQHa+Mlc=" + }, + "pg-types": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", + "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "requires": { + "postgres-array": "1.0.2", + "postgres-bytea": "1.0.0", + "postgres-date": "1.0.3", + "postgres-interval": "1.1.1" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "1.0.1" + } + }, + "postgres-array": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", + "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" + }, + "postgres-interval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.1.tgz", + "integrity": "sha512-OkuCi9t/3CZmeQreutGgx/OVNv9MKHGIT5jH8KldQ4NLYXkvmT9nDVxEuCENlNwhlGPE374oA/xMqn05G49pHA==", + "requires": { + "xtend": "4.0.1" + } + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "retry-as-promised": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.2.tgz", + "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", + "requires": { + "bluebird": "3.5.1", + "debug": "2.6.9" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + } + }, + "sequelize": { + "version": "4.33.4", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.33.4.tgz", + "integrity": "sha512-PoKGxgHkc701Nfm0GO1/Sl3VJUALVHdI1k4TViDIDpUwYu98/qxkDSsZeT0geq1xKVNwRzYjhO5zSH+y1C3xQw==", + "requires": { + "bluebird": "3.5.1", + "cls-bluebird": "2.1.0", + "debug": "3.1.0", + "depd": "1.1.2", + "dottie": "2.0.0", + "generic-pool": "3.4.2", + "inflection": "1.12.0", + "lodash": "4.17.5", + "moment": "2.20.1", + "moment-timezone": "0.5.14", + "retry-as-promised": "2.3.2", + "semver": "5.5.0", + "terraformer-wkt-parser": "1.1.2", + "toposort-class": "1.0.1", + "uuid": "3.2.1", + "validator": "9.4.1", + "wkx": "0.4.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag==" + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2.3.8" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "terraformer": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.8.tgz", + "integrity": "sha1-UeCtiXRvzyFh3G9lqnDkI3fItZM=", + "requires": { + "@types/geojson": "1.0.6" + } + }, + "terraformer-wkt-parser": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz", + "integrity": "sha1-M2oMj8gglKWv+DKI9prt7NNpvww=", + "requires": { + "terraformer": "1.0.8" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "validator": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "wkx": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.2.tgz", + "integrity": "sha1-d201pjSlwi5lbkdEvetU+D/Szo0=", + "requires": { + "@types/node": "9.4.6" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6fe0b18 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "express-from-scratch", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/platinum-fox-2017/express-from-scratch.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/platinum-fox-2017/express-from-scratch/issues" + }, + "homepage": "https://github.com/platinum-fox-2017/express-from-scratch#readme", + "dependencies": { + "body-parser": "^1.18.2", + "ejs": "^2.5.7", + "express": "^4.16.2", + "pg": "^7.4.1", + "sequelize": "^4.33.4" + } +} diff --git a/public/styles/css.css b/public/styles/css.css new file mode 100644 index 0000000..046fb4b --- /dev/null +++ b/public/styles/css.css @@ -0,0 +1,83 @@ +* { + margin: 0px; + padding: 0px; +} + +h1 { + text-align: center; + color: black; + font-family: "Arial"; + margin-top: 30px; + font-size: 2.4em; +} + +table { + width: 100%; + border: solid 1px; +} +table th { + border: solid 1px; + padding : 4px 2px; +} +table td { + border: solid 1px; + padding : 2px; + text-align: center; +} + +#topBanner { + height: 60px; + background-color: black; + padding: 0px; + padding-left: 100px; + padding-right: 100px; + display: flex; + align-items: center; +} + +.navigation { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; +} + +.navigation a { + margin: 0px 10px; +} +.navigation button { + padding: 2px 5px; + width: auto; + background-color: rgba(0, 0, 0, 0.5); + border: none; + color: rgb(190,190,190 ); + font-size: 16px; + font-weight: bold; + outline:none; +} +button:hover { + color: rgb(255,255,255) +} + +.main{ + display: flex; + flex-direction: column; + justify-content: center; +} + +.content{ + display: flex; + flex-direction: column; + justify-content: center; + margin: 0px 100px; +} +.form { + display: flex; + padding: 10px 0px; + margin:auto; + +} + +body { + background-color: rgb(244,244,244); +} diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..e763ea7 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,68 @@ +const express = require('express') +const route = express.Router() + +route.use('/subjects', require('./subjects')); +route.use('/users', require('./users')); +route.use('/students', require('./students')); +route.use('/teachers', require('./teachers')); + +// Menampilkan profile sekolahan yang akan kamu buat seperti halaman home jika kalian masuk ke web sekolahan +route.get('/', (req, res)=>{ + // res.send('HelloWorld from Routes') + res.render('home.ejs', { title:'HOME PAGE', h1:'HELLO HOME PAGE'}) +}) + + +// test +route.get('/routing', (req, res)=>{ + // res.send('This is Routing page') + res.render('home.ejs', { title:'ROUTING PAGE', h1:'HELLO ROUTING PAGE'}) +}) + + +module.exports = route + + +// // menampilkan form untuk menginput data student +// app.get('/student', (req, res)=>{ +// res.render('form.ejs', { title:'Student', h1:'Student Data'}) +// }) +// // menerima data form untuk add student +// app.post('/send', (req, res)=>{ +// // console.log(req.body); +// let studentName = req.body.studentName; +// let studentAge = req.body.age +// res.render('home.ejs', { title:'Student', h1:`Student Name : ${studentName} Age : ${studentAge}`}) +// }) + + +// menampilkan data teachers dengan menggunakan table html +// router.get('/teacher', (req, res)=>{ + // res.render('home.ejs', { title:'Teachers', h1:'Teachers Data'}) +// }) + + +// menampilkan data Subjects dengan menggunakan table html +// router.get('/subject', (req, res)=>{ +// res.render('home.ejs', { title:'Teachers', h1:'Teachers Data'}) +// }) + + +// menampilkan data Users dengan menggunakan table html +// router.get('/user', (req, res)=>{ +// res.render('home.ejs', { title:'Teachers', h1:'Teachers Data'}) +// }) + + + + +// function(app){ +// let routes = fs.readdirSync(_dirname); +// routes .forEach(function(filename){ +// if (filename === 'index.js') { +// return; +// } +// let name = filename.substr(0, filename.indexOf('.')); +// require('./'+name)(app); +// }) +// } diff --git a/routes/students.js b/routes/students.js new file mode 100644 index 0000000..132cfaf --- /dev/null +++ b/routes/students.js @@ -0,0 +1,84 @@ +const express = require('express') +const route = express.Router(); +const app = express(); +const Student = require('../controller/index.js').Student; +const db = require('../models/index.js'); + +// /student +route.get('/', (req, res)=>{ + // get all students + Student.tableResponse(res) + // res.render('form.ejs', { title:'Student', h1:'Student Data'}) +}); + +// ############# ADD DATA #################### +route.get('/add', (req, res)=>{ + // get form for students + res.render('form.ejs', { title:'Student', h1:'Student Data', path:'students'}) +}); + +route.post('/send', (req, res)=>{ + // console.log(req.body); + let first_name = req.body.first_name; + let last_name = req.body.last_name; + let email = req.body.email; + let options = [first_name, last_name, email]; + // Controller => add student => view render tableResponse + Student.addStudent(options, res) + // res.render('home.ejs', { title:'Student', h1:`Student Name : ${first_name} ${last_name} email : ${email}`}); +}); + +// ################# EDIT #################### +route.get('/edit/:id', (req, res)=>{ + let id = req.param('id') + // console.log(id); + // res.send([id]) + // get edit form for students + // execute through controller => update student => view with res.render + res.render('formEdit.ejs', { title:'Edit Student', h1:'Edit Student Data', id: id, path:'students'}) +}); + +route.post('/edit/:id', (req, res)=>{ + // console.log(req.params.id); + // console.log('received success'); + // get request from edit page + let id = req.params.id + let first_name = req.body.first_name; + let last_name = req.body.last_name; + let email = req.body.email; + let options = [id, first_name, last_name, email]; + // console.log(options); + // Controller => edit student => view render tableResponse + Student.updateStudent(options, res) + // Student.addStudent(options, res) + // res.render('home.ejs', { title:'Student', h1:`Student Name : ${first_name} ${last_name} email : ${email}`}); +}); + + +// ################# DELETE #################### +route.get(`/delete/:id`, (req, res)=>{ + let options = [req.params.id] + // sent alert to webpage + // if (window.confirm('Do you want to delete this student record?')) { + Student.deleteStudent(options, res) + // } + // res.render('formEdit.ejs', { title:'Student', h1:'Edit Student Data'}) +}); + + + +// ################# SUBJECT #################### +route.get('/:id/addsubject', (req, res)=>{ + let id = req.param('id') + Student.showSubjectAddForm(id,res) +}); + +route.post('/:id/addsubject', (req, res)=>{ + // console.log('logging post'); + // console.log(req.param('id')); + // console.log(req.body); + Student.updateSubject(req.body, req.param('id'), res) +}); + + +module.exports = route diff --git a/routes/subjects.js b/routes/subjects.js new file mode 100644 index 0000000..d747b66 --- /dev/null +++ b/routes/subjects.js @@ -0,0 +1,25 @@ +const express = require('express') +const route = express.Router(); +const SubjectCRUD = require('../controller/index.js').Subject; + +route.get('/', SubjectCRUD.tableResponse); + +// ############# ADD DATA #################### +route.get('/add', SubjectCRUD.form); +route.post('/send', SubjectCRUD.formPost); + +// ################# EDIT #################### + +route.get('/edit/:id', SubjectCRUD.editSubject); +route.post('/edit/:id', SubjectCRUD.editSubjectPost); + +// ################# DELETE #################### +route.get(`/delete/:id`, SubjectCRUD.deleteSubjectWeb); + +// ################# ENROLLED STUDENTS #################### +route.get(`/:subjectId/enrolledstudents`, SubjectCRUD.subjectStudentsList); +route.get(`/:subjectId/givescore/:studentId`, SubjectCRUD.giveScore); +route.post('/:subjectId/givescore/:studentId', SubjectCRUD.submitScore); + + +module.exports = route diff --git a/routes/teachers.js b/routes/teachers.js new file mode 100644 index 0000000..ac62755 --- /dev/null +++ b/routes/teachers.js @@ -0,0 +1,46 @@ +const express = require('express') +const route = express.Router(); +const Teacher = require('../controller/index.js').Teacher; + +// /teacher +route.get('/', (req, res)=>{ + Teacher.tableResponse(res) +}); + +// ############# ADD DATA #################### +route.get('/add', (req, res)=>{ + res.render('./teachers_view/formTeachers.ejs', { title:'Teacher', h1:'Teacher Data', path:'teachers'}) +}); + +route.post('/send', (req, res)=>{ + let first_name = req.body.first_name; + let last_name = req.body.last_name; + let email = req.body.email; + let options = [first_name, last_name, email]; + Teacher.addTeacher(options, res) +}); + +// ################# EDIT #################### +route.get('/edit/:id', (req, res)=>{ + let id = req.param('id') + res.render('formEdit.ejs', { title:'Edit Teacher', h1:'Edit Teacher Data', id: id, path:'teachers'}) +}); + +route.post('/edit/:id', (req, res)=>{ + let id = req.params.id + let first_name = req.body.first_name; + let last_name = req.body.last_name; + let email = req.body.email; + let options = [id, first_name, last_name, email]; + Teacher.updateTeacher(options, res) +}); + + +// ################# DELETE #################### +route.get(`/delete/:id`, (req, res)=>{ + let options = [req.params.id] + Student.deleteTeacher(options, res) +}); + + +module.exports = route diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..881b98b --- /dev/null +++ b/routes/users.js @@ -0,0 +1,33 @@ +const express = require('express') +const route = express.Router() + + +// /user +route.get('/', (req, res)=>{ + res.render('home.ejs', { title:'Teachers', h1:'Teachers Data'}) +}) + +module.exports = route + +// router.get('/', (req, res)=>{ +// res.send('show all user data') +// }) +// +// router.post('/', (req, res)=>{ +// res.send('receive data form to input user') +// }) +// +// // ### edit/:id ### +// router.get('/edit/:id', (req, res)=>{ +// res.send('Show specific user data to change') +// }) +// +// router.post('/edit/:id', (req, res)=>{ +// res.send('receive data form to update user') +// }) +// +// +// // ### delete/:id ### +// router.get('/delete/:id', (req, res)=>{ +// res.send('delete data user by ID') +// }) diff --git a/seeders/20180224032252-Teacher_data.js b/seeders/20180224032252-Teacher_data.js new file mode 100644 index 0000000..8168666 --- /dev/null +++ b/seeders/20180224032252-Teacher_data.js @@ -0,0 +1,54 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('Teachers', [ + { first_name: 'Bambang', + last_name: 'Suprapto', + createdAt: new Date(), + updatedAt: new Date(), + email: 'bambangsuprapto@sekolah.id' + }, + { first_name: 'Rukmana', + last_name: 'Fatmawati', + createdAt: new Date(), + updatedAt: new Date(), + email: 'rukmanafatmawati@sekolah.id' + }, + { first_name: 'Butet', + last_name: 'Naiborhu', + createdAt: new Date(), + updatedAt: new Date(), + email: 'butetnaiborhu@sekolah.id' + }, + { first_name: 'Yulius', + last_name: 'Prawiranegara', + createdAt: new Date(), + updatedAt: new Date(), + email: 'yuliusprawiranegara@sekolah.id' + } + ]) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + return queryInterface.bulkDelete('Teachers', { where:{} }); + } + +}; diff --git a/seeders/20180224033443-subject_data.js b/seeders/20180224033443-subject_data.js new file mode 100644 index 0000000..cf88cb0 --- /dev/null +++ b/seeders/20180224033443-subject_data.js @@ -0,0 +1,39 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('Subjects', [ + { + subject_name: 'Kimia', + createdAt: new Date(), + updatedAt: new Date() + }, + { + subject_name: 'Ekonomi', + createdAt: new Date(), + updatedAt: new Date() + }, + ]) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + return queryInterface.bulkDelete('Subjects', { where:{}}) + } +}; diff --git a/seeders/20180224082240-students.js b/seeders/20180224082240-students.js new file mode 100644 index 0000000..1d2ff8c --- /dev/null +++ b/seeders/20180224082240-students.js @@ -0,0 +1,57 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('Students', [ + { + first_name: 'Fransiskus', + last_name: 'Teddy', + email: 'work@email.com', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Sebastian', + last_name: 'Sumali', + email: 'newemail@gmail.com', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Wika', + last_name: 'Silo', + email: 'potato@potato.com', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Yohanes', + last_name: 'Sahrul', + email: 'coding@allday.com', + createdAt: new Date(), + updatedAt: new Date() + } + ]) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + return queryInterface.bulkDelete('Students', {where:{}}) + } +}; diff --git a/seeders/20180225145551-StudentSubject.js b/seeders/20180225145551-StudentSubject.js new file mode 100644 index 0000000..7ed5aa1 --- /dev/null +++ b/seeders/20180225145551-StudentSubject.js @@ -0,0 +1,71 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('StudentSubjects', [ + { + score: null, + StudentId : 2, + SubjectId : 1, + createdAt : new Date(), + updatedAt : new Date() + }, + { + score: null, + StudentId : 2, + SubjectId : 2, + createdAt : new Date(), + updatedAt : new Date() + }, + { + score: null, + StudentId : 3, + SubjectId : 2, + createdAt : new Date(), + updatedAt : new Date() + }, + { + score: null, + StudentId : 4, + SubjectId : 1, + createdAt : new Date(), + updatedAt : new Date() + }, + { + score: null, + StudentId : 5, + SubjectId : 1, + createdAt : new Date(), + updatedAt : new Date() + }, + { + score: null, + StudentId : 5, + SubjectId : 2, + createdAt : new Date(), + updatedAt : new Date() + } + ]) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + return queryInterface.bulkDelete('StudentSubjects', {where:{}}) + } +}; diff --git a/views/form.ejs b/views/form.ejs new file mode 100644 index 0000000..3453ac2 --- /dev/null +++ b/views/form.ejs @@ -0,0 +1,78 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+ <% if (err) { %> +

Subject has to be alphabets

+

<%=err.message%>

+ <% } %> +
+ + <% if (path === "students" || path === "teachers") { %> +
+ First Name:
+
+
+ Last Name:
+
+
+ email:
+
+
+ +
+ <% } else { %> +
+ Subject Name:
+
+
+ +
+ <% } %> + + + +
+ +
+
+ + + + + diff --git a/views/formEdit.ejs b/views/formEdit.ejs new file mode 100644 index 0000000..4e34e7b --- /dev/null +++ b/views/formEdit.ejs @@ -0,0 +1,71 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+ <% if (err) { %> +

Subject has to be alphabets

+

<%=err.message%>

+ <% } %> +
+
+ <% if (path === "students" || path === "teachers") { %> + First Name:
+
+
+ Last Name:
+
+
+ email:
+
+
+ <% } else { %> + Subject Name:
+
+
+ <% } %> + +
+
+ +
+
+ + + + + diff --git a/views/home.ejs b/views/home.ejs new file mode 100644 index 0000000..7cfb61b --- /dev/null +++ b/views/home.ejs @@ -0,0 +1,47 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+
+
+ + + + diff --git a/views/index.js b/views/index.js new file mode 100644 index 0000000..a88c723 --- /dev/null +++ b/views/index.js @@ -0,0 +1,108 @@ +'use strict' +const express = require('express'); + + +class View { + constructor() { + + } + + static displayAddData(newData){ + console.log(newData.dataValues); + } + + static displayOneFound(oneFound){ + console.log(oneFound.dataValues); + } + + static displayManyFound(manyFound){ + console.log(manyFound.dataValues); + } + + static displayUpdate(updatedData){ + console.log(updatedData.dataValues); + } + + static displayDestroyed(destroyedData){ + console.log(destroyedData.dataValues); + } + + //display table + static displayTable(res, foundDatas, tableName, newData, method) { + let props = Object.getOwnPropertyNames(foundDatas[0].dataValues); + let path = tableName.toLowerCase(); + res.render('table.ejs', { + title: tableName, + h1: tableName, + heads: props, + foundDatas: foundDatas, + newData: newData, + method: method, + path: path + }) + } + + static displayStudentTable(res, foundDatas, tableName, newData, method) { + let props = Object.getOwnPropertyNames(foundDatas[0].dataValues); + let path = tableName.toLowerCase(); + res.render('./students_view/tableStudent.ejs', { + title: tableName, + h1: tableName, + heads: props, + foundDatas: foundDatas, + newData: newData, + method: method, + path: path + }) + } + + static displayTeacherTable(res, foundDatas, tableName, newData, method) { + let props = Object.getOwnPropertyNames(foundDatas[0].dataValues); + let path = tableName.toLowerCase(); + res.render('./teachers_view/tableTeacher.ejs', { + title: tableName, + h1: tableName, + heads: props, + foundDatas: foundDatas, + newData: newData, + method: method, + path: path + }) + } + + static displaySubjectTable(res, foundDatas, tableName, newData, method) { + let props = Object.getOwnPropertyNames(foundDatas[0].dataValues); + let path = tableName.toLowerCase(); + res.render('./subjects_view/tableSubject.ejs', { + title: tableName, + h1: tableName, + heads: props, + foundDatas: foundDatas, + newData: newData, + method: method, + path: path + }) + } + + static displayEnrolledStudents(res, foundSubject, tableName, subjectId){ + let path = tableName.toLowerCase() + console.log(foundSubject); + let params = { + title: tableName, + foundDatas: foundSubject.Students, + StudentSubjects: foundSubject.StudentSubjects, + subject_name:foundSubject.subject_name, + path: path, + subjectId:subjectId + } + res.render('./subjects_view/subjectStudentsList.ejs', params) + } + + + static redirect(res, route){ + res.redirect(route); + } + +} + +module.exports = View; diff --git a/views/students_view/formAddSubject.ejs b/views/students_view/formAddSubject.ejs new file mode 100644 index 0000000..c994a74 --- /dev/null +++ b/views/students_view/formAddSubject.ejs @@ -0,0 +1,75 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+
+
+ + + + + + + + + + + + + + + +
First Name<%= foundStudent.first_name %>
Last Name<%= foundStudent.last_name %>
Email<%= foundStudent.email %>
+
+ Select Subject:
+
+
+ +
+
+ +
+
+ + + + + diff --git a/views/students_view/tableStudent.ejs b/views/students_view/tableStudent.ejs new file mode 100644 index 0000000..50660b3 --- /dev/null +++ b/views/students_view/tableStudent.ejs @@ -0,0 +1,93 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+ +
+ + + + + + + + + + + + + + + + + <% for (let i = 0; i < foundDatas.length; i++) { %> + + + + + + + + + + + + + <% } %> +
NoIDNameemailSubjectsActionsOptions
<%= i+1 %><%= foundDatas[i].id %><%= foundDatas[i].fullName() %><%= foundDatas[i].email %> +
    + <% if (foundDatas[i].Subjects.length < 1) { %> +
  • Unassigned
  • + <% } else { %> + <% for (let j = 0; j < foundDatas[i].Subjects.length; j++) { %> +
  • <%= foundDatas[i].Subjects[j].subject_name %>
  • + <% } %> + <% } %> +
+
Add Subject edit + /delete
+
+
+ + + + diff --git a/views/subjects_view/formGiveScore.ejs b/views/subjects_view/formGiveScore.ejs new file mode 100644 index 0000000..c0740ec --- /dev/null +++ b/views/subjects_view/formGiveScore.ejs @@ -0,0 +1,53 @@ + + + + Scoring + + + + +
+
+

Give <%= foundStudent.fullName() %> Score

+
+
+ Score:
+
+
+ +
+ +
+
+
+ + + diff --git a/views/subjects_view/subjectStudentsList.ejs b/views/subjects_view/subjectStudentsList.ejs new file mode 100644 index 0000000..d49a6e2 --- /dev/null +++ b/views/subjects_view/subjectStudentsList.ejs @@ -0,0 +1,68 @@ + + + + <%= title %> + + + + +
+
+

<%= subject_name %>

+
+ Return +
+ + + + + + + + <% console.log(foundDatas[0]) %> + <% for (let i = 0; i < foundDatas.length; i++) { %> + + + + <% if (StudentSubjects[i].score === null){ %> + + <% } else { %> + + <% } %> + + <% } %> +
NoStudent NameScore
<%= i+1 %><%= foundDatas[i].fullName() %>Give Score<%= StudentSubjects[i].score %>
+
+
+ + + diff --git a/views/subjects_view/tableSubject.ejs b/views/subjects_view/tableSubject.ejs new file mode 100644 index 0000000..1f4b82e --- /dev/null +++ b/views/subjects_view/tableSubject.ejs @@ -0,0 +1,87 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+
+ + + + + + + + + + + + + + + + <% for (let i = 0; i < foundDatas.length; i++) { %> + + + + + + + + + + + + + <% } %> +
NoIDSubjectTeachersStudentsActions
<%= i+1 %><%= foundDatas[i].id %><%= foundDatas[i].dataValues['Subject Name'] %> +
    + <% for (let j = 0; j < foundDatas[i].Teachers.length; j++) { %> +
  1. <%= foundDatas[i].Teachers[j].fullName() %>
  2. + <% } %> +
+
Enrolled Students edit + /delete
+
+
+ + + + diff --git a/views/table.ejs b/views/table.ejs new file mode 100644 index 0000000..5cc8fec --- /dev/null +++ b/views/table.ejs @@ -0,0 +1,80 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+ <% if (newData) { %> + <% let info = `${method} ${newData.first_name} ${newData.last_name} ${newData.email}` %> +

<%= info %>

+ <% } %> +
+ + + + + + + + <% for (let i = 0; i < heads.length; i++) { %> + + <% } %> + + + + <% for (let i = 0; i < foundDatas.length; i++) { %> + + <% let datas = Object.values(foundDatas[i].dataValues) %> + <% for (var j = 0; j < datas.length; j++) { %> + + + <% } %> + + + + <% } %> +
<%= heads[i] %>Actions
<%= datas[j] %> edit + /delete
+
+
+ + + + diff --git a/views/teachers_view/formTeachers.ejs b/views/teachers_view/formTeachers.ejs new file mode 100644 index 0000000..58feeb6 --- /dev/null +++ b/views/teachers_view/formTeachers.ejs @@ -0,0 +1,73 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+
+ <% if (path === "students" || path === "teachers") { %> +
+ First Name:
+
+
+ Last Name:
+
+
+ email:
+
+
+ +
+ <% } else { %> +
+ Subject Name:
+
+
+ +
+ <% } %> + + + +
+ +
+
+ + + + + diff --git a/views/teachers_view/tableTeacher.ejs b/views/teachers_view/tableTeacher.ejs new file mode 100644 index 0000000..fba3e75 --- /dev/null +++ b/views/teachers_view/tableTeacher.ejs @@ -0,0 +1,84 @@ + + + + <%= title %> + + + + +
+
+

<%= h1 %>

+
+ + + + + + + + + + + + + + + + <% console.log(foundDatas[0].Subject.dataValues['Subject Name']) %> + <% for (let i = 0; i < foundDatas.length; i++) { %> + + + + + + + <% if (foundDatas[i].Subject.dataValues['Subject Name']) { %> + + <% } else { %> + + <% } %> + + + + <% } %> +
NoIDNameemailSubjectActions
<%= i+1 %><%= foundDatas[i].id %><%= foundDatas[i].fullName() %><%= foundDatas[i].email %><%= foundDatas[i].Subject.dataValues['Subject Name'] %>Unassigned edit + /delete
+
+
+ + + +