From ed34b69b64004524154a779dc409fe44f824a5b6 Mon Sep 17 00:00:00 2001 From: flifloo Date: Wed, 20 Jan 2021 17:14:33 +0100 Subject: [PATCH] Finish teacher marks page --- app.js | 26 ++++-- models/group.js | 16 +++- models/semester.js | 2 +- models/user.js | 2 - .../{marks.js => marks-student.js} | 0 public/javascripts/marks-teacher.js | 56 +++++++++++ sass/style.sass | 9 +- sockets/get/evaluationGet.js | 7 +- sockets/get/gradeGet.js | 4 +- sockets/get/studentGet.js | 23 +++++ sockets/index.js | 5 +- sockets/set/gradeSet.js | 19 ++++ views/pages/marks.pug | 93 ++++--------------- views/template/layout.pug | 4 +- views/template/navbar.pug | 11 ++- 15 files changed, 168 insertions(+), 109 deletions(-) rename public/javascripts/{marks.js => marks-student.js} (100%) create mode 100644 public/javascripts/marks-teacher.js create mode 100644 sockets/get/studentGet.js create mode 100644 sockets/set/gradeSet.js diff --git a/app.js b/app.js index 3b56354..9762f6f 100644 --- a/app.js +++ b/app.js @@ -1,12 +1,13 @@ -let express = require("express"); -let path = require("path"); -let cookieParser = require("cookie-parser"); -let logger = require("morgan"); +const express = require("express"); +const path = require("path"); +const cookieParser = require("cookie-parser"); +const logger = require("morgan"); const session = require("express-session"); const error = require("./routes/utils/error"); -let config = process.env.NODE_ENV === "test" ? {} : require("./config/config.json"); +const config = process.env.NODE_ENV === "test" ? {} : require("./config/config.json"); +const models = require("./models"); -let indexRouter = require("./routes/index"); +const indexRouter = require("./routes/index"); const loginRouter = require("./routes/login"); const edtRouter = require("./routes/edt"); const marksRouter = require("./routes/marks"); @@ -16,7 +17,9 @@ const profilRouter = require("./routes/profil"); let app = express(); const sessionMiddleware = session({ - secret: process.env.NODE_ENV === "test" ? "Keyboard Cat" : config.secret + secret: process.env.NODE_ENV === "test" ? "Keyboard Cat" : config.secret, + resave: false, + saveUninitialized: true }); // view engine setup @@ -31,7 +34,14 @@ app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, "public"))); app.use(sessionMiddleware); -app.use((req, res, next) => { +app.use(async (req, res, next) => { + if (req.session.user) { + let user = await models.User.findByPk(req.session.user.email, {include: {model: models.Group, include: models.Semester}}); + if (user.updatedAt !== req.session.user.updatedAt) { + req.session.user = user; + req.session.save(); + } + } res.locals.session = req.session; next(); }); diff --git a/models/group.js b/models/group.js index d9a2cf7..577a900 100644 --- a/models/group.js +++ b/models/group.js @@ -5,19 +5,27 @@ const { Model } = require("sequelize"); module.exports = (sequelize, DataTypes) => { class Group extends Model { static associate(models) { - Group.belongsTo(models.Semester); + Group.belongsTo(models.Semester, {foreignKey: {allowNull: false}}); Group.belongsToMany(models.User, {through: "UserGroup"}); Group.belongsToMany(models.Event, {through: "EventGroup"}); } } - Group.init({ + return Group.init({ number: { type: DataTypes.STRING, allowNull: false + }, + displayName: { + type: DataTypes.VIRTUAL, + get() { + if (this.number.startsWith("G")) + return this.number + this.Semester.name; + else + return this.Semester.name + " " + this.number + } } }, { sequelize, - modelName: "Group", + modelName: "Group" }); - return Group; }; diff --git a/models/semester.js b/models/semester.js index fac1dad..5f50e0b 100644 --- a/models/semester.js +++ b/models/semester.js @@ -5,7 +5,7 @@ const { Model } = require("sequelize"); module.exports = (sequelize, DataTypes) => { class Semester extends Model { static associate(models) { - Semester.hasMany(models.Group); + Semester.hasMany(models.Group, {foreignKey: {allowNull: false}}); Semester.belongsToMany(models.Event, {through: "EventSemester"}); } } diff --git a/models/user.js b/models/user.js index 0eacb8f..11901ae 100644 --- a/models/user.js +++ b/models/user.js @@ -22,8 +22,6 @@ module.exports = (sequelize, DataTypes) => { User.belongsToMany(models.Event, {through: "EventTeacher"}); User.belongsToMany(models.Evaluation, {through: "EvaluationTeacher"}); User.belongsToMany(models.UE, {through: "UEUser"}); - //User.hasMany(models.Grade, {as : "TeacherGrade"}); - //User.hasMany(models.Grade, {as: "StudentGrade"}); } checkPassword(password) { diff --git a/public/javascripts/marks.js b/public/javascripts/marks-student.js similarity index 100% rename from public/javascripts/marks.js rename to public/javascripts/marks-student.js diff --git a/public/javascripts/marks-teacher.js b/public/javascripts/marks-teacher.js new file mode 100644 index 0000000..18daa4f --- /dev/null +++ b/public/javascripts/marks-teacher.js @@ -0,0 +1,56 @@ +const socket = io.connect(); +const group = document.getElementById("group"); +const evaluation = document.getElementById("evaluation"); +const marksform = document.getElementById("marksform"); +const markstable = document.getElementById("markstable").querySelector("tbody"); +const studentTemplate = document.getElementById("studentTemplate"); + +let evaluations = {}; +let students = []; + +group.addEventListener("change", () => socket.emit("evaluationGet")); + +socket.on("evaluationGet", evals => { + evaluations = {}; + evaluation.innerHTML = ""; + for (let ev of evals) { + if (!document.getElementById("UE"+ev.UE.id)) { + evaluation.insertAdjacentHTML("beforeend", ``) + } + document.getElementById("UE"+ev.UE.id).insertAdjacentHTML("beforeend", ``); + evaluations[ev.id] = ev; + } + M.FormSelect.init(evaluation); +}); + +evaluation.addEventListener("change", () => { + marksform.querySelector(".evaluationName").innerHTML = evaluations[evaluation.value].UE.name + " - " + evaluations[evaluation.value].name; + socket.emit("studentGet", group.value); +}); + +socket.on("studentGet", sts => { + markstable.querySelectorAll("tr:not(.studentTemplate)").forEach(el => el.remove()); + for (let st of sts) { + let el = studentTemplate.cloneNode(true); + el.style = ""; + el.id = "Student"+st.email; + el.querySelector(".studentName").innerHTML = st.firstName + " " + st.lastName; + + let gs = el.querySelector(".gradeScore"); + gs.name = "score"+st.email; + let g = evaluations[evaluation.value].Grades.find(s => s.StudentGradeEmail === st.email); + if (g) + gs.value = g.score; + + students.push(st); + markstable.insertAdjacentElement("beforeend", el); + } +}); + +marksform.addEventListener("submit", e => { + e.preventDefault(); + let grds = {}; + for (let e of new FormData(marksform)) + grds[e[0].replace(/^score/i, "")] = e[1]; + socket.emit("gradeSet", {evaluation: evaluations[evaluation.value].id, grades: grds}); +}); diff --git a/sass/style.sass b/sass/style.sass index 3b7b30c..b3f1326 100644 --- a/sass/style.sass +++ b/sass/style.sass @@ -484,13 +484,8 @@ div#visible + div #hamburger position: fixed - -#notvisible - display: none - -#marksform - display: none - + top: 0 + left: 0 .grades border: 2px solid white height: 202px diff --git a/sockets/get/evaluationGet.js b/sockets/get/evaluationGet.js index 55c3beb..df6e5ac 100644 --- a/sockets/get/evaluationGet.js +++ b/sockets/get/evaluationGet.js @@ -6,7 +6,8 @@ module.exports = socket => { include: [models.UE, {model: models.User}, { model: models.Grade, - include: [{model: models.User, as: "TeacherGrade"}, {model: models.User, as: "StudentGrade"}] + include: [{attributes: ["email", "firstName", "lastName"], model: models.User, as: "TeacherGrade"}, + {attributes: ["email", "firstName", "lastName"], model: models.User, as: "StudentGrade"}] }] }; @@ -14,8 +15,8 @@ module.exports = socket => { options.where.id = data.id; if (socket.request.session.user.permissions === 2) { - options.include[1].where = {email: socket.request.session.user.email}; - options.include[1].required = true; + options.include[0].through = {where: {UserEmail: socket.request.session.user.email}}; + options.include[0].required = true; } socket.emit("evaluationGet", await models.Evaluation.findAll(options)); } diff --git a/sockets/get/gradeGet.js b/sockets/get/gradeGet.js index b61dbb9..ab01e00 100644 --- a/sockets/get/gradeGet.js +++ b/sockets/get/gradeGet.js @@ -3,8 +3,8 @@ const models = require("../../models"); module.exports = socket => { return async (data) => { const options = {where: {}, include: [{model: models.Evaluation, include: {model: models.UE}}, - {model: models.User, as: "TeacherGrade"}, - {model: models.User, as: "StudentGrade"}]}; + {attributes: ["email", "firstName", "lastName"], model: models.User, as: "TeacherGrade"}, + {attributes: ["email", "firstName", "lastName"], model: models.User, as: "StudentGrade", include: {model: models.Group, include: models.Semester}}]}; if (data && data.id) options.where.id = data.id; diff --git a/sockets/get/studentGet.js b/sockets/get/studentGet.js new file mode 100644 index 0000000..8a81573 --- /dev/null +++ b/sockets/get/studentGet.js @@ -0,0 +1,23 @@ +const models = require("../../models"); + +module.exports = socket => { + return async (data) => { + let options = { + attributes: ["email", "firstName", "lastName"], + where: {permissions: 1}, + include: [{model: models.Group, include: models.Semester}] + }; + if (data && data.email) + options.where.email = data.email; + if (data && data.firstName && data.lastName) { + options.where.firstName = data.firstName; + options.where.lastName = data.lastName; + } + if (data && data.group) { + options.include[0].where = {id: data.group}; + options.include[0].required = true; + } + + socket.emit("studentGet", await models.User.findAll(options)); + } +}; diff --git a/sockets/index.js b/sockets/index.js index fb53df2..028605b 100644 --- a/sockets/index.js +++ b/sockets/index.js @@ -11,8 +11,11 @@ module.exports = socket => { socket.on("logout", require("./logout")(socket)); socket.on("agendaGet", require("./get/agendaGet")(socket)); socket.on("gradeGet", require("./get/gradeGet")(socket)); - if (socket.request.session.user.permissions > 1) + if (socket.request.session.user.permissions > 1) { socket.on("evaluationGet", require("./get/evaluationGet")(socket)); + socket.on("gradeSet", require("./set/gradeSet")(socket)); + socket.on("studentGet", require("./get/studentGet")(socket)); + } if (socket.request.session.user.permissions > 2) { socket.on("groupGet", require("./get/groupGet")(socket)); socket.on("semesterGet", require("./get/semesterGet")(socket)); diff --git a/sockets/set/gradeSet.js b/sockets/set/gradeSet.js new file mode 100644 index 0000000..27e7b2b --- /dev/null +++ b/sockets/set/gradeSet.js @@ -0,0 +1,19 @@ +const models = require("../../models"); + +module.exports = socket => { + return async (data) => { + if (!data || !data.evaluation || !data.grades) { + socket.emit("gradeSet", {error: {message: "missing_arguments"}}); + return; + } + for (let student in data.grades) { + let grade = await models.Grade.findOne({where: {StudentGradeEmail: student, EvaluationId: data.evaluation}}); + if (!grade) { + await models.Grade.create({TeacherGradeEmail: socket.request.session.user.email, StudentGradeEmail: student, EvaluationId: data.evaluation, score: data.grades[student], limit: 20}) + } else { + grade.score = data.grades[student]; + await grade.save(); + } + } + } +}; diff --git a/views/pages/marks.pug b/views/pages/marks.pug index d6a4efb..de0beb2 100644 --- a/views/pages/marks.pug +++ b/views/pages/marks.pug @@ -28,86 +28,29 @@ block content div#marksdetailsbackground.invisible + script(src="/javascripts/marks-student.js") - if teacher - div.row - div(class="col s12 m10 offset-m1 marksgroup") - h3 Select a group - div#flexgroup - p(onclick="marksformChange(this.getAttribute('id'))") G1S1 - p(onclick="marksformChange(this.getAttribute('id'))") G2S2 - p(onclick="marksformChange(this.getAttribute('id'))") G3S3 + else + form + label(for="group") Group: + select#group(name="group") + option(selected disabled) + for group in session.user.Groups + option(value=group.id)=group.displayName + label(for="evaluation") + select#evaluation(name="evaluation") + option(selected disabled) form#marksform table#markstable thead tr - th Name - th - input(type="text" value="DS1") - th - input(type="text" placeholder="Add a test") + th Student + th.evaluationName tbody - tr - td Test + tr#studentTemplate(style="display: none") + td.studentName td - input(type="number" value="16") - td - input(type="number") - tr - td Keze - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - tr - td Kezel - td - input(type="number" value="16") - td - input(type="number") - input#marksubmit(type="submit" value="Enregistrer") - - script(src="/javascripts/marks.js") \ No newline at end of file + input.gradeScore(type="number") + input#marksubmit(type="submit" value="Save") + script(src="/javascripts/marks-teacher.js") diff --git a/views/template/layout.pug b/views/template/layout.pug index 0392ab6..a7878dc 100644 --- a/views/template/layout.pug +++ b/views/template/layout.pug @@ -15,8 +15,8 @@ html meta(name="theme-color" content="#ffffff") script(src="/socket.io/socket.io.js") body - - var student = true; - - var teacher = false; + - var student = false; + - var teacher = true; - var admin = false; div(class="row" id="page") block navbar diff --git a/views/template/navbar.pug b/views/template/navbar.pug index 4b0baaa..1e67b42 100644 --- a/views/template/navbar.pug +++ b/views/template/navbar.pug @@ -9,12 +9,11 @@ block navbar span.white-text.name=session.user.firstName + " " + session.user.lastName p if session.user.Groups[session.user.Groups.length-1] - if session.user.Groups[session.user.Groups.length-1].number.startsWith("G") - span.white-text.name=session.user.Groups[session.user.Groups.length-1].number + session.user.Groups[session.user.Groups.length-1].Semester.name - else - span.white-text.name=session.user.Groups[session.user.Groups.length-1].Semester.name + " " + session.user.Groups[session.user.Groups.length-1].number + span.white-text.name=session.user.Groups[session.user.Groups.length-1].displayName p span.white-text.email=session.user.email + a + span.white-text Se déconnecter li a(href="/" class="waves-effect") Home @@ -36,6 +35,8 @@ block navbar span.white-text.name=session.user.firstName + " " + session.user.lastName p(href='#email') span.white-text.email=session.user.email + a + span.white-text Se déconnecter li a(href="/" class="waves-effect") Home li @@ -56,6 +57,8 @@ block navbar span.white-text.name=session.user.firstName + " " + session.user.lastName p(href='#email') span.white-text.email=session.user.email + a + span.white-text Se déconnecter li a(href="/" class="waves-effect") Home li(class="active")