diff --git a/admin/tool/lp/amd/build/competencies.min.js b/admin/tool/lp/amd/build/competencies.min.js index f99d77b6ba3..78d2c970e1f 100644 --- a/admin/tool/lp/amd/build/competencies.min.js +++ b/admin/tool/lp/amd/build/competencies.min.js @@ -1 +1 @@ -define(["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/competencyselector","tool_lp/dragdrop-reorder"],function(a,b,c,d,e,f,g){var h=function(c,e,g){this.itemid=c,this.itemtype=e,this.pageContextId=g;var h=this,i=null,j=null,k=null;"course"===e?(i=[{methodname:"tool_lp_add_competency_to_course",args:{courseid:this.itemid}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:this.itemid}}],j="tool_lp/course_competencies_page",k="coursecompetenciespage"):"template"===e&&(i=[{methodname:"tool_lp_add_competency_to_template",args:{templateid:this.itemid}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:this.itemid}}],j="tool_lp/template_competencies_page",k="templatecompetenciespage");var l=f.init();l.done(function(c){return 0===c.length?void d.render("tool_lp/no_frameworks_warning",{}).done(function(b){a('[data-region="actions"]').append(b),a('[data-region="actions"] button').hide()}).fail(b.exception):(a('[data-region="actions"] button').show(),h.registerEvents(),h.registerDragDrop(),void f.setAddCompetencyRequests(i,j,k))}).fail(b.exception)};return h.prototype.registerDragDrop=function(){var a=this;e.get_string("movecompetency","tool_lp").done(function(b){g.dragdrop("movecompetency",b,{identifier:"movecompetency",component:"tool_lp"},{identifier:"movecompetencyafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",function(b,c){a.handleDrop.call(a,b,c)})}).fail(b.exception)},h.prototype.handleDrop=function(d,e){var f=a(d).data("id"),g=a(e).data("id"),h=this,i=[];if("course"==h.itemtype)i=c.call([{methodname:"tool_lp_reorder_course_competency",args:{courseid:h.itemid,competencyidfrom:f,competencyidto:g}}]);else{if("template"!=h.itemtype)return null;i=c.call([{methodname:"tool_lp_reorder_template_competency",args:{templateid:h.itemid,competencyidfrom:f,competencyidto:g}}])}i[0].fail(b.exception)},h.prototype.registerEvents=function(){var e=this;a('[data-region="actions"] button').click(function(a){return f.openCompetencySelector()}),a('[data-action="delete-competency-link"]').click(function(f){var g=[],h="",i="";f.preventDefault();var j=a(f.target).closest("[data-id]").data("id");"course"==e.itemtype?(g=c.call([{methodname:"tool_lp_remove_competency_from_course",args:{courseid:e.itemid,competencyid:j}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:e.itemid}}]),h="tool_lp/course_competencies_page",i="coursecompetenciespage"):"template"==e.itemtype&&(g=c.call([{methodname:"tool_lp_remove_competency_from_template",args:{templateid:e.itemid,competencyid:j}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:e.itemid,pagecontext:{contextid:e.pageContextId}}}]),h="tool_lp/template_competencies_page",i="templatecompetenciespage"),g[1].done(function(c){d.render(h,c).done(function(b,c){a('[data-region="'+i+'"]').replaceWith(b),d.runTemplateJS(c)}).fail(b.exception)}).fail(b.exception)})},h}); \ No newline at end of file +define(["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/competencypicker","tool_lp/dragdrop-reorder"],function(a,b,c,d,e,f,g){var h=function(b,c,d){this.itemid=b,this.itemtype=c,this.pageContextId=d,this.pickerInstance=null,a('[data-region="actions"] button').show(),this.registerEvents(),this.registerDragDrop()};return h.prototype.registerDragDrop=function(){var a=this;e.get_string("movecompetency","tool_lp").done(function(b){g.dragdrop("movecompetency",b,{identifier:"movecompetency",component:"tool_lp"},{identifier:"movecompetencyafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",function(b,c){a.handleDrop.call(a,b,c)})}).fail(b.exception)},h.prototype.handleDrop=function(d,e){var f=a(d).data("id"),g=a(e).data("id"),h=this,i=[];if("course"==h.itemtype)i=c.call([{methodname:"tool_lp_reorder_course_competency",args:{courseid:h.itemid,competencyidfrom:f,competencyidto:g}}]);else{if("template"!=h.itemtype)return null;i=c.call([{methodname:"tool_lp_reorder_template_competency",args:{templateid:h.itemid,competencyidfrom:f,competencyidto:g}}])}i[0].fail(b.exception)},h.prototype.pickCompetency=function(){var e,g,h,i=this;i.pickerInstance||(i.pickerInstance=new f(i.pageContextId,void 0,"course"===i.itemtype?"parents":void 0),i.pickerInstance.on("save",function(f,j){var k=j.competencyId;"course"===i.itemtype?(e=[{methodname:"tool_lp_add_competency_to_course",args:{courseid:i.itemid,competencyid:k}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:i.itemid}}],g="tool_lp/course_competencies_page",h="coursecompetenciespage"):"template"===i.itemtype&&(e=[{methodname:"tool_lp_add_competency_to_template",args:{templateid:i.itemid,competencyid:k}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:i.itemid,pagecontext:{contextid:i.pageContextId}}}],g="tool_lp/template_competencies_page",h="templatecompetenciespage"),c.call(e)[1].then(function(b){return d.render(g,b).done(function(b,c){a('[data-region="'+h+'"]').replaceWith(b),d.runTemplateJS(c)})},b.exception)})),i.pickerInstance.display()},h.prototype.registerEvents=function(){var e=this;a('[data-region="actions"] button').click(function(a){a.preventDefault(),e.pickCompetency()}),a('[data-action="delete-competency-link"]').click(function(f){var g=[],h="",i="";f.preventDefault();var j=a(f.target).closest("[data-id]").data("id");"course"==e.itemtype?(g=c.call([{methodname:"tool_lp_remove_competency_from_course",args:{courseid:e.itemid,competencyid:j}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:e.itemid}}]),h="tool_lp/course_competencies_page",i="coursecompetenciespage"):"template"==e.itemtype&&(g=c.call([{methodname:"tool_lp_remove_competency_from_template",args:{templateid:e.itemid,competencyid:j}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:e.itemid,pagecontext:{contextid:e.pageContextId}}}]),h="tool_lp/template_competencies_page",i="templatecompetenciespage"),g[1].done(function(c){d.render(h,c).done(function(b,c){a('[data-region="'+i+'"]').replaceWith(b),d.runTemplateJS(c)}).fail(b.exception)}).fail(b.exception)})},h}); \ No newline at end of file diff --git a/admin/tool/lp/amd/build/competencyactions.min.js b/admin/tool/lp/amd/build/competencyactions.min.js index 5ed4a3b3852..e22b41f698e 100644 --- a/admin/tool/lp/amd/build/competencyactions.min.js +++ b/admin/tool/lp/amd/build/competencyactions.min.js @@ -1 +1 @@ -define(["jquery","core/url","core/templates","core/notification","core/str","core/ajax","tool_lp/dragdrop-reorder","tool_lp/tree","tool_lp/dialogue","tool_lp/menubar","tool_lp/competencyselector"],function(a,b,c,d,e,f,g,h,i,j,k){var l,m=null,n=null,o=null,p=function(){var c=a('[data-region="competencyactions"]').data("competency"),d={competencyframeworkid:m.getCompetencyFrameworkId(),pagecontextid:l};null!==c&&(d.parentid=c.id);var e=a.param(d);window.location=b.relativeUrl("/admin/tool/lp/editcompetency.php?"+e)},q=function(){if("undefined"==typeof o&&(o=0),o!=n){var b=a('[data-region="filtercompetencies"]').data("frameworkid"),c=f.call([{methodname:"tool_lp_set_parent_competency",args:{competencyid:n,parentid:o}},{methodname:"tool_lp_data_for_competencies_manage_page",args:{competencyframeworkid:b,search:a('[data-region="filtercompetencies"] input').val()}}]);c[1].done(v).fail(d.exception)}},r=function(b){new h("[data-enhance=movetree]",function(b){o=a(b).data("id")});var c=a(b.getContent());c.on("click",'[data-action="move"]',function(){b.close(),q()}),c.on("click",'[data-action="cancel"]',function(){b.close()})},s=function(a,b){var c;for(c=0;c"),h._frameworks=[],h._reset(),h._pageContextId=b,h._pageContextIncludes=d||"children",c&&(h._frameworkId=c,h._singleFramework=!0)};return i.prototype._competencies=null,i.prototype._disallowedCompetencyIDs=null,i.prototype._eventNode=null,i.prototype._frameworks=null,i.prototype._frameworkId=null,i.prototype._pageContextId=null,i.prototype._pageContextIncludes=null,i.prototype._popup=null,i.prototype._searchText="",i.prototype._selectedCompetency=null,i.prototype._singleFramework=!1,i.prototype._afterRender=function(){new g(h._find("[data-enhance=linktree]"),function(b){var c=b.data("id"),d=!0;a.each(h._disallowedCompetencyIDs,function(a,b){return b==c?(d=!1,!1):void 0}),h._selectedCompetency=null,d&&(h._selectedCompetency=c),h._selectedCompetency?h._find('[data-region="competencylinktree"] [data-action="add"]').removeAttr("disabled"):h._find('[data-region="competencylinktree"] [data-action="add"]').attr("disabled","disabled")}),h._singleFramework||h._find('[data-action="chooseframework"]').change(function(b){h._frameworkId=a(b.target).val(),h._loadCompetencies().then(h._refresh)}),h._find('[data-region="filtercompetencies"] button').click(function(b){return b.preventDefault(),a(b.target).attr("disabled","disabled"),h._searchText=h._find('[data-region="filtercompetencies"] input').val()||"",h._refresh().always(function(){a(b.target).removeAttr("disabled")})}),h._find('[data-region="competencylinktree"] [data-action="cancel"]').click(function(a){a.preventDefault(),h.close()}),h._find('[data-region="competencylinktree"] [data-action="add"]').click(function(a){a.preventDefault(),h._selectedCompetency&&(h._trigger("save",{competencyId:h._selectedCompetency}),h.close())})},i.prototype.close=function(){h._popup.close(),h._reset()},i.prototype.display=function(){return h._render().done(function(a){return f.get_string("competencypicker","tool_lp").done(function(b){h._popup=new e(b,a,h._afterRender.bind(h))})}).fail(b.exception)},i.prototype._fetchCompetencies=function(a,d){return c.call([{methodname:"tool_lp_search_competencies",args:{searchtext:d,competencyframeworkid:a}}])[0].done(function(a){function b(a,c){for(var d=0;d0?a.when():(d=h._singleFramework?c.call([{methodname:"tool_lp_read_competency_framework",args:{id:this._frameworkId}}])[0].then(function(a){return[a]}):c.call([{methodname:"tool_lp_list_competency_frameworks",args:{sort:"shortname",context:{contextid:h._pageContextId},includes:h._pageContextIncludes}}])[0],d.done(function(a){h._frameworks=a}).fail(b.exception))},i.prototype.on=function(a,b){h._eventNode.on(a,b)},i.prototype._preRender=function(){return h._loadFrameworks().then(function(){return!h._frameworkId&&h._frameworks.length>0&&(h._frameworkId=h._frameworks[0].id),h._frameworkId?h._loadCompetencies():(h._frameworks=[],a.when())})},i.prototype._refresh=function(){return h._render().then(function(a){h._find('[data-region="competencylinktree"]').replaceWith(a),h._afterRender()})},i.prototype._render=function(){return h._preRender().then(function(){h._singleFramework||a.each(h._frameworks,function(a,b){b.id==h._frameworkId?b.selected=!0:b.selected=!1});var b={competencies:h._competencies,framework:h._getFramework(h._frameworkId),frameworks:h._frameworks,search:h._searchText,singleFramework:h._singleFramework};return d.render("tool_lp/competency_picker",b)})},i.prototype._reset=function(){h._competencies=[],h._disallowedCompetencyIDs=[],h._popup=null,h._searchText="",h._selectedCompetency=null},i.prototype.setDisallowedCompetencyIDs=function(a){h._disallowedCompetencyIDs=a},i.prototype._trigger=function(a,b){h._eventNode.trigger(a,[b])},i}); \ No newline at end of file diff --git a/admin/tool/lp/amd/build/competencyselector.min.js b/admin/tool/lp/amd/build/competencyselector.min.js deleted file mode 100644 index 035ef0f2f54..00000000000 --- a/admin/tool/lp/amd/build/competencyselector.min.js +++ /dev/null @@ -1 +0,0 @@ -define(["jquery","core/notification","core/ajax","core/templates","tool_lp/dialogue","core/str","tool_lp/tree"],function(a,b,c,d,e,f,g){return{frameworks:null,popup:null,selectedCompetency:0,requests:[],pagerender:null,pageregion:null,addCompetencyCallback:null,init:function(){var a=c.call([{methodname:"tool_lp_list_competency_frameworks",args:{filters:{},sort:"sortorder"}}]);return a[0].done(function(a){this.frameworks=a}.bind(this)).fail(b.exception),a[0]},setAddCompetencyRequests:function(a,b,c,d){this.requests=a,this.pagerender=b,this.pageregion=c,this.addCompetencyCallback=d},applyFilter:function(c){c.preventDefault();var e=a('[data-region="filtercompetencies"] input'),f=e.val(),g=a('[data-action="chooseframework"]'),h=g.val();this.searchCompetencies().done(function(c){var e=0,g=this.frameworks[0];for(e=0;e. + +/** + * Competency picker. + * + * @package tool_lp + * @copyright 2015 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define(['jquery', + 'core/notification', + 'core/ajax', + 'core/templates', + 'tool_lp/dialogue', + 'core/str', + 'tool_lp/tree'], + function($, Notification, Ajax, Templates, Dialogue, Str, Tree) { + + var self; + + /** + * Competency picker class. + * @param {Number} pageContextId The page context ID. + * @param {Number|false} singleFramework The ID of the framework when limited to one. + */ + var Picker = function(pageContextId, singleFramework, pageContextIncludes) { + self = this; + self._eventNode = $('
'); + self._frameworks = []; + self._reset(); + + self._pageContextId = pageContextId; + self._pageContextIncludes = pageContextIncludes || 'children'; + if (singleFramework) { + self._frameworkId = singleFramework; + self._singleFramework = true; + } + }; + + /** @type {Array} The competencies fetched. */ + Picker.prototype._competencies = null; + /** @type {Array} The competencies that cannot be picked. */ + Picker.prototype._disallowedCompetencyIDs = null; + /** @type {Node} The node we attach the events to. */ + Picker.prototype._eventNode = null; + /** @type {Array} The list of frameworks fetched. */ + Picker.prototype._frameworks = null; + /** @type {Number} The current framework ID. */ + Picker.prototype._frameworkId = null; + /** @type {Number} The page context ID. */ + Picker.prototype._pageContextId = null; + /** @type {Number} Relevant contexts inclusion. */ + Picker.prototype._pageContextIncludes = null; + /** @type {Dialogue} The reference to the dialogue. */ + Picker.prototype._popup = null; + /** @type {String} The string we filter the competencies with. */ + Picker.prototype._searchText = ''; + /** @type {Object} The competency that was selected. */ + Picker.prototype._selectedCompetency = null; + /** @type {Boolean} Whether we can browser frameworks or not. */ + Picker.prototype._singleFramework = false; + + /** + * Hook to executed after the view is rendered. + * + * @method _afterRender + */ + Picker.prototype._afterRender = function() { + + // Initialise the tree. + new Tree(self._find('[data-enhance=linktree]'), function(target) { + var compId = target.data('id'), + valid = true; + + $.each(self._disallowedCompetencyIDs, function(i, id) { + if (id == compId) { + valid = false; + return false; + } + }); + + self._selectedCompetency = null; + if (valid) { + self._selectedCompetency = compId; + } + + // TODO Implement disabling of nodes in the tree module somehow. + if (!self._selectedCompetency) { + self._find('[data-region="competencylinktree"] [data-action="add"]').attr('disabled', 'disabled'); + } else { + self._find('[data-region="competencylinktree"] [data-action="add"]').removeAttr('disabled'); + } + }); + + // Add listener for framework change. + if (!self._singleFramework) { + self._find('[data-action="chooseframework"]').change(function(e) { + self._frameworkId = $(e.target).val(); + self._loadCompetencies().then(self._refresh); + }); + } + + // Add listener for search. + self._find('[data-region="filtercompetencies"] button').click(function(e) { + e.preventDefault(); + $(e.target).attr('disabled', 'disabled'); + self._searchText = self._find('[data-region="filtercompetencies"] input').val() || ''; + return self._refresh().always(function() { + $(e.target).removeAttr('disabled'); + }); + }); + + // Add listener for cancel. + self._find('[data-region="competencylinktree"] [data-action="cancel"]').click(function(e) { + e.preventDefault(); + self.close(); + }); + + // Add listener for add. + self._find('[data-region="competencylinktree"] [data-action="add"]').click(function(e) { + e.preventDefault(); + if (!self._selectedCompetency) { + return; + } + + self._trigger('save', { competencyId: self._selectedCompetency }); + self.close(); + }); + }; + + /** + * Close the dialogue. + * + * @method close + */ + Picker.prototype.close = function() { + self._popup.close(); + self._reset(); + }; + + /** + * Opens the picker. + * + * @method display + * @return {Promise} + */ + Picker.prototype.display = function() { + return self._render().done(function(html) { + return Str.get_string('competencypicker', 'tool_lp').done(function(title) { + self._popup = new Dialogue( + title, + html, + self._afterRender.bind(self) + ); + }); + }).fail(Notification.exception); + }; + + /** + * Fetch the competencies. + * + * @param {Number} frameworkId The frameworkId. + * @param {String} searchText Limit the competencies to those matching the text. + * @method _fetchCompetencies + * @return {Promise} + */ + Picker.prototype._fetchCompetencies = function(frameworkId, searchText) { + return Ajax.call([ + { methodname: 'tool_lp_search_competencies', args: { + searchtext: searchText, + competencyframeworkid: frameworkId + }} + ])[0].done(function(competencies) { + + function addCompetencyChildren(parent, competencies) { + for (var i = 0; i < competencies.length; i++) { + if (competencies[i].parentid == parent.id) { + parent.haschildren = true; + competencies[i].children = []; + competencies[i].haschildren = false; + parent.children[parent.children.length] = competencies[i]; + addCompetencyChildren(competencies[i], competencies); + } + } + } + + // Expand the list of competencies into a tree. + var i, tree = [], comp; + for (i = 0; i < competencies.length; i++) { + comp = competencies[i]; + if (comp.parentid == "0") { // Loose check for now, because WS returns a string. + comp.children = []; + comp.haschildren = 0; + tree[tree.length] = comp; + addCompetencyChildren(comp, competencies); + } + } + + self._competencies = tree; + + }).fail(Notification.exception); + }; + + /** + * Find a node in the dialogue. + * + * @param {String} selector + * @method _find + */ + Picker.prototype._find = function(selector) { + return $(self._popup.getContent()).find(selector); + }; + + /** + * Convenience method to get a framework object. + * + * @param {Number} fid The framework ID. + * @method _getFramework + */ + Picker.prototype._getFramework = function(fid) { + var frm; + $.each(self._frameworks, function(i, f) { + if (f.id == fid) { + frm = f; + return false; + } + }); + return frm; + }; + + /** + * Load the competencies. + * + * @method _loadCompetencies + * @return {Promise} + */ + Picker.prototype._loadCompetencies = function() { + return self._fetchCompetencies(self._frameworkId, self._searchText); + }; + + /** + * Load the frameworks. + * + * @method _loadFrameworks + * @return {Promise} + */ + Picker.prototype._loadFrameworks = function() { + var promise; + + // Quit early because we already have the data. + if (self._frameworks.length > 0) { + return $.when(); + } + + if (self._singleFramework) { + promise = Ajax.call([ + { methodname: 'tool_lp_read_competency_framework', args: { + id: this._frameworkId + }} + ])[0].then(function(framework) { + return [framework]; + }); + } else { + promise = Ajax.call([ + { methodname: 'tool_lp_list_competency_frameworks', args: { + sort: 'shortname', + context: { contextid: self._pageContextId }, + includes: self._pageContextIncludes + }} + ])[0]; + } + + return promise.done(function(frameworks) { + self._frameworks = frameworks; + }).fail(Notification.exception); + }; + + /** + * Register an event listener. + * + * @param {String} type The event type. + * @param {Function} handler The event listener. + * @method on + */ + Picker.prototype.on = function(type, handler) { + self._eventNode.on(type, handler); + }; + + /** + * Hook to executed before render. + * + * @method _preRender + * @return {Promise} + */ + Picker.prototype._preRender = function() { + return self._loadFrameworks().then(function() { + if (!self._frameworkId && self._frameworks.length > 0) { + self._frameworkId = self._frameworks[0].id; + } + + // We could not set a framework ID, that probably means there are no frameworks accessible. + if (!self._frameworkId) { + self._frameworks = []; + return $.when(); + } + + return self._loadCompetencies(); + }); + }; + + /** + * Refresh the view. + * + * @method _refresh + * @return {Promise} + */ + Picker.prototype._refresh = function() { + return self._render().then(function(html) { + self._find('[data-region="competencylinktree"]').replaceWith(html); + self._afterRender(); + }); + }; + + /** + * Render the dialogue. + * + * @method _render + * @return {Promise} + */ + Picker.prototype._render = function() { + return self._preRender().then(function() { + + if (!self._singleFramework) { + $.each(self._frameworks, function(i, framework) { + if (framework.id == self._frameworkId) { + framework.selected = true; + } else { + framework.selected = false; + } + }); + } + + var context = { + competencies: self._competencies, + framework: self._getFramework(self._frameworkId), + frameworks: self._frameworks, + search: self._searchText, + singleFramework: self._singleFramework, + }; + + return Templates.render('tool_lp/competency_picker', context); + }); + }; + + /** + * Reset the dialogue properties. + * + * This does not reset everything, just enough to reset the UI. + * + * @method _reset + */ + Picker.prototype._reset = function() { + self._competencies = []; + self._disallowedCompetencyIDs = []; + self._popup = null; + self._searchText = ''; + self._selectedCompetency = null; + }; + + /** + * Set what competencies cannot be picked. + * + * This needs to be set after reset/close. + * + * @params {Number[]} The IDs. + * @method _setDisallowedCompetencyIDs + */ + Picker.prototype.setDisallowedCompetencyIDs = function(ids) { + self._disallowedCompetencyIDs = ids; + }; + + /** + * Trigger an event. + * + * @param {String} type The type of event. + * @param {Object} The data to pass to the listeners. + * @method _reset + */ + Picker.prototype._trigger = function(type, data) { + self._eventNode.trigger(type, [data]); + }; + + return /** @alias module:tool_lp/competencypicker */ Picker; + +}); diff --git a/admin/tool/lp/amd/src/competencyselector.js b/admin/tool/lp/amd/src/competencyselector.js deleted file mode 100644 index 1d9f8cf3924..00000000000 --- a/admin/tool/lp/amd/src/competencyselector.js +++ /dev/null @@ -1,293 +0,0 @@ -// 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 . - -/** - * Competency selector handler. - * - * @module tool_lp/competencyselector - * @package tool_lp - * @copyright 2015 David Monllao - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -define(['jquery', - 'core/notification', - 'core/ajax', - 'core/templates', - 'tool_lp/dialogue', - 'core/str', - 'tool_lp/tree'], - function($, notification, ajax, templates, Dialogue, str, Ariatree) { - - return { - - // Private variables and functions. - /** @var {Object} frameworks - Site frameworks data */ - frameworks : null, - - /** @var {Dialogue} popup - Pop up where competencies are displayed. */ - popup : null, - - /** @var {Number} selectedCompetency - Currently selected competency. */ - selectedCompetency : 0, - - /** @var {Object[]} requests - Requests specified by the dependant module. */ - requests : [], - - /** @var {String} pagerender - Template to render, specified by the dependant module. */ - pagerender : null, - - /** @var {String} pageregion - Region to render in, specified by the dependant module. */ - pageregion : null, - - /** @var {Callback} addCompetencyCallback - Additional stuff to execute once the region is updated. */ - addCompetencyCallback : null, - - /** @var {Number} The page context ID. */ - pageContextId: null, - - /** - * Returns the load competency frameworks promise. - * - * Caller can act depending on whether frameworks were found or not. - * - * @param {Number} pagectxid The page context ID. - * @return {Promise} - * @method init - */ - init : function(pagectxid) { - this.pageContextId = pagectxid; - - var loadframeworks = ajax.call([ - { methodname: 'tool_lp_list_competency_frameworks', args: { - sort: 'shortname', - context: { contextid: this.pageContextId } - }} - ]); - - loadframeworks[0].done(function(frameworks) { - this.frameworks = frameworks; - }.bind(this)).fail(notification.exception); - - return loadframeworks[0]; - }, - - /** - * Sets the data required by the module. - * @param {Object[]} requests - Array of objects with the requests to send once a competency is selected. - * @param {String} pagerender - The template to render. - * @param {String} pageregion - The region to render in. - * @param {Callback} addCompetencyCallback - Additional stuff to execute once all done. - * @method setAddCompetencyRequests - */ - setAddCompetencyRequests : function(requests, pagerender, pageregion, addCompetencyCallback) { - this.requests = requests; - this.pagerender = pagerender; - this.pageregion = pageregion; - this.addCompetencyCallback = addCompetencyCallback; - }, - - /** - * Get the search text from the input field and reload the tree based on the search. - * - * @method applyFilter - * @param {Event} e The event that triggered the button. - */ - applyFilter : function(e) { - - e.preventDefault(); - - var searchInput = $('[data-region="filtercompetencies"] input'); - var searchText = searchInput.val(); - var framework = $('[data-action="chooseframework"]'); - var frameworkid = framework.val(); - - this.searchCompetencies().done(function (competencies) { - var i = 0; - - var framework = this.frameworks[0]; - for (i = 0; i < this.frameworks.length; i++) { - if (this.frameworks[i].id == frameworkid) { - framework = this.frameworks[i]; - framework.selected = true; - } else { - this.frameworks[i].selected = false; - } - } - framework.selected = true; - var context = { - framework: framework, - frameworks: this.frameworks, - competencies: competencies, - search: searchText - }; - templates.render('tool_lp/link_competencies', context).done(function(html) { - $('[data-region="competencylinktree"]').replaceWith(html); - this.initLinkCourseCompetencies(); - }.bind(this)).fail(notification.exception); - }.bind(this)).fail(notification.exception); - }, - - /** - * The link course competencies popup was just opened and we need to initialise it. - * - * @method initLinkCourseCompetencies - */ - initLinkCourseCompetencies : function() { - var requests; - - new Ariatree('[data-enhance=linktree]', function(target) { - this.selectedCompetency = target.data('id'); - }.bind(this)); - - $('[data-action="chooseframework"]').change(function(e) { - return this.applyFilter(e); - }.bind(this)); - - $('[data-region="filtercompetencies"] button').click(function(e) { - $(e.target).attr('disabled', 'disabled'); - return this.applyFilter(e); - }.bind(this)); - - $('[data-region="competencylinktree"] [data-action="cancel"]').click(function(e) { - $(e.target).attr('disabled', 'disabled'); - e.preventDefault(); - this.popup.close(); - }.bind(this)); - $('[data-region="competencylinktree"] [data-action="add"]').click(function(e) { - var btn = $(e.target); - - e.preventDefault(); - if (!this.selectedCompetency) { - return; - } - - btn.attr('disabled', 'disabled'); - - // The required callbacks and rendered templates depends on the page, but we should always - // attach the selectCompetency to the first request, the one adding data to the database. - this.requests[0].args.competencyid = this.selectedCompetency; - requests = ajax.call(this.requests); - - requests[1].done(function(context) { - templates.render(this.pagerender, context).done(function(html, js) { - this.popup.close(); - $('[data-region="' + this.pageregion + '"]').replaceWith(html); - templates.runTemplateJS(js); - - // Extra callback in case we need additional processes. - if (typeof this.addCompetencyCallback !== "undefined") { - this.addCompetencyCallback(); - } - }.bind(this)).fail(function(err) { - btn.removeAttr('disabled'); - notification.exception(err); - }); - }.bind(this)).fail(function(err) { - btn.removeAttr('disabled'); - notification.exception(err); - }); - }.bind(this)); - }, - - /** - * Turn the flat list of competencies into a tree. - * - * @method addCompetencyChildren - * @param {Object} parent The current parent node - * @param {Object[]} competencies The flat list of all nodes. - */ - addCompetencyChildren : function(parent, competencies) { - var i; - - for (i = 0; i < competencies.length; i++) { - if (competencies[i].parentid == parent.id) { - parent.haschildren = true; - competencies[i].children = []; - competencies[i].haschildren = false; - parent.children[parent.children.length] = competencies[i]; - this.addCompetencyChildren(competencies[i], competencies); - } - } - }, - - /** - * Get the search text from the input, and reload the tree. - * - * @method searchCompetencies - * @return {promise} When resolved it will contain the tree of competencies. - */ - searchCompetencies : function() { - var deferred = $.Deferred(); - var searchInput = $('[data-region="filtercompetencies"] input'); - var searchText = ''; - if (searchInput.length) { - searchText = searchInput.val(); - } - var framework = $('[data-action="chooseframework"]'); - var frameworkid = this.frameworks[0].id; - if (framework.length) { - frameworkid = framework.val(); - } - - var loadCompetencies = ajax.call([ - { methodname: 'tool_lp_search_competencies', args: { - searchtext: searchText, - competencyframeworkid: frameworkid - }} - ]); - - loadCompetencies[0].done(function (competencies) { - // Expand the list of competencies into a tree. - var i, competenciestree = []; - for (i = 0; i < competencies.length; i++) { - var onecompetency = competencies[i]; - if (onecompetency.parentid == 0) { - onecompetency.children = []; - onecompetency.haschildren = 0; - competenciestree[competenciestree.length] = onecompetency; - this.addCompetencyChildren(onecompetency, competencies); - } - } - deferred.resolve(competenciestree); - }.bind(this)).fail(function (ex) { deferred.reject(ex); }); - - return deferred.promise(); - }, - - /** - * Open a popup to choose competencies. - * - * @method openCompetencySelector - */ - openCompetencySelector : function() { - this.searchCompetencies().done(function (competencies) { - var framework = this.frameworks[0]; - framework.selected = true; - var context = { framework: framework, frameworks: this.frameworks, competencies: competencies, search: '' }; - templates.render('tool_lp/link_competencies', context).done(function(html) { - str.get_string('linkcompetencies', 'tool_lp').done(function(title) { - this.popup = new Dialogue( - title, - html, // The link UI. - function() { - this.initLinkCourseCompetencies(); - }.bind(this) - ); - }.bind(this)).fail(notification.exception); - }.bind(this)).fail(notification.exception); - }.bind(this)).fail(notification.exception); - } - }; -}); diff --git a/admin/tool/lp/amd/src/dialogue.js b/admin/tool/lp/amd/src/dialogue.js index c5b8f92f5da..176361f5c66 100644 --- a/admin/tool/lp/amd/src/dialogue.js +++ b/admin/tool/lp/amd/src/dialogue.js @@ -36,7 +36,7 @@ define(['core/yui'], function(Y) { this.yuiDialogue = null; var parent = this; - Y.use('moodle-core-notification', function () { + Y.use('moodle-core-notification', 'timers', function () { parent.yuiDialogue = new M.core.dialogue({ headerContent: title, @@ -49,7 +49,11 @@ define(['core/yui'], function(Y) { parent.yuiDialogue.after('visibleChange', function(e) { if (e.newVal) { - afterShow(parent); + // Delay the callback call to the next tick, otherwise it can happen that it is + // executed before the dialogue constructor returns. + Y.soon(function() { + afterShow(parent); + }); } }); diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php index 7bfc77ba46b..b547d9666df 100644 --- a/admin/tool/lp/lang/en/tool_lp.php +++ b/admin/tool/lp/lang/en/tool_lp.php @@ -37,6 +37,7 @@ $string['competencyframeworkcreated'] = 'Competency framework created.'; $string['competencyframeworkname'] = 'Name'; $string['competencyframeworks'] = 'Competency Frameworks'; $string['competencyframeworkupdated'] = 'Competency framework updated.'; +$string['competencypicker'] = 'Competency picker'; $string['competencyrelatedcompetencies'] = '{$a} related competencies'; $string['competencyupdated'] = 'Competency updated'; $string['configurescale'] = 'Configure scales'; @@ -66,7 +67,6 @@ $string['idnumber'] = 'Id number'; $string['invalidpersistent'] = 'Invalid persistent'; $string['itemstoadd'] = 'Items to add'; $string['learningplans'] = 'Learning plans'; -$string['linkcompetencies'] = 'Link competencies'; $string['linkcoursecompetencies'] = 'Link course competencies'; $string['linkedcourses'] = 'Linked courses'; $string['linktemplatecompetencies'] = 'Link template competencies'; diff --git a/admin/tool/lp/templates/link_competencies.mustache b/admin/tool/lp/templates/competency_picker.mustache similarity index 96% rename from admin/tool/lp/templates/link_competencies.mustache rename to admin/tool/lp/templates/competency_picker.mustache index 2f0911d1445..035ea666267 100644 --- a/admin/tool/lp/templates/link_competencies.mustache +++ b/admin/tool/lp/templates/competency_picker.mustache @@ -1,10 +1,12 @@
+{{^singleFramework}}

{{#str}}competencyframeworks, tool_lp{{/str}}

+{{/singleFramework}}

{{#str}}locatecompetency, tool_lp{{/str}}

diff --git a/admin/tool/lp/templates/manage_competencies_page.mustache b/admin/tool/lp/templates/manage_competencies_page.mustache index a2159807cdd..4ede739d35b 100644 --- a/admin/tool/lp/templates/manage_competencies_page.mustache +++ b/admin/tool/lp/templates/manage_competencies_page.mustache @@ -20,6 +20,7 @@ Classes required for JS: Data attibutes required for JS: + * data-action=add * data-enhance=tree Context variables required for this template: