MDL-51036 tool_lp: Addressing comments left during peer review

This commit is contained in:
Frederic Massart 2016-01-13 17:59:29 +08:00
parent 572721ac1d
commit 182f609213
12 changed files with 59 additions and 23 deletions

View file

@ -1 +1 @@
define(["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/base"],function(a,b,c,d,e,f,g){var h=function(){g.prototype.constructor.apply(this,[])};return h.prototype=Object.create(g.prototype),h.prototype._nodeSelector='[data-node="user-competency"]',h.prototype._cancelReviewRequest=function(a){var b={methodname:"tool_lp_user_competency_cancel_review_request",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-request-cancelled",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.cancelReviewRequest=function(a){this._cancelReviewRequest(a)},h.prototype._cancelReviewRequestHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.cancelReviewRequest(c)},h.prototype._requestReview=function(a){var b={methodname:"tool_lp_user_competency_request_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-requested",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.requestReview=function(a){this._requestReview(a)},h.prototype._requestReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.requestReview(c)},h.prototype._startReview=function(a){var b={methodname:"tool_lp_user_competency_start_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-started",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.startReview=function(a){this._startReview(a)},h.prototype._startReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.startReview(c)},h.prototype._stopReview=function(a){var b={methodname:"tool_lp_user_competency_stop_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-stopped",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.stopReview=function(a){this._stopReview(a)},h.prototype._stopReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.stopReview(c)},h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this)})},h.prototype._findUserCompetencyData=function(a){var b,c=a.parents(this._nodeSelector);if(1!=c.length)throw new Error("The evidence node was not located.");if(b=c.data(),"undefined"==typeof b||"undefined"==typeof b.userid||"undefined"==typeof b.competencyid)throw new Error("User competency data could not be found.");return b},h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this),'[data-action="start-review"]':this._startReviewHandler.bind(this),'[data-action="stop-review"]':this._stopReviewHandler.bind(this)})},h.prototype.registerEvents=function(b){var c=a(b);c.find('[data-action="request-review"]').click(this._requestReviewHandler.bind(this)),c.find('[data-action="cancel-review-request"]').click(this._cancelReviewRequestHandler.bind(this)),c.find('[data-action="start-review"]').click(this._startReviewHandler.bind(this)),c.find('[data-action="stop-review"]').click(this._stopReviewHandler.bind(this))},h}); define(["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/event_base"],function(a,b,c,d,e,f,g){var h=function(){g.prototype.constructor.apply(this,[])};return h.prototype=Object.create(g.prototype),h.prototype._nodeSelector='[data-node="user-competency"]',h.prototype._cancelReviewRequest=function(a){var b={methodname:"tool_lp_user_competency_cancel_review_request",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-request-cancelled",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.cancelReviewRequest=function(a){this._cancelReviewRequest(a)},h.prototype._cancelReviewRequestHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.cancelReviewRequest(c)},h.prototype._requestReview=function(a){var b={methodname:"tool_lp_user_competency_request_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-requested",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.requestReview=function(a){this._requestReview(a)},h.prototype._requestReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.requestReview(c)},h.prototype._startReview=function(a){var b={methodname:"tool_lp_user_competency_start_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-started",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.startReview=function(a){this._startReview(a)},h.prototype._startReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.startReview(c)},h.prototype._stopReview=function(a){var b={methodname:"tool_lp_user_competency_stop_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-stopped",a),this._trigger("status-changed",a)}.bind(this),function(){this._trigger("error-occured",a)}.bind(this))},h.prototype.stopReview=function(a){this._stopReview(a)},h.prototype._stopReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.stopReview(c)},h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this)})},h.prototype._findUserCompetencyData=function(a){var b,c=a.parents(this._nodeSelector);if(1!=c.length)throw new Error("The evidence node was not located.");if(b=c.data(),"undefined"==typeof b||"undefined"==typeof b.userid||"undefined"==typeof b.competencyid)throw new Error("User competency data could not be found.");return b},h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this),'[data-action="start-review"]':this._startReviewHandler.bind(this),'[data-action="stop-review"]':this._stopReviewHandler.bind(this)})},h.prototype.registerEvents=function(b){var c=a(b);c.find('[data-action="request-review"]').click(this._requestReviewHandler.bind(this)),c.find('[data-action="cancel-review-request"]').click(this._cancelReviewRequestHandler.bind(this)),c.find('[data-action="start-review"]').click(this._startReviewHandler.bind(this)),c.find('[data-action="stop-review"]').click(this._stopReviewHandler.bind(this))},h});

View file

