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.
This commit is contained in:
Damyon Wiese
2016-04-18 10:58:47 +08:00
committed by Frederic Massart
parent 3fb067a203
commit e07c2ef62a
8 changed files with 349 additions and 9 deletions
+1
View File
@@ -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});
+116
View File
@@ -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 <http://www.gnu.org/licenses/>.
/**
* 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;
});
+134
View File
@@ -0,0 +1,134 @@
<?php
// 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 <http://www.gnu.org/licenses/>.
/**
* 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()
)
))
)
));
}
}
+31 -3
View File
@@ -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()) {
+43
View File
@@ -0,0 +1,43 @@
<?php
// 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 <http://www.gnu.org/licenses/>.
/**
* 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,
)
);
@@ -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';
+22 -5
View File
@@ -1,10 +1,13 @@
<div data-region="competency-breakdown-report" data-courseid="{{course.id}}" data-groupid="{{groupid}}" data-onlyactive="{{onlyactive}}">
<table class="table table-bordered">
<caption>{{#str}}coursecompetencybreakdownsummary, report_competency{{/str}}</caption>
<summary>{{#str}}coursecompetencybreakdownsummary, report_competency{{/str}}</summary>
<tr>
<td scope="col"><span class="accesshide">{{#str}}students{{/str}}</span></td>
<th scope="col"><span class="accesshide">{{#str}}students{{/str}}</span></th>
{{#competencies}}
<th scope="col">
{{> tool_lp/competency_summary }}
<a href="#" data-action="competency-dialogue" data-id="{{id}}">
{{shortname}} - {{idnumber}}
</a>
</th>
{{/competencies}}
</tr>
@@ -12,14 +15,28 @@
<tr>
<th scope="row">
{{#user}}
{{> tool_lp/form-user-selector-suggestion }}
{{> tool_lp/user_summary }}
{{/user}}
</th>
{{#usercompetencies}}
<td class="alert {{#proficiency}}alert-success{{/proficiency}}">
<td class="alert {{#proficiency}}alert-success{{/proficiency}}"
data-user-competency="true"
data-userid="{{user.id}}"
data-competencyid="{{competencyid}}"
data-courseid="{{course.id}}">
{{> report_competency/user_competency_summary}}
</td>
{{/usercompetencies}}
</tr>
{{/usercompetencies}}
</table>
</div>
{{#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}}
@@ -1 +1 @@
{{gradename}}
<a href="#" title="{{#str}}usercompetencysummary, report_competency{{/str}}">{{#grade}}{{gradename}}{{/grade}}{{^grade}}Not rated{{/grade}}</a>