diff --git a/CHANGELOG.md b/CHANGELOG.md index a07b30cd3b9bb904f8cbffed4233cd25dea809ff..ad9e8efe386dfc4fade89e3304faa16630425746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,7 +107,7 @@ Ne pas utiliser de méthodes root, quitte à abandonner des fonctionnalités. Tr [x] L'étudiant ne doit pas pouvoir voir les données d'un autre étudiant (en changeant l'id dans l'url, ni le formulaire pour changer d'étudiant. -[ ] Générer un lien vers la page cpt x users +[x] Générer un lien vers la page cpt x users [ ] Exclure l'enseignant des tableau de bord : ne prendre que les rôles étudiants @@ -129,7 +129,7 @@ Ne pas utiliser de méthodes root, quitte à abandonner des fonctionnalités. Tr [x] Pouvoir changer de compétence via des boutons précédent, suivant -[ ] Générer un lien vers la page cpt x user +[x] Générer un lien vers la page cpt x user [ ] Exclure l'enseignant des tableau de bord : ne prendre que les rôles étudiants @@ -137,6 +137,30 @@ Ne pas utiliser de méthodes root, quitte à abandonner des fonctionnalités. Tr [ ] Récupérer toutes les données (ne marchera sûrement pas) +__Récupérer les données de base :__ +[x] Nom de l'étudiant +[x] Nom et description de la compétence +[x] Nom et description des parents et du référentiel en chemin avec des petits liens clicables qui lèvent des petites popup avec la description. +[x] Proficiency +[x] Info évaluation demandée (review) +[x] Evaluer un étudiant avec : évaluation, commentaire d'évaluation +[x] Lever une éventuelle demande d'évaluation (review) quand on évalue +[ ] Demande et annulation de demande d'évaluation (par l'étudiant) +[ ] Historique d'évaluation en liste : essayer de récupérer l'exporteur de moodle +[ ] Historique d'évaluation en graphique +[x] Liste des modules de cours liés à l'activité avec lien vers l'activité +[ ] Etat d'achèvement du module de cours (attention de vérifier si achèvement activé à tous les niv) + +[ ] Formulaire de changement d'étudiant avec les boutons précédent et suivant +[ ] Formulaire de changement de compétence avec les boutons précédent et suivant + +[x] Message d'erreur si l'étudiant demandé n'appartient pas au cours +[x] Redirection si un étudiant essaie d'accéder à la page d'un autre étudiant + +### Page par activité + +Créer une page qui permet d'évaluer les compétences en lien avec une activité particulière ? Ou de lister l'acquisition des compétences pour cette activité ? + ### Block en lui-même Changement de l'ordre et de l'apparence des boutons. diff --git a/competency_iena_competencies_2.php b/competency_iena_competencies_2.php index ff6adffd6500a2fbee3a152aaacf5589473d839e..9c5d6609baaa25e9f6c94698ac2b44eeb1d56f1b 100644 --- a/competency_iena_competencies_2.php +++ b/competency_iena_competencies_2.php @@ -133,7 +133,7 @@ if ($count_course_cpts === 0) { $proficient_class = $user_course_competency->get('proficiency') == 1 ? " list-group-item-success" : ""; $proficient_str = $user_course_competency->get('proficiency') == 1 ? "Oui" : "Non"; echo " - <a href='#?courseid={$courseid}&studentid={$studentid}&competencyid={$cpt->get('id')}' class='list-group-item list-group-item-action{$proficient_class}'> + <a href='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$cpt->get('id')}' class='list-group-item list-group-item-action{$proficient_class}'> <div class='d-flex w-100 justify-content-between'> <h3 class='mb-1 iena-cpt-action-title'>{$cpt->get('shortname')}</h3>"; foreach ($reviews_data as $review) { diff --git a/competency_iena_competency_students_2.php b/competency_iena_competency_students_2.php index e45217319dde7cb4bec37620c9fa935f0e5d5184..ee988ade172609d0635081b3381c025a5aeca991 100644 --- a/competency_iena_competency_students_2.php +++ b/competency_iena_competency_students_2.php @@ -310,7 +310,7 @@ if (count($course_cpts) === 0) { $grade_d = $cpt_stud->grade == NULL ? "-" : $current_cpt->scale[$cpt_stud->grade - 1]; $proficiency_d = $cpt_stud->proficiency == 1 ? "Oui" : "Non"; echo " - <a href='#?courseid={$courseid}&studentid={$cpt_stud->id}&competencyid={$current_cpt->id}' class='list-group-item list-group-item-action{$proficient_class}'> + <a href='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$cpt_stud->id}&competencyid={$current_cpt->id}' class='list-group-item list-group-item-action{$proficient_class}'> <div class='d-flex w-100 justify-content-between'> <h3 class='mb-1 iena-cpt-action-title'>{$cpt_stud->firstname} {$cpt_stud->lastname}</h3>"; if ($cpt_stud->review == 1) { diff --git a/course_competency.php b/course_competency.php new file mode 100644 index 0000000000000000000000000000000000000000..6db1262602f9bc73f39de024ac9916d06841d065 --- /dev/null +++ b/course_competency.php @@ -0,0 +1,281 @@ +<?php + +require_once('../../config.php'); + +global $USER, $COURSE; + +$courseid = required_param('courseid', PARAM_INT); +$studentid = required_param('studentid', PARAM_INT); +$competencyid = required_param('competencyid', PARAM_INT); + +$url = new moodle_url('/blocks/competency_iena/course_competency.php', array('courseid' => $courseid, 'studentid' => $studentid, 'competencyid' => $competencyid)); +$PAGE->set_url($url); + +require_login($courseid, false, NULL); + +$PAGE->set_pagelayout('course'); +$PAGE->set_title(get_string('title_plugin', 'block_competency_iena')); +$PAGE->set_heading($OUTPUT->heading($COURSE->fullname, 2, 'headingblock header outline')); +$PAGE->requires->js("/blocks/competency_iena/js/datalist-polyfill.min.js"); +$PAGE->requires->js("/blocks/competency_iena/js/stud-x-cpts.js"); +$PAGE->requires->js("/blocks/competency_iena/js/cpt-x-studs.js"); + +/* <<< GESTION DROITS D'ACCÈS >>> */ + +$context = context_course::instance($courseid); + +/* Check if studentid is a course participant */ +$is_enrolled = is_enrolled($context, $studentid, '', true); + +/* Check if the user is teacher */ +$is_teacher = false; +if (has_capability('moodle/course:update', $context, $USER->id)) { + $is_teacher = true; +} + +/* Redirect student if he try accèss another student data */ +if ( $is_teacher === false && $studentid != $USER->id ) { + $link = $CFG->wwwroot . '/blocks/competency_iena/course_competency.php?courseid=' . $courseid . '&studentid=' . $USER->id . '&competencyid=' . $competencyid; + header("Location: {$link}"); + exit; +} + +echo $OUTPUT->header(); + +/* REVIEW DATA */ +$sql_rev = "SELECT * FROM {competency_usercomp} +WHERE userid = ? AND competencyid = ? AND status = ?"; +$reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]); +$review_asked = count($reviews_data) > 0 ? true : false; + +/* POST EVALUATION */ + +if ( isset($_POST['competencyid']) ) { + $note = "Évaluation donnée pour le cours {$COURSE->fullname} par {$USER->firstname} {$USER->lastname}. " . $_POST['note']; + \core_competency\api::grade_competency_in_course($courseid, $studentid, $competencyid, $_POST['grade'], $note); + if ( $review_asked ) { + \core_competency\api::user_competency_start_review($studentid, $competencyid); + \core_competency\api::user_competency_stop_review($studentid, $competencyid); + /* Refresh review data */ + $reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]); + $review_asked = count($reviews_data) > 0 ? true : false; + } +} + +/* POST REVIEW */ + +if ( isset($_POST['review']) ) { + if ( $_POST['review'] == 'request' ) { + \core_competency\api::user_competency_request_review($studentid, $competencyid); + } elseif ( $_POST['review'] == 'cancel' ) { + \core_competency\api::user_competency_cancel_review_request($studentid, $competencyid); + } + /* Refresh review data */ + $reviews_data = $DB->get_records_sql($sql_rev, [$studentid, $competencyid, 1]); + $review_asked = count($reviews_data) > 0 ? true : false; +} + + +/* HELPERS */ +function _html($el, $str, $class = "") { + $class = " class='" . $class . "'"; + echo "<" . $el . $class . ">" . $str . "</" . $el . ">"; +} + +function _modal_builder($id, $title, $body) { + return "<div class='modal fade' id='{$id}' tabindex='-1' role='dialog' aria-labelledby='exampleModalScrollableTitle' aria-hidden='true'><div class='modal-dialog modal-dialog-scrollable' role='document'><div class='modal-content'><div class='modal-header'><h5 class='modal-title' id='exampleModalScrollableTitle'>{$title}</h5><button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button></div><div class='modal-body'>{$body}</div></div></div></div>"; +} + +/* <<< GESTION ERREUR ACCÈS >>> */ + +if ( $is_enrolled === false ) { + _html("p", "L'étudiant demandé n'est pas inscrit dans ce cours.", "alert alert-warning"); +} + +/* <<< DATA >>> */ + +/* Student USER object */ +$student = user_get_users_by_id([$studentid])[$studentid]; + +/* All students */ +/* Only if is teacher because it's to load stud list to switch : teacher feature */ +$students = NULL; +if ( $is_teacher ) { + $students = get_enrolled_users($context); +} + +/* Course modules linked to this competency */ +$cm_ids = \core_competency\api::list_course_modules_using_competency($competencyid, $courseid); + +/* Competency */ +$u_c_cpt = \core_competency\api::get_user_competency_in_course($courseid, $studentid, $competencyid); +$cpt = new \core_competency\competency($competencyid); +$cpt_scale = $cpt->get_scale()->scale_items; +$eval = "-"; /* current eval string */ +if ( $u_c_cpt->get('grade') != null ) { + $eval = $cpt_scale[$u_c_cpt->get('grade') - 1]; +} +$proficiency = $u_c_cpt->get('proficiency') == 1 ? "Oui" : "Non"; + +/* All course competencies */ +$course_cpts = \core_competency\course_competency::list_competencies($COURSE->id); + +/* <<< PAGE >>> */ + +/*user_competency_request_review($userid, $competencyid)*/ + +echo "<pre>"; +// var_dump($u_c_cpt->get('proficiency')); +// var_dump($course_cpts); +// var_dump($students); +// var_dump($reviews_data); +// var_dump($review_asked); +// var_dump($proficiency); +// var_dump($u_c_cpt->get('grade')); +// var_dump($eval); +// var_dump($cpt_scale); +// // var_dump($cpt); +// var_dump($cpt->get('competencyframeworkid')); +// var_dump($cpt->get('parentid')); + +echo "</pre>"; + +/* STUDENT NAME */ +_html("h2", $student->firstname . " " . $student->lastname); + +/* SWITCH STUDENT FORM */ +if ( $is_teacher && $students != NULL && count($students) != 0 ) { + echo "<form action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php' id='change_stud_form' class='form-inline'>"; + echo "<input type='text' hidden name='courseid' value='{$courseid}'>"; + echo "<input type='text' hidden name='competencyid' value='{$competencyid}'>"; + echo "<span hidden id='studentid'>{$studentid}</span>"; + echo "<label class='m-y-1 m-r-1' for='studentid_sel' style='color: black;'>Etudiant</label>"; + echo "<input type='text' name='studentid' id='studentid_sel' value='' list='student_list' class='form-control m-r-1'>"; + echo "<datalist id='student_list' title='Select student'>"; + foreach ($students as $stud) { + echo "<option value='{$stud->firstname} {$stud->lastname} ({$stud->id})' data-value='{$stud->id}'>{$stud->firstname} {$stud->lastname} ({$stud->id})</option>"; + } + echo "</datalist>"; + echo "<div><button class='btn btn-secondary' id='prevStud'>Précédent</button>"; + echo "<button class='btn btn-secondary m-l-1' id='nextStud'>Suivant</button></div>"; + echo "</form>"; +} + +/* SWITCH COMPETENCY FORM */ +echo "<form action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php' id='change_cpt_form' class='form-inline'>"; +echo "<input type='text' hidden name='courseid' value='{$courseid}'>"; +echo "<input type='text' hidden name='studentid' value='{$studentid}'>"; +echo "<span hidden id='competencyid'>{$competencyid}</span>"; +echo "<label class='m-r-1' for='competencyid_sel' style=''>Changer de compétence</label>"; +echo "<input type='text' name='competencyid' id='competencyid_sel' value='' list='competency_list' class='form-control'>"; +echo "<datalist id='competency_list' title='Select competency'>"; +foreach ($course_cpts as $course_cpt) { + echo "<option value='{$course_cpt->get('shortname')} ({$course_cpt->get('id')})' data-value='{$course_cpt->get('id')}'>{$course_cpt->get('shortname')} ({$course_cpt->get('id')})</option>"; +} +echo "</datalist>"; +echo "<button class='btn btn-secondary m-l-1' id='prevCpt'>Précédent</button>"; +echo "<button class='btn btn-secondary m-l-1' id='nextCpt'>Suivant</button>"; +echo "</form>"; + +/* LINKED MODULES */ +if ( count($cm_ids) !== 0 ) { + $modinfo = get_fast_modinfo($courseid); + _html("h3", "Lié à cette compétence"); + echo "<div class='list-group'>"; + foreach ($cm_ids as $cm_id) { + echo "<a href='{$modinfo->cms[$cm_id]->url->out()}' target='_blank' class='list-group-item list-group-item-action'><img src='$CFG->wwwroot/theme/image.php/boost/{$modinfo->cms[$cm_id]->modname}/1/icon>' style='height: 1.3rem;'><span class='align-middle'> {$modinfo->cms[$cm_id]->name}</span></a>"; + } + echo "</div>"; +} else { + _html("p", "Aucune ressource ou activité n'est liée à cette compétence dans ce cours. ", "alert alert-secondary"); +} + +/* INFO ABOUT COMPETENCIES, FRAMEWORK AND CURRENT GRADE */ + +echo "<div class='alert alert-secondary'>"; /* for competency info and grade info */ +_html('h2', $cpt->get('shortname')); +/* Competency tree parents path from current to framework */ +$cptid = $competencyid; +$parent_cpts = array(); +while ($cptid > 0) { + $tmp_cpt = new \core_competency\competency($cptid); + array_unshift($parent_cpts, ['id' => $tmp_cpt->get('id'), 'shortname' => $tmp_cpt->get('shortname'), 'description' => $tmp_cpt->get('description')]); + $cptid = $tmp_cpt->get('parentid'); +} +/* Framework infos */ +$cpt_path_link = "<a href='#' data-toggle='modal' data-target='#modalref'>{$cpt->get_framework()->get('shortname')}</a>" . _modal_builder('modalref', $cpt->get_framework()->get('shortname'), $cpt->get_framework()->get('description')); +/* Each competency info */ +foreach ($parent_cpts as $parent_cpt) { + $cpt_path_link .= " / <a href='#' data-toggle='modal' data-target='#modal{$parent_cpt['id']}'>{$parent_cpt['shortname']}</a>" . _modal_builder("modal{$parent_cpt['id']}", $parent_cpt['shortname'], $parent_cpt['description']); +} +echo "<div style='margin-bottom: 0.7rem;'>" . $cpt_path_link . "</div>"; + +/* Current grade */ +_html('p', "Validé : {$proficiency}<br>Évaluation : {$eval}"); + +/* Review */ +if ( $review_asked ) { + echo "<div class='alert alert-primary'>Évaluation demandée</div>"; + /* Student can cancer his own request review */ + if ( $USER->id == $studentid ) { + /* Student cancel review */ + echo "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}'>"; + echo "<input hidden style='display: none;' type='text' name='review' value='cancel'>"; + echo "<button type='submit' class='btn btn-secondary'>Annuler la demande</button>"; + echo "</form>"; + } +} else { + if ( $USER->id == $studentid ) { + /* Student ask review */ + echo "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}'>"; + echo "<input hidden style='display: none;' type='text' name='review' value='request'>"; + echo "<button type='submit' class='btn btn-primary'>Demande d'évaluation</button>"; + echo "</form>"; + } +} +echo "</div>"; /* for competency info and grade info */ + +/* EVALUATION ACTION */ + +/* TODO : check if user is teacher */ +echo "<div class='alert alert-secondary'>"; +echo "<form method='post' action='{$CFG->wwwroot}/blocks/competency_iena/course_competency.php?courseid={$courseid}&studentid={$studentid}&competencyid={$competencyid}'>"; +echo "<div class='form-group'>"; +echo "<label>Évaluation</label>"; +echo "<select name='grade' class='form-control'>"; +foreach ($cpt_scale as $key => $item) { + $grade = $key + 1; + $selected = ""; + if ( $item == $eval ) { + $selected = " selected"; + } + echo "<option value='{$grade}'{$selected}>{$item}</option>"; +} +echo "</select>"; +echo "</div>"; +echo "<div class='form-group'>"; +echo "<label>Commentaire d'évaluation</label>"; +echo "<textarea name='note' class='form-control' placeholder=\"Commentaire d'évaluation\"></textarea>"; +echo "</div>"; +echo "<button type='submit' class='btn btn-primary'>Évaluer</button>"; +echo "</form>"; +echo "</div>"; + + + + +echo "<pre>"; +// var_dump($cpt->get_framework()->get('shortname')); +// var_dump($cpt->get_framework()->get('description')); +echo "</pre>"; + + + + +echo $OUTPUT->footer(); + + + +// $student = user_get_users_by_id($studentid) + +?> \ No newline at end of file diff --git a/js/cpt-x-studs.js b/js/cpt-x-studs.js index b56033bb819aad48759957d3131c37a47d0fc10a..57c32c91e98556086604597f402c174fc01b3215 100644 --- a/js/cpt-x-studs.js +++ b/js/cpt-x-studs.js @@ -2,8 +2,7 @@ /* Submit datalist selector to change current competency on the dashboard listing avery student status regarding a particular competency. */ - - window.onload = function () { + window.addEventListener('load', function () { var opts = document.getElementById('competency_list').childNodes; var competencyid = document.getElementById('competencyid').innerHTML; for (var i = 0; i < opts.length; i++) { @@ -30,17 +29,16 @@ } } } - }; - - // remplace le nom de l'étu par son id dans la valeur de l'input puis soumet le formulaire - document.getElementById('competencyid_sel').oninput = function (e) { - var val = document.getElementById('competencyid_sel').value; - var opts = document.getElementById('competency_list').childNodes; - for (var i = 0; i < opts.length; i++) { - if (opts[i].value === val) { - document.getElementById('competencyid_sel').value = opts[i].dataset.value; - document.getElementById('change_cpt_form').submit(); + /* remplace le nom de l'étu par son id dans la valeur de l'input puis soumet le formulaire */ + document.getElementById('competencyid_sel').oninput = function (e) { + var val = document.getElementById('competencyid_sel').value; + var opts = document.getElementById('competency_list').childNodes; + for (var i = 0; i < opts.length; i++) { + if (opts[i].value === val) { + document.getElementById('competencyid_sel').value = opts[i].dataset.value; + document.getElementById('change_cpt_form').submit(); + } } - } - }; + }; + }); })() \ No newline at end of file diff --git a/js/stud-x-cpts.js b/js/stud-x-cpts.js index 35e4dc57f9e9d02ff909e91fd6b2a03b4303aeb4..6c3ad428038795fd5323b847596e303ee14e7d60 100644 --- a/js/stud-x-cpts.js +++ b/js/stud-x-cpts.js @@ -1,5 +1,5 @@ (function() { - window.onload = function () { + window.addEventListener('load', function () { var opts = document.getElementById('student_list').childNodes; var studentid = document.getElementById('studentid').innerHTML; for (var i = 0; i < opts.length; i++) { @@ -26,17 +26,17 @@ } } } - }; - - // remplace le nom de l'étu par son id dans la valeur de l'input puis soumet le formulaire - document.getElementById('studentid_sel').oninput = function (e) { - var val = document.getElementById('studentid_sel').value; - var opts = document.getElementById('student_list').childNodes; - for (var i = 0; i < opts.length; i++) { - if (opts[i].value === val) { - document.getElementById('studentid_sel').value = opts[i].dataset.value; - document.getElementById('change_stud_form').submit(); + /* remplace le nom de l'étu par son id dans la valeur de l'input puis soumet le formulaire */ + document.getElementById('studentid_sel').oninput = function (e) { + var val = document.getElementById('studentid_sel').value; + var opts = document.getElementById('student_list').childNodes; + for (var i = 0; i < opts.length; i++) { + if (opts[i].value === val) { + document.getElementById('studentid_sel').value = opts[i].dataset.value; + document.getElementById('change_stud_form').submit(); + } } - } - }; + }; + }); + })() \ No newline at end of file