@ -14,9 +14,9 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/** /**
* Base javascript module. * Event base javascript module.
* *
* @module tool_lp/base * @module tool_lp/event_base
* @package tool_lp * @package tool_lp
* @copyright 2015 Frédéric Massart - FMCorz.net * @copyright 2015 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -55,5 +55,5 @@ define(['jquery'], function($) {
this._eventNode.trigger(type, [data]); this._eventNode.trigger(type, [data]);
}; };
return /** @alias module:tool_lp/base */ Base; return /** @alias module:tool_lp/event_base */ Base;
}); });

View file

@ -27,8 +27,8 @@ define(['jquery',
'core/notification', 'core/notification',
'core/str', 'core/str',
'tool_lp/menubar', 'tool_lp/menubar',
'tool_lp/base'], 'tool_lp/event_base'],
function($, Templates, Ajax, Notification, Str, Menubar, Base) { function($, Templates, Ajax, Notification, Str, Menubar, EventBase) {
/** /**
* UserCompetencyWorkflow class. * UserCompetencyWorkflow class.
@ -36,9 +36,9 @@ define(['jquery',
* @param {String} selector The node containing the buttons to switch mode. * @param {String} selector The node containing the buttons to switch mode.
*/ */
var UserCompetencyWorkflow = function() { var UserCompetencyWorkflow = function() {
Base.prototype.constructor.apply(this, []); EventBase.prototype.constructor.apply(this, []);
}; };
UserCompetencyWorkflow.prototype = Object.create(Base.prototype); UserCompetencyWorkflow.prototype = Object.create(EventBase.prototype);
/** @type {String} The selector to find the user competency data. */ /** @type {String} The selector to find the user competency data. */
UserCompetencyWorkflow.prototype._nodeSelector = '[data-node="user-competency"]'; UserCompetencyWorkflow.prototype._nodeSelector = '[data-node="user-competency"]';

View file

@ -24,6 +24,7 @@
namespace tool_lp; namespace tool_lp;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
use coding_exception;
use stdClass; use stdClass;
use lang_string; use lang_string;

View file

@ -2714,7 +2714,7 @@ class external extends external_api {
* @return \external_function_parameters * @return \external_function_parameters
*/ */
public static function user_competency_cancel_review_request_returns() { public static function user_competency_cancel_review_request_returns() {
new external_value(PARAM_BOOL, 'The success'); return new external_value(PARAM_BOOL, 'The success');
} }
/** /**
@ -2754,7 +2754,7 @@ class external extends external_api {
* @return \external_function_parameters * @return \external_function_parameters
*/ */
public static function user_competency_request_review_returns() { public static function user_competency_request_review_returns() {
new external_value(PARAM_BOOL, 'The success'); return new external_value(PARAM_BOOL, 'The success');
} }
/** /**
@ -2793,7 +2793,7 @@ class external extends external_api {
* @return \external_function_parameters * @return \external_function_parameters
*/ */
public static function user_competency_start_review_returns() { public static function user_competency_start_review_returns() {
new external_value(PARAM_BOOL, 'The success'); return new external_value(PARAM_BOOL, 'The success');
} }
/** /**
@ -2832,7 +2832,7 @@ class external extends external_api {
* @return \external_function_parameters * @return \external_function_parameters
*/ */
public static function user_competency_stop_review_returns() { public static function user_competency_stop_review_returns() {
new external_value(PARAM_BOOL, 'The success'); return new external_value(PARAM_BOOL, 'The success');
} }
/** /**

View file

@ -26,6 +26,7 @@
namespace tool_lp\external; namespace tool_lp\external;
require_once($CFG->dirroot . '/comment/lib.php'); require_once($CFG->dirroot . '/comment/lib.php');
// TODO MDL-52243 Move this to core.
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
use comment; use comment;

View file

@ -153,6 +153,12 @@ $string['lp:planviewown'] = 'View own learning plans';
$string['lp:planviewowndraft'] = 'View own draft learning plans'; $string['lp:planviewowndraft'] = 'View own draft learning plans';
$string['lp:templatemanage'] = 'Manage templates'; $string['lp:templatemanage'] = 'Manage templates';
$string['lp:templateread'] = 'View template'; $string['lp:templateread'] = 'View template';
$string['lp:usercompetencycomment'] = 'Comment on a user competency';
$string['lp:usercompetencycommentown'] = 'Comment on own user competency';
$string['lp:usercompetencyrequestreview'] = 'Request the review of a user competency';
$string['lp:usercompetencyrequestreviewown'] = 'Request the review of own user competency';
$string['lp:usercompetencyreview'] = 'Review a user competency';
$string['lp:usercompetencyview'] = 'View a user competency';
$string['lp:userevidencemanage'] = 'Manage evidence of prior learning'; $string['lp:userevidencemanage'] = 'Manage evidence of prior learning';
$string['lp:userevidencemanageown'] = 'Manage own evidence of prior learning'; $string['lp:userevidencemanageown'] = 'Manage own evidence of prior learning';
$string['lp:userevidenceread'] = 'View evidence of prior learning of a user'; $string['lp:userevidenceread'] = 'View evidence of prior learning of a user';
@ -203,6 +209,7 @@ $string['proficient'] = 'Proficient';
$string['rate'] = 'Rate'; $string['rate'] = 'Rate';
$string['rating'] = 'Rating'; $string['rating'] = 'Rating';
$string['relatedcompetencies'] = 'Related competencies'; $string['relatedcompetencies'] = 'Related competencies';
$string['reviewstatus'] = 'Review status';
$string['requestreview'] = 'Request review'; $string['requestreview'] = 'Request review';
$string['reopenplan'] = 'Reopen this learning plan'; $string['reopenplan'] = 'Reopen this learning plan';
$string['reopenplanconfirm'] = 'Reopen the plan \'{$a}\'? The status of the users competencies that was recorded at the time the plan was previously completed will be deleted, and the plan will become active again.'; $string['reopenplanconfirm'] = 'Reopen the plan \'{$a}\'? The status of the users competencies that was recorded at the time the plan was previously completed will be deleted, and the plan will become active again.';
@ -219,7 +226,7 @@ $string['shortname'] = 'Name';
$string['startreview'] = 'Start review'; $string['startreview'] = 'Start review';
$string['state'] = 'State'; $string['state'] = 'State';
$string['status'] = 'Status'; $string['status'] = 'Status';
$string['stopreview'] = 'Stop review'; $string['stopreview'] = 'Finish review';
$string['stopsyncingcohort'] = 'Stop syncing cohort'; $string['stopsyncingcohort'] = 'Stop syncing cohort';
$string['suggest'] = 'Suggest'; $string['suggest'] = 'Suggest';
$string['syncplanscohorts'] = 'Sync plans from template cohorts'; $string['syncplanscohorts'] = 'Sync plans from template cohorts';

View file

@ -222,6 +222,7 @@ function tool_lp_comment_add($comment, $params) {
} }
// Urls. // Urls.
// TODO MDL-52749 Replace the link to the plan with the user competency page.
if (empty($plan)) { if (empty($plan)) {
$urlname = get_string('userplans', 'tool_lp'); $urlname = get_string('userplans', 'tool_lp');
$url = new moodle_url('/admin/tool/lp/plans.php', array('userid' => $uc->get_userid())); $url = new moodle_url('/admin/tool/lp/plans.php', array('userid' => $uc->get_userid()));
@ -258,8 +259,8 @@ function tool_lp_comment_add($comment, $params) {
$message = new \core\message\message(); $message = new \core\message\message();
$message->component = 'tool_lp'; $message->component = 'tool_lp';
$message->name = 'user_competency_comment'; $message->name = 'user_competency_comment';
$message->notification = 0; $message->notification = 1;
$message->userfrom = $comment->userid; $message->userfrom = core_user::get_noreply_user();
$message->subject = get_string('usercommentedonacompetencysubject', 'tool_lp', $fullname); $message->subject = get_string('usercommentedonacompetencysubject', 'tool_lp', $fullname);
$message->fullmessage = $fullmessage; $message->fullmessage = $fullmessage;
$message->fullmessageformat = $format; $message->fullmessageformat = $format;
@ -299,8 +300,14 @@ function tool_lp_comment_permissions($params) {
* Validates comments. * Validates comments.
* *
* @param stdClass $params The parameters. * @param stdClass $params The parameters.
* @return array * @return bool
*/ */
function tool_lp_comment_validate($params) { function tool_lp_comment_validate($params) {
if ($params->commentarea == 'user_competency') {
if (!\tool_lp\user_competency::record_exists($params->itemid)) {
return false;
}
return true; return true;
} }
return false;
}

View file

@ -40,13 +40,25 @@
This template does not have an example context because it includes ajax functionality. This template does not have an example context because it includes ajax functionality.
}} }}
{{#usercompetencysummary}} {{#usercompetencysummary}}
<div data-region="user-competency-full-info" > <div data-region="user-competency-full-info" data-node="user-competency" data-competencyid="{{usercompetency.competencyid}}" data-userid="{{usercompetency.userid}}" data-region-id="{{uniqid}}">
<div data-region="competency-summary"> <div data-region="competency-summary">
{{#competency}} {{#competency}}
{{> tool_lp/competency_summary }} {{> tool_lp/competency_summary }}
{{/competency}} {{/competency}}
<dl> <dl>
{{#usercompetency}} {{#usercompetency}}
<dt>{{#str}}reviewstatus, tool_lp{{/str}}</dt>
<dd data-region="user-competency-status">{{statusname}}
{{#isstatusinreview}}
- {{reviewer.fullname}}
{{/isstatusinreview}}
{{#isrequestreviewallowed}}<button data-action="request-review">{{#str}}requestreview, tool_lp{{/str}}</button>{{/isrequestreviewallowed}}
{{#iscancelreviewrequestallowed}}<button data-action="cancel-review-request">{{#str}}cancelreviewrequest, tool_lp{{/str}}</button>{{/iscancelreviewrequestallowed}}
{{#isstartreviewallowed}}<button data-action="start-review">{{#str}}startreview, tool_lp{{/str}}</button>{{/isstartreviewallowed}}
{{#isstopreviewallowed}}<button data-action="stop-review">{{#str}}stopreview, tool_lp{{/str}}</button>{{/isstopreviewallowed}}
</dd>
<dt>{{#str}}proficient, tool_lp{{/str}}</dt> <dt>{{#str}}proficient, tool_lp{{/str}}</dt>
<dd> <dd>
<span class="label{{^proficiency}} label-important{{/proficiency}} pull-left"> <span class="label{{^proficiency}} label-important{{/proficiency}} pull-left">
@ -71,20 +83,25 @@
</form> </form>
<br><br> <br><br>
</p> </p>
{{/cangradeorsuggest}}
</dd> </dd>
{{#js}} {{#js}}
require(['jquery', 'tool_lp/grade_user_competency_inline', 'tool_lp/user_competency_info'], function($, mod, info) { require(['jquery', 'tool_lp/grade_user_competency_inline', 'tool_lp/user_competency_info', 'tool_lp/user_competency_workflow'], function($, mod, info, UserCompWorkflow) {
var scaleConfig = JSON.parse('{{{competency.scaleconfiguration}}}'); var scaleConfig = JSON.parse('{{{competency.scaleconfiguration}}}');
var inlineGrader = new mod('grade-competency-form-{{uniqid}}', scaleConfig, '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}', '{{#str}}chooserating, tool_lp{{/str}}'); var inlineGrader = new mod('grade-competency-form-{{uniqid}}', scaleConfig, '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}', '{{#str}}chooserating, tool_lp{{/str}}');
var competencyElement = $(document.getElementById('grade-competency-form-{{uniqid}}')).closest('[data-region=user-competency-full-info]'); var competencyElement = $('[data-region-id="{{uniqid}}"]');
var infoReloader = new info(competencyElement, '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}'); var infoReloader = new info(competencyElement, '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}');
var ucw = new UserCompWorkflow();
ucw.registerEvents('[data-region="user-competency-status"]');
ucw.on('status-changed', infoReloader.reload.bind(infoReloader));
ucw.on('error-occured', infoReloader.reload.bind(infoReloader));
inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader)); inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader));
}); });
{{/js}} {{/js}}
{{/cangradeorsuggest}}
{{/usercompetency}} {{/usercompetency}}
{{#usercompetencyplan}} {{#usercompetencyplan}}
<dd>{{gradename}} - {{#str}}plancompleted, tool_lp{{/str}}</dd> <dd>{{gradename}} - {{#str}}plancompleted, tool_lp{{/str}}</dd>
@ -101,6 +118,9 @@
</dd> </dd>
{{/usercompetencyplan}} {{/usercompetencyplan}}
</dl> </dl>
{{#commentarea}}
{{>tool_lp/comment_area}}
{{/commentarea}}
<dl data-region="evidence-listing"> <dl data-region="evidence-listing">
<dt>{{#str}}evidence, tool_lp{{/str}}</dt> <dt>{{#str}}evidence, tool_lp{{/str}}</dt>
<dd> <dd>

View file

@ -47,7 +47,7 @@
{{/competency}} {{/competency}}
<dl> <dl>
{{#usercompetency}} {{#usercompetency}}
<dt>{{#str}}status, tool_lp{{/str}}</dt> <dt>{{#str}}reviewstatus, tool_lp{{/str}}</dt>
<dd data-region="user-competency-status">{{statusname}} <dd data-region="user-competency-status">{{statusname}}
{{#isstatusinreview}} {{#isstatusinreview}}

View file

@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015111036; // The current plugin version (Date: YYYYMMDDXX). $plugin->version = 2015111037; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2014110400; // Requires this Moodle version. $plugin->requires = 2014110400; // Requires this Moodle version.
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics). $plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).