MDL-50262 outcomes: Added scales and scale configuration.

Competency frameworks can now specify a scale to determine
proficiency.
This commit is contained in:
Adrian Greeve
2016-04-18 10:58:32 +08:00
committed by Frederic Massart
parent 9408e77eca
commit d629323f72
10 changed files with 421 additions and 1 deletions
+1
View File
@@ -0,0 +1 @@
define(["jquery","core/notification","core/templates","core/ajax","core/dialogue"],function(a,b,c,d,e){var f=null,g=0,h=0,i=function(){h=a("#id_scaleid").val();var d=a("#id_scaleid option:selected").text();m(h).done(function(){var a={scalename:d,scales:f};c.render("tool_lp/scale_configuration_page",a).done(function(a){new e(d,a,k)}).fail(b.exception)}).fail(b.exception)},j=function(){var b=a("#tool_lp_scaleconfiguration").val();if(""!==b){var c=a.parseJSON(b),d=c.shift();if(d.scaleid===g)return c}return""},k=function(b){var c=a(b.getContent());if(g===h){var d=j();""!==d&&d.forEach(function(b){1===b.scaledefault&&a("#tool_lp_scale_default_"+b.id).attr("checked",!0),1===b.proficient&&a("#tool_lp_scale_proficient_"+b.id).attr("checked",!0)})}c.on("click",'[data-action="close"]',function(){l(),b.close()}),c.on("click",'[data-action="cancel"]',function(){b.close()})},l=function(){var b=[{scaleid:h}];f.forEach(function(c){var d=0,e=0;a("#tool_lp_scale_default_"+c.id).is(":checked")&&(d=1),a("#tool_lp_scale_proficient_"+c.id).is(":checked")&&(e=1),b.push({name:c.name,id:c.id,scaledefault:d,proficient:e})});var c=JSON.stringify(b);a("#tool_lp_scaleconfiguration").val(c),g=h},m=function(b){var c=a.Deferred(),e=d.call([{methodname:"tool_lp_get_scale_values",args:{scaleid:b}}]);return e[0].done(function(a){f=a,c.resolve(a)}).fail(function(a){c.reject(a)}),c.promise()};return{init:function(){g=a("#id_scaleid").val(),a("#id_scaleconfigbutton").click(i)}}});
+171
View File
@@ -0,0 +1,171 @@
// 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/>.
/**
* Handle opening a dialogue to configure scale data.
*
* @module tool_lp/scaleconfig
* @package tool_lp
* @copyright 2015 Adrian Greeve <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/notification', 'core/templates', 'core/ajax', 'core/dialogue'],
function($, notification, templates, ajax, Dialogue) {
/** @var {Array} scalevalues ID and name of the scales. */
var scalevalues = null;
/** @var {Number) originalscaleid Original scale ID when the page loads. */
var originalscaleid = 0;
/** @var {Number} scaleid Current scale ID. */
var scaleid = 0;
/**
* Displays the scale configuration dialogue.
*
* @method showConfig
*/
var showConfig = function() {
scaleid = $("#id_scaleid").val();
var scalename = $("#id_scaleid option:selected").text();
getScaleValues(scaleid).done(function() {
var context = {
scalename: scalename,
scales: scalevalues
};
// Dish up the form.
templates.render('tool_lp/scale_configuration_page', context)
.done(function(html) {
new Dialogue(
scalename,
html,
initScaleConfig
);
}).fail(notification.exception);
}).fail(notification.exception);
};
/**
* Gets the original scale configuration if it was set.
*
* @method retrieveOriginalScaleConfig
* @return {Object|String} scale configuration or empty string.
*/
var retrieveOriginalScaleConfig = function() {
var jsonstring = $('#tool_lp_scaleconfiguration').val();
if (jsonstring !== '') {
var scaleconfiguration = $.parseJSON(jsonstring);
// The first object should contain the scale ID for the configuration.
var scaledetail = scaleconfiguration.shift();
// Check that this scale id matches the one from the page before returning the configuration.
if (scaledetail.scaleid === originalscaleid) {
return scaleconfiguration;
}
}
return '';
};
/**
* Initialises the scale configuration dialogue.
*
* @method initScaleConfig
* @param {Dialogue} popup Dialogue object to initialise.
*/
var initScaleConfig = function(popup) {
var body = $(popup.getContent());
if (originalscaleid === scaleid) {
// Set up the popup to show the current configuration.
var currentconfig = retrieveOriginalScaleConfig();
// Set up the form only if there is configuration settings to set.
if (currentconfig !== '') {
currentconfig.forEach(function(value) {
if (value.scaledefault === 1) {
$('#tool_lp_scale_default_' + value.id).attr('checked', true);
}
if (value.proficient === 1) {
$('#tool_lp_scale_proficient_' + value.id).attr('checked', true);
}
});
}
}
body.on('click', '[data-action="close"]', function() { setScaleConfig(); popup.close(); });
body.on('click', '[data-action="cancel"]', function() { popup.close(); });
};
/**
* Set the scale configuration back into a JSON string in the hidden element.
*
* @method setScaleConfig
*/
var setScaleConfig = function() {
// Get the data.
var data = [{ scaleid: scaleid}];
scalevalues.forEach(function(value) {
var scaledefault = 0;
var proficient = 0;
if ($('#tool_lp_scale_default_' + value.id).is(':checked')) { scaledefault = 1; }
if ($('#tool_lp_scale_proficient_' + value.id).is(':checked')) { proficient = 1; }
data.push({
name: value.name,
id: value.id,
scaledefault: scaledefault,
proficient: proficient
});
});
var datastring = JSON.stringify(data);
// Send to the hidden field on the form.
$('#tool_lp_scaleconfiguration').val(datastring);
// Once the configuration has been saved then the original scale ID is set to the current scale ID.
originalscaleid = scaleid;
};
/**
* Get the scale values for the selected scale.
*
* @method getScaleValues
* @param {Number} scaleid The scale ID of the selected scale.
* @return {Promise} A deffered object with the scale values.
*/
var getScaleValues = function(scaleid) {
var deferred = $.Deferred();
var promises = ajax.call([{
methodname: 'tool_lp_get_scale_values',
args: {
scaleid: scaleid
}
}]);
promises[0].done(function(result) {
scalevalues = result;
deferred.resolve(result);
}).fail(function(exception) {
deferred.reject(exception);
});
return deferred.promise();
};
return {
/**
* Main initialisation.
*
* @method init
*/
init: function() {
// Get the current scale ID.
originalscaleid = $("#id_scaleid").val();
$('#id_scaleconfigbutton').click(showConfig);
}
};
});
@@ -51,6 +51,12 @@ class competency_framework extends persistent {
/** @var bool $visible Used to show/hide this framework */
private $visible = true;
/** @var int $scaleid The scale ID for this framework */
private $scaleid = 0;
/** @var string $scaleconfiguration scale information relevant to this framework*/
private $scaleconfiguration = '';
/**
* Method that provides the table name matching this class.
*
@@ -167,6 +173,42 @@ class competency_framework extends persistent {
$this->visible = $visible;
}
/**
* Get the scale ID.
*
* @return int The scale ID
*/
public function get_scaleid() {
return $this->scaleid;
}
/**
* Set the scale ID.
*
* @param int $scale The scale ID
*/
public function set_scaleid($scaleid) {
$this->scaleid = $scaleid;
}
/**
* Get the scale configuration.
*
* @return string The scale configuration
*/
public function get_scaleconfiguration() {
return $this->scaleconfiguration;
}
/**
* Set the scale configuration.
*
* @param string $scaleconfiguration The scale configuration (JSON string)
*/
public function set_scaleconfiguration($scaleconfiguration) {
$this->scaleconfiguration = $scaleconfiguration;
}
/**
* Populate this class with data from a DB record.
*
@@ -192,6 +234,12 @@ class competency_framework extends persistent {
if (isset($record->sortorder)) {
$this->set_sortorder($record->sortorder);
}
if (isset($record->scaleid)) {
$this->set_scaleid($record->scaleid);
}
if (isset($record->scaleconfiguration)) {
$this->set_scaleconfiguration($record->scaleconfiguration);
}
if (isset($record->visible)) {
$this->set_visible($record->visible);
}
@@ -221,6 +269,8 @@ class competency_framework extends persistent {
$record->descriptionformat = $this->get_descriptionformat();
$record->descriptionformatted = format_text($this->get_description(), $this->get_descriptionformat());
$record->sortorder = $this->get_sortorder();
$record->scaleid = $this->get_scaleid();
$record->scaleconfiguration = $this->get_scaleconfiguration();
$record->visible = $this->get_visible();
$record->timecreated = $this->get_timecreated();
$record->timemodified = $this->get_timemodified();
+68
View File
@@ -24,6 +24,7 @@
namespace tool_lp;
require_once("$CFG->libdir/externallib.php");
require_once("$CFG->libdir/grade/grade_scale.php");
use external_api;
use external_function_parameters;
@@ -32,6 +33,7 @@ use external_format_value;
use external_single_structure;
use external_multiple_structure;
use invalid_parameter_exception;
use grade_scale;
/**
* This is the external API for this tool.
@@ -3451,4 +3453,70 @@ class external extends external_api {
));
}
/**
* Returns the description of the get_scale_values() parameters.
*
* @return external_function_parameters.
*/
public static function get_scale_values_parameters() {
$scaleid = new external_value(
PARAM_INT,
'The scale id',
VALUE_REQUIRED
);
$params = array('scaleid' => $scaleid);
return new external_function_parameters($params);
}
/**
* Expose to AJAX
*
* @return boolean
*/
public static function get_scale_values_is_allowed_from_ajax() {
return true;
}
/**
* Get the values associated with a scale.
*
* @param int $scaleid Scale ID
* @return array Values for a scale.
*/
public static function get_scale_values($scaleid) {
global $DB;
$params = self::validate_parameters(self::get_scale_values_parameters(),
array(
'scaleid' => $scaleid,
)
);
// The following section is not learning plan specific and so has not been moved to the api.
// Retrieve the scale value from the database.
$scale = grade_scale::fetch(array('id' => $scaleid));
// Reverse the array so that high levels are at the top.
$scalevalues = array_reverse($scale->load_items());
foreach ($scalevalues as $key => $value) {
// Add a key (make the first value 1).
$scalevalues[$key] = array(
'id' => $key + 1,
'name' => $value
);
}
return $scalevalues;
}
/**
* Returns description of get_scale_values() result value.
*
* @return external_description
*/
public static function get_scale_values_returns() {
return new external_multiple_structure(
new external_single_structure(array(
'id' => new external_value(PARAM_INT, 'Scale value ID'),
'name' => new external_value(PARAM_RAW, 'Scale value name')
)
)
);
}
}
@@ -44,6 +44,8 @@ class competency_framework extends moodleform {
* Define the form - called by parent constructor
*/
public function definition() {
global $PAGE;
$mform = $this->_form;
$id = $this->_customdata;
@@ -61,6 +63,18 @@ class competency_framework extends moodleform {
$mform->addElement('text', 'idnumber',
get_string('idnumber', 'tool_lp'));
$mform->setType('idnumber', PARAM_TEXT);
$scales = get_scales_menu();
$mform->addElement('select', 'scaleid', get_string('scale', 'tool_lp'), $scales);
$mform->setType('scaleid', PARAM_INT);
$mform->addHelpButton('scaleid', 'scale', 'tool_lp');
$mform->addElement('button', 'scaleconfigbutton', get_string('configurescale', 'tool_lp'));
// Add js.
$PAGE->requires->js_call_amd('tool_lp/scaleconfig', 'init');
$mform->addElement('hidden', 'scaleconfiguration', '', array('id' => 'tool_lp_scaleconfiguration'));
$mform->setType('scaleconfiguration', PARAM_RAW);
$mform->addElement('selectyesno', 'visible',
get_string('visible', 'tool_lp'));
$mform->setDefault('visible', true);
+3 -1
View File
@@ -32,6 +32,8 @@
<FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Description of this competency framework"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field"/>
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Defined sort order for this competency when it is displayed in a list."/>
<FIELD NAME="scaleid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false" COMMENT="Scale used to define competency."/>
<FIELD NAME="scaleconfiguration" TYPE="char" LENGTH="1333" NOTNULL="false" SEQUENCE="false" COMMENT="Scale information."/>
<FIELD NAME="visible" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Used to show/hide this competency framework."/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this competency framework was created."/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this competency framework was last modified."/>
@@ -114,4 +116,4 @@
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
+8
View File
@@ -387,6 +387,14 @@ $functions = array(
'description' => 'Load the data for the plans page template',
'type' => 'read',
'capabilities'=> 'tool/lp:planviewown',
),
'tool_lp_get_scale_values' => array(
'classname' => 'tool_lp\external',
'methodname' => 'get_scale_values',
'classpath' => '',
'description' => 'Fetch the values for a specific scale',
'type' => 'read',
'capabilities'=> 'tool/lp:competencymanage',
)
);
+7
View File
@@ -39,12 +39,14 @@ $string['lp:templateread'] = 'View template';
$string['competencies'] = 'Competencies';
$string['competenciesforframework'] = 'Competencies for {$a}';
$string['competencyframeworks'] = 'Competency Frameworks';
$string['configurescale'] = 'Configure scales';
$string['addnewcompetencyframework'] = 'Add new competency framework';
$string['addnewplan'] = 'Add new learning plan';
$string['addnewtemplate'] = 'Add new learning plan template';
$string['addnewcompetency'] = 'Add new competency';
$string['addnewplan'] = 'Add new learning plan';
$string['addcompetency'] = 'Add competency';
$string['default'] = 'Default';
$string['editcompetencyframework'] = 'Edit competency framework';
$string['erroreditingmodifiedplan'] = 'You can not edit a learning plan modified by another user if you don\'t have tool/lp:planmanage or tool/lp:planmanageown capabilities.';
$string['errorplanstatus'] = 'Learning plans {$a} status unknown';
@@ -60,8 +62,13 @@ $string['nocompetencies'] = 'No competencies have been created in this framework
$string['nocompetenciesincourse'] = 'No competencies have been linked to this course.';
$string['nouserplans'] = 'No learning plans have been created yet.';
$string['nocompetenciesintemplate'] = 'No competencies have been linked to this template.';
$string['proficient'] = 'Proficient';
$string['shortname'] = 'Name';
$string['savechanges'] = 'Save changes';
$string['scale'] = 'Scale';
$string['scalevalue'] = 'Scale value';
$string['scale_help'] = 'A scale determines how proficiency is measured in a competency. After selecting a scale, configure the scale, setting one of the scale values as default and marking all scale values that are deemed proficient.';
$string['description'] = 'Description';
$string['visible'] = 'Visible';
$string['visible_help'] = 'A competency framework can be hidden from teachers. This could be useful if a framework is still in the process of being developed.';
@@ -0,0 +1,61 @@
{{!
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/>.
}}
{{!
Set scale configuration for the competency framework.
Classes required for JS:
* none
Data attibutes required for JS:
* none
Context variables required for this template:
* scales Array of id / name pairs.
Example context (json):
{
"scales": [
{ "id": 1, "name": "Competent" },
{ "id": 2, "name": "Not competent"}
]
}
}}
<div>
<table class="table table-condensed">
<thead>
<tr>
<th scope="col">{{#str}}scalevalue, tool_lp{{/str}}</th>
<th scope="col">{{#str}}default, tool_lp{{/str}}</th>
<th scope="col">{{#str}}proficient, tool_lp{{/str}}</th>
</tr>
</thead>
<tbody>
{{#scales}}
<tr class="tool_lp_scale_config">
<td>{{name}}</td>
<td><input type="radio" name="default" id="tool_lp_scale_default_{{id}}" /></td>
<td><input type="checkbox" name="proficient" id="tool_lp_scale_proficient_{{id}}" /></td>
</tr>
{{/scales}}
</tbody>
</table>
</div>
<div data-region="scale-buttons">
<input type="button" data-action="close" value="{{#str}}closebuttontitle{{/str}}"/>
<input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</div>
+38
View File
@@ -886,4 +886,42 @@ class tool_lp_external_testcase extends externallib_advanced_testcase {
$this->setUser($this->user);
external::reorder_template_competency($template->id, $competency1->id, $competency2->id);
}
/**
* Test that we can return scale values for a scale with the scale ID.
*/
public function test_get_scale_values() {
global $DB;
// Create a scale.
$record = new stdClass();
$record->courseid = 0;
$record->userid = $this->creator->id;
$record->name = 'Test scale';
$record->scale = 'Poor, Not good, Okay, Fine, Excellent';
$record->description = '<p>Test scale description.</p>';
$record->descriptionformat = 1;
$record->timemodified = time();
$scaleid = $DB->insert_record('scale', $record);
// Expected return value.
$expected = array(array(
'id' => 1,
'name' => 'Excellent'
), array(
'id' => 2,
'name' => 'Fine'
), array(
'id' => 3,
'name' => 'Okay'
), array(
'id' => 4,
'name' => 'Not good'
), array(
'id' => 5,
'name' => 'Poor'
)
);
// Call the webservice.
$result = external::get_scale_values($scaleid);
$this->assertEquals($expected, $result);
}
}