admin/tool/lp/amd/src/competencytree.js

  1. // This file is part of Moodle - http://moodle.org/
  2. //
  3. // Moodle is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // Moodle is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Handle selection changes on the competency tree.
  17. *
  18. * @module tool_lp/competencytree
  19. * @copyright 2015 Damyon Wiese <damyon@moodle.com>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. define(['core/ajax', 'core/notification', 'core/templates', 'tool_lp/tree', 'tool_lp/competency_outcomes', 'jquery'],
  23. function(ajax, notification, templates, Ariatree, CompOutcomes, $) {
  24. // Private variables and functions.
  25. /** @var {Object[]} competencies - Cached list of competencies */
  26. var competencies = {};
  27. /** @var {Number} competencyFrameworkId - The current framework id */
  28. var competencyFrameworkId = 0;
  29. /** @var {String} competencyFrameworkShortName - The current framework short name */
  30. var competencyFrameworkShortName = '';
  31. /** @var {String} treeSelector - The selector for the root of the tree. */
  32. var treeSelector = '';
  33. /** @var {String} currentNodeId - The data-id of the current node in the tree. */
  34. var currentNodeId = '';
  35. /** @var {Boolean} competencyFramworkCanManage - Can manage the competencies framework */
  36. var competencyFramworkCanManage = false;
  37. /**
  38. * Build a tree from the flat list of competencies.
  39. * @param {Object} parent The parent competency.
  40. * @param {Array} all The list of all competencies.
  41. */
  42. var addChildren = function(parent, all) {
  43. var i = 0;
  44. var current = false;
  45. parent.haschildren = false;
  46. parent.children = [];
  47. for (i = 0; i < all.length; i++) {
  48. current = all[i];
  49. if (current.parentid == parent.id) {
  50. parent.haschildren = true;
  51. parent.children.push(current);
  52. addChildren(current, all);
  53. }
  54. }
  55. };
  56. /**
  57. * Load the list of competencies via ajax. Competencies are filtered by the searchtext.
  58. * @param {String} searchtext The text to filter on.
  59. * @return {promise}
  60. */
  61. var loadCompetencies = function(searchtext) {
  62. var deferred = $.Deferred();
  63. templates.render('tool_lp/loading', {}).done(function(loadinghtml, loadingjs) {
  64. templates.replaceNodeContents($(treeSelector), loadinghtml, loadingjs);
  65. var promises = ajax.call([{
  66. methodname: 'core_competency_search_competencies',
  67. args: {
  68. searchtext: searchtext,
  69. competencyframeworkid: competencyFrameworkId
  70. }
  71. }]);
  72. promises[0].done(function(result) {
  73. competencies = {};
  74. var i = 0;
  75. for (i = 0; i < result.length; i++) {
  76. competencies[result[i].id] = result[i];
  77. }
  78. var children = [];
  79. var competency = false;
  80. for (i = 0; i < result.length; i++) {
  81. competency = result[i];
  82. if (parseInt(competency.parentid, 10) === 0) {
  83. children.push(competency);
  84. addChildren(competency, result);
  85. }
  86. }
  87. var context = {
  88. shortname: competencyFrameworkShortName,
  89. canmanage: competencyFramworkCanManage,
  90. competencies: children
  91. };
  92. templates.render('tool_lp/competencies_tree_root', context).done(function(html, js) {
  93. templates.replaceNodeContents($(treeSelector), $(html).html(), js);
  94. var tree = new Ariatree(treeSelector, false);
  95. if (currentNodeId) {
  96. var node = $(treeSelector).find('[data-id=' + currentNodeId + ']');
  97. if (node.length) {
  98. tree.selectItem(node);
  99. tree.updateFocus(node);
  100. }
  101. }
  102. deferred.resolve(competencies);
  103. }).fail(deferred.reject);
  104. }).fail(deferred.reject);
  105. });
  106. return deferred.promise();
  107. };
  108. /**
  109. * Whenever the current item in the tree is changed - remember the "id".
  110. * @param {Event} evt
  111. * @param {Object} params The parameters for the event (This is the selected node).
  112. */
  113. var rememberCurrent = function(evt, params) {
  114. var node = params.selected;
  115. currentNodeId = node.attr('data-id');
  116. };
  117. return /** @alias module:tool_lp/competencytree */ {
  118. // Public variables and functions.
  119. /**
  120. * Initialise the tree.
  121. *
  122. * @param {Number} id The competency framework id.
  123. * @param {String} shortname The framework shortname
  124. * @param {String} search The current search string
  125. * @param {String} selector The selector for the tree div
  126. * @param {Boolean} canmanage Can manage the competencies
  127. * @param {Number} competencyid The id of the competency to show first
  128. */
  129. init: function(id, shortname, search, selector, canmanage, competencyid) {
  130. competencyFrameworkId = id;
  131. competencyFrameworkShortName = shortname;
  132. competencyFramworkCanManage = canmanage;
  133. treeSelector = selector;
  134. loadCompetencies(search).fail(notification.exception);
  135. if (competencyid > 0) {
  136. currentNodeId = competencyid;
  137. }
  138. this.on('selectionchanged', rememberCurrent);
  139. },
  140. /**
  141. * Add an event handler for custom events emitted by the tree.
  142. *
  143. * @param {String} eventname The name of the event - only "selectionchanged" for now
  144. * @param {Function} handler The handler for the event.
  145. */
  146. on: function(eventname, handler) {
  147. // We can't use the tree on function directly
  148. // because the tree gets rebuilt whenever the search string changes,
  149. // instead we attach the listner to the root node of the tree which never
  150. // gets destroyed (same as "on()" code in the tree.js).
  151. $(treeSelector).on(eventname, handler);
  152. },
  153. /**
  154. * Get the children of a competency.
  155. *
  156. * @param {Number} id The competency ID.
  157. * @return {Array}
  158. * @method getChildren
  159. */
  160. getChildren: function(id) {
  161. var children = [];
  162. $.each(competencies, function(index, competency) {
  163. if (competency.parentid == id) {
  164. children.push(competency);
  165. }
  166. });
  167. return children;
  168. },
  169. /**
  170. * Get the competency framework id this model was initiliased with.
  171. *
  172. * @return {Number}
  173. */
  174. getCompetencyFrameworkId: function() {
  175. return competencyFrameworkId;
  176. },
  177. /**
  178. * Get a competency by id
  179. *
  180. * @param {Number} id The competency id
  181. * @return {Object}
  182. */
  183. getCompetency: function(id) {
  184. return competencies[id];
  185. },
  186. /**
  187. * Get the competency level.
  188. *
  189. * @param {Number} id The competency ID.
  190. * @return {Number}
  191. */
  192. getCompetencyLevel: function(id) {
  193. var competency = this.getCompetency(id),
  194. level = competency.path.replace(/^\/|\/$/g, '').split('/').length;
  195. return level;
  196. },
  197. /**
  198. * Whether a competency has children.
  199. *
  200. * @param {Number} id The competency ID.
  201. * @return {Boolean}
  202. * @method hasChildren
  203. */
  204. hasChildren: function(id) {
  205. return this.getChildren(id).length > 0;
  206. },
  207. /**
  208. * Does the competency have a rule?
  209. *
  210. * @param {Number} id The competency ID.
  211. * @return {Boolean}
  212. */
  213. hasRule: function(id) {
  214. var comp = this.getCompetency(id);
  215. if (comp) {
  216. return comp.ruleoutcome != CompOutcomes.OUTCOME_NONE
  217. && comp.ruletype;
  218. }
  219. return false;
  220. },
  221. /**
  222. * Reload all the page competencies framework competencies.
  223. * @method reloadCompetencies
  224. * @return {Promise}
  225. */
  226. reloadCompetencies: function() {
  227. return loadCompetencies('').fail(notification.exception);
  228. },
  229. /**
  230. * Get all competencies for this framework.
  231. *
  232. * @return {Object[]}
  233. */
  234. listCompetencies: function() {
  235. return competencies;
  236. },
  237. };
  238. });