'update'
[qomet.git] / public / javascripts / course.js
index 8064eaf..6320538 100644 (file)
@@ -1,45 +1,64 @@
-// TODO: YAML format for questions, parsed from text (nested questions)
-// Then yaml parsed to json --> array of indexed questions
-// Use open mode for question banks: add setting "nbQuestions" to show nbQuestions
-// at random among active questions
+/*Draft format (compiled to json)
+ * TODO: separate questions and answers in Evaluation object
+
+<some html question (or/+ exercise intro)>
+
+       <some html subQuestion>
+       * some answer [trigger input/index in answers]
+
+       <another subquestion>
+
+               <sub-subQuestion>
+               + choix1
+               - choix 2
+               + choix 3
+               - choix4
+
+               <another sub sub> with params interpolation £ (tout simplement)
+               / params: javascript parameter generator (another function, body only)
+               * answer 2 (which can
+               be on
+               several lines)
+
+<Some second question>
+* With answer
+
+       dans le cas de parametetrized, answer est une fonction javascript !! qui prend en arg le(s) param(s)
+       coté serveur on stock parameterized question + body func
+       une fois côté client, extra work first to 1) execute each func 2) replace (and store!!!) all params
+https://stackoverflow.com/questions/7650071/is-there-a-way-to-create-a-function-from-a-string-with-javascript
+
+       */
 
 new Vue({
        el: '#course',
        data: {
-               display: "assessments", //or "students", or "grades" (admin mode)
+               display: "evaluations", //or "students" (in admin mode)
                course: course,
-               mode: "view", //or "edit" (some assessment)
-               // assessment data:
                monitorPwd: "",
-               newAssessment: { name: "" },
-               assessmentArray: assessmentArray,
-               assessmentIndex: 0, //current edited assessment index
-               assessment: { }, //copy of assessment at editing index in array
-               assessmentText: "", //questions in an assessment, in text format
-               // grades data:
-               settings: {
-                       totalPoints: 20,
-                       halfPoints: false,
-                       zeroSum: false,
-               },
-               group: 1, //for detailed grades tables
-               grades: { }, //computed
+               newEvaluation: { name: "" },
+               evaluationArray: evaluationArray,
+               mode: "view", //or "edit" (some evaluation)
+               evaluationIndex: 0, //current edited evaluation index
+               evaluation: { }, //copy of evaluation at editing index in array
+               questionsText: "", //questions in an evaluation, in text format
        },
        mounted: function() {
+               
+               
+               
                $('.modal').each( (i,elem) => {
-                       if (elem.id != "assessmentEdit")
+                       if (elem.id != "evaluationEdit")
                                $(elem).modal();
                });
-               $('ul.tabs').tabs();
-               $('#assessmentEdit').modal({
+               $('ul.tabs').tabs(); //--> migrate to grade.js
+               
+               
+               
+               $('#evaluationEdit').modal({
                        complete: () => {
-                               this.parseAssessment();
-                               Vue.nextTick( () => {
-                                       $("#questionList").find("code[class^=language-]").each( (i,elem) => {
-                                               Prism.highlightElement(elem);
-                                       });
-                                       MathJax.Hub.Queue(["Typeset",MathJax.Hub,"questionList"]);
-                               });
+                               this.parseEvaluation();
+                               Vue.nextTick(statementsLibsRefresh);
                        },
                });
        },
@@ -79,8 +98,8 @@ new Vue({
                                                        d.number = d.number.toString();
                                                students.push(d);
                                        });
-                                       $.ajax("/import/students", {
-                                               method: "POST",
+                                       $.ajax("/courses/student-list", {
+                                               method: "PUT",
                                                data: {
                                                        cid: this.course._id,
                                                        students: JSON.stringify(students),
@@ -96,29 +115,29 @@ new Vue({
                                },
                        });
                },
-               // ASSESSMENT:
-               addAssessment: function() {
+               // evaluation:
+               addEvaluation: function() {
                        if (!admin)
                                return;
                        // modal, fill code and description
-                       let error = Validator.checkObject(this.newAssessment, "Assessment");
+                       let error = Validator.checkObject(this.newEvaluation, "Evaluation");
                        if (!!error)
                                return alert(error);
                        else
-                               $('#newAssessment').modal('close');
-                       $.ajax("/add/assessment",
+                               $('#newEvaluation').modal('close');
+                       $.ajax("/evaluations",
                                {
-                                       method: "GET",
+                                       method: "POST",
                                        data: {
-                                               name: this.newAssessment.name,
+                                               name: this.newEvaluation.name,
                                                cid: course._id,
                                        },
                                        dataType: "json",
                                        success: res => {
                                                if (!res.errmsg)
                                                {
-                                                       this.newAssessment["name"] = "";
-                                                       this.assessmentArray.push(res);
+                                                       this.newEvaluation["name"] = "";
+                                                       this.evaluationArray.push(res);
                                                }
                                                else
                                                        alert(res.errmsg);
@@ -130,15 +149,15 @@ new Vue({
                        $("#" + id).modal("open");
                        Materialize.updateTextFields(); //textareas, time field...
                },
-               updateAssessment: function() {
-                       $.ajax("/update/assessment", {
-                               method: "POST",
-                               data: {assessment: JSON.stringify(this.assessment)},
+               updateEvaluation: function() {
+                       $.ajax("/evaluations", {
+                               method: "PUT",
+                               data: {evaluation: JSON.stringify(this.evaluation)},
                                dataType: "json",
                                success: res => {
                                        if (!res.errmsg)
                                        {
-                                               this.assessmentArray[this.assessmentIndex] = this.assessment;
+                                               this.evaluationArray[this.evaluationIndex] = this.evaluation;
                                                this.mode = "view";
                                        }
                                        else
@@ -146,20 +165,20 @@ new Vue({
                                },
                        });
                },
-               deleteAssessment: function(assessment) {
+               deleteEvaluation: function(evaluation) {
                        if (!admin)
                                return;
-                       if (confirm("Delete assessment '" + assessment.name + "' ?"))
+                       if (confirm("Delete evaluation '" + evaluation.name + "' ?"))
                        {
-                               $.ajax("/remove/assessment",
+                               $.ajax("/evaluations",
                                        {
-                                               method: "GET",
-                                               data: { qid: this.assessment._id },
+                                               method: "DELETE",
+                                               data: { qid: this.evaluation._id },
                                                dataType: "json",
                                                success: res => {
                                                        if (!res.errmsg)
-                                                               this.assessmentArray.splice( this.assessmentArray.findIndex( item => {
-                                                                       return item._id == assessment._id;
+                                                               this.evaluationArray.splice( this.evaluationArray.findIndex( item => {
+                                                                       return item._id == evaluation._id;
                                                                }), 1 );
                                                        else
                                                                alert(res.errmsg);
@@ -169,16 +188,16 @@ new Vue({
                        }
                },
                toggleState: function(questionIndex) {
-                       // add or remove from activeSet of current assessment
-                       let activeIndex = this.assessment.activeSet.findIndex( item => { return item == questionIndex; });
+                       // add or remove from activeSet of current evaluation
+                       let activeIndex = this.evaluation.activeSet.findIndex( item => { return item == questionIndex; });
                        if (activeIndex >= 0)
-                               this.assessment.activeSet.splice(activeIndex, 1);
+                               this.evaluation.activeSet.splice(activeIndex, 1);
                        else
-                               this.assessment.activeSet.push(questionIndex);
+                               this.evaluation.activeSet.push(questionIndex);
                },
-               setAssessmentText: function() {
+               setEvaluationText: function() {
                        let txt = "";
-                       this.assessment.questions.forEach( q => {
+                       this.evaluation.questions.forEach( q => {
                                txt += q.wording; //already ended by \n
                                q.options.forEach( (o,i) => {
                                        let symbol = q.answer.includes(i) ? "+" : "-";
@@ -186,11 +205,11 @@ new Vue({
                                });
                                txt += "\n"; //separate questions by new line
                        });
-                       this.assessmentText = txt;
+                       this.questionsText = txt;
                },
-               parseAssessment: function() {
+               parseEvaluation: function() {
                        let questions = [ ];
-                       let lines = this.assessmentText.split("\n").map( L => { return L.trim(); })
+                       let lines = this.questionsText.split("\n").map( L => { return L.trim(); })
                        lines.push(""); //easier parsing
                        let emptyQuestion = () => {
                                return {
@@ -227,37 +246,32 @@ new Vue({
                                        }
                                }
                        });
-                       this.assessment.questions = questions;
+                       this.evaluation.questions = questions;
                },
-               actionAssessment: function(index) {
+               actionEvaluation: function(index) {
                        if (admin)
                        {
                                // Edit screen
-                               this.assessmentIndex = index;
-                               this.assessment = $.extend(true, {}, this.assessmentArray[index]);
-                               this.setAssessmentText();
+                               this.evaluationIndex = index;
+                               this.evaluation = $.extend(true, {}, this.evaluationArray[index]);
+                               this.setEvaluationText();
                                this.mode = "edit";
-                               Vue.nextTick( () => {
-                                       $("#questionList").find("code[class^=language-]").each( (i,elem) => {
-                                               Prism.highlightElement(elem);
-                                       });
-                                       MathJax.Hub.Queue(["Typeset",MathJax.Hub,"questionList"]);
-                               });
+                               Vue.nextTick(statementsLibsRefresh);
                        }
-                       else //external user: show assessment
-                               this.redirect(this.assessmentArray[index].name);
+                       else //external user: show evaluation
+                               this.redirect(this.evaluationArray[index].name);
                },
-               redirect: function(assessmentName) {
-                       document.location.href = "/" + initials + "/" + course.code + "/" + assessmentName;
+               redirect: function(evaluationName) {
+                       document.location.href = "/" + initials + "/" + course.code + "/" + evaluationName;
                },
                setPassword: function() {
                        let hashPwd = Sha1.Compute(this.monitorPwd);
                        let error = Validator.checkObject({password:hashPwd}, "Course");
                        if (error.length > 0)
                                return alert(error);
-                       $.ajax("/set/password",
+                       $.ajax("/courses/password",
                                {
-                                       method: "GET",
+                                       method: "PUT",
                                        data: {
                                                cid: this.course._id,
                                                pwd: hashPwd,
@@ -273,79 +287,11 @@ new Vue({
                        );
                },
                // NOTE: artifact required for Vue v-model to behave well
-               checkBoxFixedId: function(i) {
+               checkboxFixedId: function(i) {
                        return "questionFixed" + i;
                },
-               checkBoxActiveId: function(i) {
+               checkboxActiveId: function(i) {
                        return "questionActive" + i;
                },
-               // GRADES:
-               gradeSettings: function() {
-                       $("#gradeSettings").modal("open");
-                       Materialize.updateTextFields(); //total points field in grade settings overlap
-               },
-               download: function() {
-                       // Download (all) grades as a CSV file
-                       let data = [ ];
-                       this.studentList(0).forEach( s => {
-                               let finalGrade = 0.;
-                               let gradesCount = 0;
-                               if (!!this.grades[s.number])
-                               {
-                                       Object.keys(this.grades[s.number]).forEach( assessmentName => {
-                                               s[assessmentName] = this.grades[s.number][assessmentName];
-                                               if (_.isNumeric(s[assessmentName]) && !isNaN(s[assessmentName]))
-                                               {
-                                                       finalGrade += s[assessmentName];
-                                                       gradesCount++;
-                                               }
-                                               if (gradesCount >= 1)
-                                                       finalGrade /= gradesCount;
-                                               s["final"] = finalGrade; //TODO: forbid "final" as assessment name
-                                       });
-                               }
-                               data.push(s); //number,name,group,assessName1...assessNameN,final
-                       });
-                       let csv = Papa.unparse(data, {
-                               quotes: true,
-                               header: true,
-                       });
-                       let downloadAnchor = $("#download");
-                       downloadAnchor.attr("download", this.course.code + "_results.csv");
-                       downloadAnchor.attr("href", "data:text/plain;charset=utf-8," + encodeURIComponent(csv));
-                       this.$refs.download.click()
-                       //downloadAnchor.click(); //fails
-               },
-               showDetails: function(group) {
-                       this.group = group;
-                       $("#detailedGrades").modal("open");
-               },
-               groupList: function() {
-                       let maxGrp = 1;
-                       this.course.students.forEach( s => {
-                               if (s.group > maxGrp)
-                                       maxGrp = s.group;
-                       });
-                       return _.range(1,maxGrp+1);
-               },
-               grade: function(assessmentIndex, studentNumber) {
-                       if (!this.grades[assessmentIndex] || !this.grades[assessmentIndex][studentNumber])
-                               return ""; //no grade yet
-                       return this.grades[assessmentIndex][studentNumber];
-               },
-               groupId: function(group, prefix) {
-                       return (prefix || "") + "group" + group;
-               },
-               togglePresence: function(number, index) {
-                       // UNIMPLEMENTED
-                       // TODO: if no grade (thus automatic 0), toggle "exempt" state on student for current exam
-                       // --> automatic update of grades view (just a few number to change)
-               },
-               computeGrades: function() {
-                       // UNIMPLEMENTED
-                       // TODO: compute all grades using settings (points, coefficients, bonus/malus...).
-                       // If some questions with free answers (open), display answers and ask teacher action.
-                       // TODO: need a setting for that too (by student, by exercice, by question)
-               },
        },
 });