From e07c2ef62aa52e64663ac73bea440bf4ad153a35 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Tue, 15 Dec 2015 14:14:51 +0800 Subject: [PATCH] MDL-51040 cbe: Improve the competency breakdown report This report now opens the user_competency_summary_in_couse in a popup when clicking on any cell in the report. The report is refreshed when the popup is closed. --- .../competency/amd/build/grading_popup.min.js | 1 + report/competency/amd/src/grading_popup.js | 116 +++++++++++++++ report/competency/classes/external.php | 134 ++++++++++++++++++ report/competency/classes/output/report.php | 34 ++++- report/competency/db/services.php | 43 ++++++ .../competency/lang/en/report_competency.php | 1 + report/competency/templates/report.mustache | 27 +++- .../user_competency_summary.mustache | 2 +- 8 files changed, 349 insertions(+), 9 deletions(-) create mode 100644 report/competency/amd/build/grading_popup.min.js create mode 100644 report/competency/amd/src/grading_popup.js create mode 100644 report/competency/classes/external.php create mode 100644 report/competency/db/services.php diff --git a/report/competency/amd/build/grading_popup.min.js b/report/competency/amd/build/grading_popup.min.js new file mode 100644 index 00000000000..ad4b3863e7b --- /dev/null +++ b/report/competency/amd/build/grading_popup.min.js @@ -0,0 +1 @@ +define(["jquery","core/notification","core/str","core/ajax","core/log","core/templates","tool_lp/dialogue"],function(a,b,c,d,e,f,g){var h=function(b,c){this._regionSelector=b,this._userCompetencySelector=c,a(this._regionSelector).on("click",this._userCompetencySelector,this._handleClick.bind(this))};return h.prototype._handleClick=function(c){var f=a(c.target).closest(this._userCompetencySelector),g=a(f).data("competencyid"),h=a(f).data("courseid"),i=a(f).data("userid");e.debug("Clicked on cell: competencyId="+g+", courseId="+h+", userId="+i),d.call([{methodname:"tool_lp_data_for_user_competency_summary_in_course",args:{userid:i,competencyid:g,courseid:h},done:this._contextLoaded.bind(this),fail:b.exception}])},h.prototype._contextLoaded=function(a){var d=this;f.render("tool_lp/user_competency_summary_in_course",a).done(function(a,e){c.get_string("usercompetencysummary","report_competency").done(function(b){new g(b,a,f.runTemplateJS.bind(f,e),d._refresh.bind(d),!0)}).fail(b.exception)}).fail(b.exception)},h.prototype._refresh=function(){var c=a(this._regionSelector),e=c.data("courseid"),f=c.data("groupid"),g=c.data("onlyactive");d.call([{methodname:"report_competency_data_for_report",args:{courseid:e,groupid:f,onlyactive:g},done:this._pageContextLoaded.bind(this),fail:b.exception}])},h.prototype._pageContextLoaded=function(a){var c=this;f.render("report_competency/report",a).done(function(a,b){f.replaceNode(c._regionSelector,a,b)}).fail(b.exception)},h.prototype._regionSelector=null,h.prototype._userCompetencySelector=null,h}); \ No newline at end of file diff --git a/report/competency/amd/src/grading_popup.js b/report/competency/amd/src/grading_popup.js new file mode 100644 index 00000000000..21b645ee915 --- /dev/null +++ b/report/competency/amd/src/grading_popup.js @@ -0,0 +1,116 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Module to enable inline editing of a comptency grade. + * + * @package report_competency + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/log', 'core/templates', 'tool_lp/dialogue'], + function($, notification, str, ajax, log, templates, Dialogue) { + + /** + * GradingPopup + * + * @param {String} The regionSelector + * @param {String} The userCompetencySelector + */ + var GradingPopup = function(regionSelector, userCompetencySelector) { + this._regionSelector = regionSelector; + this._userCompetencySelector = userCompetencySelector; + + $(this._regionSelector).on('click', this._userCompetencySelector, this._handleClick.bind(this)); + }; + + /** + * Get the data from the clicked cell and open the popup. + * + * @method _handleClick + * @param {Event} e + */ + GradingPopup.prototype._handleClick = function(e) { + var cell = $(e.target).closest(this._userCompetencySelector); + var competencyId = $(cell).data('competencyid'); + var courseId = $(cell).data('courseid'); + var userId = $(cell).data('userid'); + + log.debug('Clicked on cell: competencyId=' + competencyId + ', courseId=' + courseId + ', userId=' + userId); + + ajax.call([{ + methodname : 'tool_lp_data_for_user_competency_summary_in_course', + args: { userid: userId, competencyid: competencyId, courseid: courseId }, + done: this._contextLoaded.bind(this), + fail: notification.exception + }]); + }; + + /** + * We loaded the context, now render the template. + * + * @method _contextLoaded + * @param {Object} context + */ + GradingPopup.prototype._contextLoaded = function(context) { + var self = this; + templates.render('tool_lp/user_competency_summary_in_course', context).done(function(html, js) { + str.get_string('usercompetencysummary', 'report_competency').done(function(title) { + (new Dialogue(title, html, templates.runTemplateJS.bind(templates, js), self._refresh.bind(self), true)); + }).fail(notification.exception); + }).fail(notification.exception); + }; + + /** + * Refresh the page. + * + * @method _refresh + */ + GradingPopup.prototype._refresh = function() { + var region = $(this._regionSelector); + var courseId = region.data('courseid'); + var groupId = region.data('groupid'); + var onlyActive = region.data('onlyactive'); + + ajax.call([{ + methodname : 'report_competency_data_for_report', + args: { courseid: courseId, groupid: groupId, onlyactive: onlyActive }, + done: this._pageContextLoaded.bind(this), + fail: notification.exception + }]); + }; + + /** + * We loaded the context, now render the template. + * + * @method _pageContextLoaded + * @param {Object} context + */ + GradingPopup.prototype._pageContextLoaded = function(context) { + var self = this; + templates.render('report_competency/report', context).done(function(html, js) { + templates.replaceNode(self._regionSelector, html, js); + }).fail(notification.exception); + }; + + /** @type {String} The selector for the region with the user competencies */ + GradingPopup.prototype._regionSelector = null; + /** @type {String} The selector for the region with a single user competencies */ + GradingPopup.prototype._userCompetencySelector = null; + + return /** @alias module:report_competency/grading_popup */ GradingPopup; + +}); diff --git a/report/competency/classes/external.php b/report/competency/classes/external.php new file mode 100644 index 00000000000..ac999b11762 --- /dev/null +++ b/report/competency/classes/external.php @@ -0,0 +1,134 @@ +. + +/** + * This is the external API for this report. + * + * @package report_competency + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace report_competency; + +defined('MOODLE_INTERNAL') || die(); + +require_once("$CFG->libdir/externallib.php"); + +use context_course; +use external_api; +use external_function_parameters; +use external_multiple_structure; +use external_single_structure; +use external_value; +use tool_lp\external\competency_exporter; +use tool_lp\external\course_summary_exporter; +use tool_lp\external\user_competency_exporter; +use tool_lp\external\user_summary_exporter; + +/** + * This is the external API for this report. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class external extends external_api { + + /** + * Returns description of data_for_competency_frameworks_manage_page() parameters. + * + * @return \external_function_parameters + */ + public static function data_for_report_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $groupid = new external_value( + PARAM_INT, + 'The group id', + VALUE_REQUIRED + ); + $onlyactive = new external_value( + PARAM_BOOL, + 'Only active users', + VALUE_REQUIRED + ); + $params = array( + 'courseid' => $courseid, + 'groupid' => $groupid, + 'onlyactive' => $onlyactive, + ); + return new external_function_parameters($params); + } + + /** + * Loads the data required to render the report. + * + * @param int $courseid The course id + * @param int $groupid The group id + * @param boolean $onlyactive Only show active enrolments + * @return \stdClass + */ + public static function data_for_report($courseid, $groupid, $onlyactive) { + global $PAGE; + + $params = self::validate_parameters( + self::data_for_report_parameters(), + array( + 'courseid' => $courseid, + 'groupid' => $groupid, + 'onlyactive' => $onlyactive + ) + ); + $context = context_course::instance($courseid); + self::validate_context($context); + + $renderable = new output\report($params['courseid'], $params['groupid'], $params['onlyactive']); + $renderer = $PAGE->get_renderer('report_competency'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_report() result value. + * + * @return \external_description + */ + public static function data_for_report_returns() { + return new external_single_structure(array ( + 'courseid' => new external_value(PARAM_INT, 'Course id'), + 'groupid' => new external_value(PARAM_INT, 'Group id'), + 'onlyactive' => new external_value(PARAM_BOOL, 'Only include active enrolments'), + 'competencies' => new external_multiple_structure( + competency_exporter::get_read_structure() + ), + 'course' => course_summary_exporter::get_read_structure(), + 'pluginbaseurl' => new external_value(PARAM_LOCALURL, 'Url to the tool_lp plugin folder on this Moodle site'), + 'usercompetencies' => new external_multiple_structure( + new external_single_structure(array( + 'user' => user_summary_exporter::get_read_structure(), + 'usercompetencies' => new external_multiple_structure( + user_competency_exporter::get_read_structure() + ) + )) + ) + )); + } + +} diff --git a/report/competency/classes/output/report.php b/report/competency/classes/output/report.php index 416d54be5f7..a1ac94270d9 100644 --- a/report/competency/classes/output/report.php +++ b/report/competency/classes/output/report.php @@ -25,12 +25,14 @@ namespace report_competency\output; use context_course; use tool_lp\external\competency_exporter; +use tool_lp\external\course_summary_exporter; use tool_lp\external\user_competency_exporter; use tool_lp\external\user_summary_exporter; use tool_lp\user_competency; use renderable; use templatable; use renderer_base; +use moodle_url; use stdClass; use tool_lp\api; @@ -44,6 +46,16 @@ class report implements renderable, templatable { /** @var context $context */ protected $context; + /** @var int $courseid */ + protected $courseid; + /** @var int $groupid */ + protected $groupid; + /** @var boolean $onlyactive */ + protected $onlyactive; + /** @var array $competencies */ + protected $competencies; + /** @var array $users */ + protected $users; /** * Construct this renderable. @@ -54,9 +66,11 @@ class report implements renderable, templatable { */ public function __construct($courseid, $groupid, $onlyactive) { $this->courseid = $courseid; + $this->groupid = $groupid; + $this->onlyactive = $onlyactive; $this->context = context_course::instance($courseid); // Get all the competencies in this course. - $this->competencies = api::list_competencies_in_course($courseid); + $this->competencies = api::list_course_competencies($courseid); // Get all the users in this course. // tool/lp:coursecompetencygradable @@ -72,10 +86,17 @@ class report implements renderable, templatable { * @return stdClass */ public function export_for_template(renderer_base $output) { + global $DB; + $data = new stdClass(); + $data->courseid = $this->courseid; + $data->groupid = $this->groupid; + $data->onlyactive = $this->onlyactive; + $competencies = array(); $contextcache = array(); - foreach ($this->competencies as $competency) { + foreach ($this->competencies as $coursecompetency) { + $competency = $coursecompetency['competency']; if (!isset($contextcache[$competency->get_competencyframeworkid()])) { $contextcache[$competency->get_competencyframeworkid()] = $competency->get_context(); } @@ -86,6 +107,12 @@ class report implements renderable, templatable { } $data->competencies = $competencies; + $course = $DB->get_record('course', array('id' => $this->courseid)); + $coursecontext = context_course::instance($course->id); + $exporter = new course_summary_exporter($course, array('context' => $coursecontext)); + $data->course = $exporter->export($output); + + $data->pluginbaseurl = (new moodle_url('/admin/tool/lp/'))->out(false); $data->usercompetencies = array(); $scalecache = array(); foreach ($this->users as $user) { @@ -95,7 +122,8 @@ class report implements renderable, templatable { $onerow->user = $exporter->export($output); $onerow->usercompetencies = array(); - foreach ($this->competencies as $competency) { + foreach ($this->competencies as $coursecompetency) { + $competency = $coursecompetency['competency']; $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $competency->get_id())); foreach ($usercompetencies as $uc) { if ($uc->get_competencyid() == $competency->get_id()) { diff --git a/report/competency/db/services.php b/report/competency/db/services.php new file mode 100644 index 00000000000..4d4a2c7d33c --- /dev/null +++ b/report/competency/db/services.php @@ -0,0 +1,43 @@ +. + + +/** + * Competency report webservice functions + * + * + * @package report_competency + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$functions = array( + + // Learning plan related functions. + + 'report_competency_data_for_report' => array( + 'classname' => 'report_competency\external', + 'methodname' => 'data_for_report', + 'classpath' => '', + 'description' => 'Load the data for the competency report in a course.', + 'type' => 'read', + 'capabilities' => 'tool/lp:coursecompetencyread', + 'ajax' => true, + ) +); + diff --git a/report/competency/lang/en/report_competency.php b/report/competency/lang/en/report_competency.php index 0853ecad0d3..cf23934f4a5 100644 --- a/report/competency/lang/en/report_competency.php +++ b/report/competency/lang/en/report_competency.php @@ -24,3 +24,4 @@ $string['pluginname'] = 'Competency breakdown'; $string['coursecompetencybreakdownsummary'] = 'A report of all the students in the course, and their progress towards the course competencies'; +$string['usercompetencysummary'] = 'User competency summary'; diff --git a/report/competency/templates/report.mustache b/report/competency/templates/report.mustache index 1993b62c998..ece7e90ee91 100644 --- a/report/competency/templates/report.mustache +++ b/report/competency/templates/report.mustache @@ -1,10 +1,13 @@ +
- +{{#str}}coursecompetencybreakdownsummary, report_competency{{/str}} - + {{#competencies}} {{/competencies}} @@ -12,14 +15,28 @@ {{#usercompetencies}} - {{/usercompetencies}} {{/usercompetencies}}
{{#str}}coursecompetencybreakdownsummary, report_competency{{/str}}
{{#str}}students{{/str}}{{#str}}students{{/str}} - {{> tool_lp/competency_summary }} + + {{shortname}} - {{idnumber}} +
{{#user}} -{{> tool_lp/form-user-selector-suggestion }} +{{> tool_lp/user_summary }} {{/user}} + {{> report_competency/user_competency_summary}}
+
+{{#js}} +require(['tool_lp/competencydialogue'], function(Compdialogue) { + var competencydialogue = new Compdialogue({includerelated : true}); + competencydialogue.watch('[data-region="competency-breakdown-report"]'); +}); +require(['report_competency/grading_popup'], function(Popup) { + (new Popup('[data-region=competency-breakdown-report]', '[data-user-competency=true]')); +}); +{{/js}} diff --git a/report/competency/templates/user_competency_summary.mustache b/report/competency/templates/user_competency_summary.mustache index 9473fbefeb3..055f4a9e373 100644 --- a/report/competency/templates/user_competency_summary.mustache +++ b/report/competency/templates/user_competency_summary.mustache @@ -1 +1 @@ -{{gradename}} +{{#grade}}{{gradename}}{{/grade}}{{^grade}}Not rated{{/grade}}