Merge branch 'MDL-36881-m23' of git://github.com/andrewnicols/moodle into MOODLE_23_S...
[moodle.git] / enrol / yui / rolemanager / rolemanager.js
1 YUI.add('moodle-enrol-rolemanager', function(Y) {
3     var MOD_NAME                    = 'Moodle role manager',
4         MOD_USER                    = 'Moodle role user',
5         MOD_PANEL                   = 'Moodle role assignment panel',
6         USERIDS                     = 'userIds',
7         COURSEID                    = 'courseId',
8         USERID                      = 'userId',
9         CONTAINER                   = 'container',
10         CONTAINERID                 = 'containerId',
11         ASSIGNABLEROLES             = 'assignableRoles',
12         ASSIGNROLELINK              = 'assignRoleLink',
13         ASSIGNROLELINKSELECTOR      = 'assignRoleLinkSelector',
14         UNASSIGNROLELINKS           = 'unassignRoleLinks',
15         UNASSIGNROLELINKSSELECTOR   = 'unassignRoleLinksSelector',
16         MANIPULATOR                 = 'manipulator',
17         CURRENTROLES                = 'currentroles',
18         OTHERUSERS                  = 'otherusers';
20     var ROLE = function(config) {
21         ROLE.superclass.constructor.apply(this, arguments);
22     };
23     ROLE.NAME = MOD_NAME;
24     ROLE.ATTRS = {
25         containerId : {
26             validator: Y.Lang.isString
27         },
28         container : {
29             setter : function(node) {
30                 var n = Y.one(node);
31                 if (!n) {
32                     Y.fail(MOD_NAME+': invalid container set');
33                 }
34                 return n;
35             }
36         },
37         courseId : {
38             value: 0,
39             setter : function(courseId) {
40                 if (!(/^\d+$/.test(courseId))) {
41                     Y.fail(MOD_NAME+': Invalid course id specified');
42                 }
43                 return courseId;
44             }
45         },
46         userIds : {
47             validator: Y.Lang.isArray
48         },
49         assignableRoles : {
50             value : []
51         },
52         otherusers : {
53             value : false
54         }
55     };
56     Y.extend(ROLE, Y.Base, {
57         users : [],
58         roleAssignmentPanel : null,
59         panelsubmitevent : null,
60         rolesLoadedEvent : null,
61         escCloseEvent  : null,
62         initializer : function(config) {
63             var i;
64             var container = Y.one('#'+this.get(CONTAINERID));
65             container.addClass('ajaxactive');
66             this.set(CONTAINER, container);
68             var userids = this.get(USERIDS);
69             for (i in userids) {
70                 this.users[userids[i]] = new ROLEUSER({userId:userids[i],manipulator:this}).wire();
71             }
72         },
73         addRole : function(e, user) {
74             e.halt();
75             this.rolesLoadedEvent = this.on('assignablerolesloaded', function(){
76                 this.rolesLoadedEvent.detach();
77                 var panel = this._getRoleAssignmentPanel();
78                 this.panelsubmitevent = panel.on('submit', this.addRoleCallback, this);
79                 panel.hide().display(user);
80             }, this);
81             this._loadAssignableRoles();
82         },
83         addRoleCallback : function(e, roleid, userid) {
84             this.panelsubmitevent.detach();
85             var panel = this._getRoleAssignmentPanel();
86             Y.io(M.cfg.wwwroot+'/enrol/ajax.php', {
87                 method:'POST',
88                 data:'id='+this.get(COURSEID)+'&action=assign&sesskey='+M.cfg.sesskey+'&roleid='+roleid+'&user='+userid,
89                 on: {
90                     complete: function(tid, outcome, args) {
91                         try {
92                             var o = Y.JSON.parse(outcome.responseText);
93                             if (o.error) {
94                                 new M.core.ajaxException(o);
95                             } else {
96                                 this.users[userid].addRoleToDisplay(args.roleid, this.get(ASSIGNABLEROLES)[args.roleid]);
97                             }
98                         } catch (e) {
99                             new M.core.exception(e);
100                         }
101                         panel.hide();
102                     }
103                 },
104                 context:this,
105                 arguments:{
106                     roleid : roleid
107                 }
108             });
109         },
110         removeRole : function(e, user, roleid) {
111             e.halt();
112             var event = this.on('assignablerolesloaded', function(){
113                 event.detach();
114                 var s = M.str.role, confirmation = {
115                     lightbox :  true,
116                     title    :  s.confirmunassigntitle,
117                     question :  s.confirmunassign,
118                     yesLabel :  s.confirmunassignyes,
119                     noLabel  :  s.confirmunassignno
120                 };
121                 new M.core.confirm(confirmation).on('complete-yes', this.removeRoleCallback, this, user.get(USERID), roleid);
122             }, this);
123             this._loadAssignableRoles();
124         },
125         removeRoleCallback : function(e, userid, roleid) {
126             Y.io(M.cfg.wwwroot+'/enrol/ajax.php', {
127                 method:'POST',
128                 data:'id='+this.get(COURSEID)+'&action=unassign&sesskey='+M.cfg.sesskey+'&role='+roleid+'&user='+userid,
129                 on: {
130                     complete: function(tid, outcome, args) {
131                         var o;
132                         try {
133                             o = Y.JSON.parse(outcome.responseText);
134                             if (o.error) {
135                                 new M.core.ajaxException(o);
136                             } else {
137                                 this.users[userid].removeRoleFromDisplay(args.roleid);
138                             }
139                         } catch (e) {
140                             new M.core.exception(e);
141                         }
142                     }
143                 },
144                 context:this,
145                 arguments:{
146                     roleid : roleid
147                 }
148             });
149         },
150         _loadAssignableRoles : function() {
151             var c = this.get(COURSEID), params = {
152                 id : this.get(COURSEID),
153                 otherusers : (this.get(OTHERUSERS))?'true':'false',
154                 action : 'getassignable',
155                 sesskey : M.cfg.sesskey
156             };
157             Y.io(M.cfg.wwwroot+'/enrol/ajax.php', {
158                 method:'POST',
159                 data:build_querystring(params),
160                 on: {
161                     complete: function(tid, outcome, args) {
162                         try {
163                             var roles = Y.JSON.parse(outcome.responseText);
164                             this.set(ASSIGNABLEROLES, roles.response);
165                         } catch (e) {
166                             new M.core.exception(e);
167                         }
168                         this._loadAssignableRoles = function() {
169                             this.fire('assignablerolesloaded');
170                         };
171                         this._loadAssignableRoles();
172                     }
173                 },
174                 context:this
175             });
176         },
177         _getRoleAssignmentPanel : function() {
178             if (this.roleAssignmentPanel === null) {
179                 this.roleAssignmentPanel = new ROLEPANEL({manipulator:this});
180             }
181             return this.roleAssignmentPanel;
182         }
183     });
184     Y.augment(ROLE, Y.EventTarget);
186     var ROLEUSER = function(config) {
187         ROLEUSER.superclass.constructor.apply(this, arguments);
188     };
189     ROLEUSER.NAME = MOD_USER;
190     ROLEUSER.ATTRS = {
191         userId  : {
192             validator: Y.Lang.isNumber
193         },
194         manipulator : {
195             validator: Y.Lang.isObject
196         },
197         container : {
198             setter : function(node) {
199                 var n = Y.one(node);
200                 if (!n) {
201                     Y.fail(MOD_USER+': invalid container set '+node);
202                 }
203                 return n;
204             }
205         },
206         assignableroles : {
207             value : []
208         },
209         currentroles : {
210             value : [],
211             validator: Y.Lang.isArray
212         },
213         assignRoleLink : {
214             setter : function(node) {
215                 if (node===false) {
216                     return node;
217                 }
218                 var n = Y.one(node);
219                 if (!n) {
220                     Y.fail(MOD_NAME+': invalid assign role link given '+node);
221                 }
222                 return n;
223             },
224             value : false
225         },
226         assignRoleLinkSelector : {
227             value : '.assignrolelink',
228             validator : Y.Lang.isString
229         },
230         unassignRoleLinks : {
231         },
232         unassignRoleLinksSelector : {
233             value : '.unassignrolelink',
234             validator : Y.Lang.isString
235         }
236     };
237     Y.extend(ROLEUSER, Y.Base, {
238         initializer : function() {
239             var container = this.get(MANIPULATOR).get(CONTAINER).one('#user_'+this.get(USERID));
240             this.set(CONTAINER,        container);
241             var assignrole = container.one(this.get(ASSIGNROLELINKSELECTOR));
242             if (assignrole) {
243                 this.set(ASSIGNROLELINK, assignrole.ancestor());
244             }
245             this.set(UNASSIGNROLELINKS , container.all(this.get(UNASSIGNROLELINKSSELECTOR)));
246         },
247         wire : function() {
248             var container = this.get(MANIPULATOR).get(CONTAINER).one('#user_'+this.get(USERID));
249             var arl = this.get(ASSIGNROLELINK);
250             var uarls = this.get(UNASSIGNROLELINKS);
251             var m = this.get(MANIPULATOR);
252             if (arl) {
253                 arl.ancestor().on('click', m.addRole, m, this);
254             }
255             var currentroles = [];
256             if (uarls.size() > 0) {
257                 uarls.each(function(link){
258                     link.roleId = link.getAttribute('rel');
259                     link.on('click', m.removeRole, m, this, link.roleId);
260                     currentroles[link.roleId] = true;
261                 }, this);
262             }
263             container.all('.role.unchangeable').each(function(node){
264                 currentroles[node.getAttribute('rel')] = true;
265             }, this);
267             this.set(CURRENTROLES, currentroles);
268             return this;
269         },
270         _checkIfHasAllRoles : function() {
271             var roles = this.get(MANIPULATOR).get(ASSIGNABLEROLES);
272             var current = this.get(CURRENTROLES);
273             var allroles = true, i = 0;
274             for (i in roles) {
275                 if (!current[i]) {
276                     allroles = false;
277                     break;
278                 }
279             }
280             var link = this.get(ASSIGNROLELINK);
281             if (allroles) {
282                 this.get(CONTAINER).addClass('hasAllRoles');
283             } else {
284                 if (!link) {
285                     var m = this.get(MANIPULATOR);
286                     link = Y.Node.create('<div class="addrole"></div>').append(
287                         Y.Node.create('<img alt="" />').setAttribute('src', M.util.image_url('t/enroladd', 'moodle'))
288                     );
289                     link.on('click', m.addRole, m, this);
290                     this.get(CONTAINER).one('.col_role').insert(link, 0);
291                     this.set(ASSIGNROLELINK, link);
292                 }
293                 this.get(CONTAINER).removeClass('hasAllRoles');
294             }
295         },
296         addRoleToDisplay : function(roleId, roleTitle) {
297             var m = this.get(MANIPULATOR);
298             var container = this.get(CONTAINER);
299             var role = Y.Node.create('<div class="role role_'+roleId+'">'+roleTitle+'<a class="unassignrolelink"><img src="'+M.util.image_url('t/delete', 'moodle')+'" alt="" /></a></div>');
300             var link = role.one('.unassignrolelink');
301             link.roleId = roleId;
302             link.on('click', m.removeRole, m, this, link.roleId);
303             container.one('.col_role .roles').append(role);
304             this._toggleCurrentRole(link.roleId, true);
305         },
306         removeRoleFromDisplay : function(roleId) {
307             var container = this.get(CONTAINER);
308             container.all('.role_'+roleId).remove();
309             this._toggleCurrentRole(roleId, false);
310         },
311         _toggleCurrentRole : function(roleId, hasRole) {
312             var roles = this.get(CURRENTROLES);
313             if (hasRole) {
314                 roles[roleId] = true;
315             } else {
316                 roles[roleId] = false;
317             }
318             this.set(CURRENTROLES, roles);
319             this._checkIfHasAllRoles();
320         }
321     });
323     var ROLEPANEL = function(config) {
324         ROLEPANEL.superclass.constructor.apply(this, arguments);
325     };
326     ROLEPANEL.NAME = MOD_PANEL;
327     ROLEPANEL.ATTRS = {
328         elementNode : {
329             setter : function(node) {
330                 var n = Y.one(node);
331                 if (!n) {
332                     Y.fail(MOD_PANEL+': Invalid element node');
333                 }
334                 return n;
335             }
336         },
337         contentNode : {
338             setter : function(node) {
339                 var n = Y.one(node);
340                 if (!n) {
341                     Y.fail(MOD_PANEL+': Invalid content node');
342                 }
343                 return n;
344             }
345         },
346         manipulator : {
347             validator: Y.Lang.isObject
348         }
349     };
350     Y.extend(ROLEPANEL, Y.Base, {
351         user : null,
352         roles : [],
353         initializer : function() {
354             var i, m = this.get(MANIPULATOR);
355             var element = Y.Node.create('<div class="enrolpanel roleassign"><div class="container"><div class="header"><h2>'+M.str.role.assignroles+'</h2><div class="close"></div></div><div class="content"></div></div></div>');
356             var content = element.one('.content');
357             var roles = m.get(ASSIGNABLEROLES);
358             for (i in roles) {
359                 var button = Y.Node.create('<input type="button" value="'+roles[i]+'" id="add_assignable_role_'+i+'" />');
360                 button.on('click', this.submit, this, i);
361                 content.append(button);
362             }
363             Y.one(document.body).append(element);
364             this.set('elementNode', element);
365             this.set('contentNode', content);
366             element.one('.header .close').on('click', this.hide, this);
367         },
368         display : function(user) {
369             var currentroles = user.get(CURRENTROLES), node = null;
370             for (var i in currentroles) {
371                 if (currentroles[i] === true) {
372                     if (node = this.get('contentNode').one('#add_assignable_role_'+i)) {
373                         node.setAttribute('disabled', 'disabled');
374                     }
375                     this.roles.push(i);
376                 }
377             }
378             this.user = user;
379             var roles = this.user.get(CONTAINER).one('.col_role .roles');
380             var x = roles.getX() + 10;
381             var y = roles.getY() + this.user.get(CONTAINER).get('offsetHeight') - 10;
382             this.get('elementNode').setStyle('left', x).setStyle('top', y);
383             this.get('elementNode').addClass('visible');
384             this.escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
385             this.displayed = true;
386         },
387         hide : function() {
388             if (this._escCloseEvent) {
389                 this._escCloseEvent.detach();
390                 this._escCloseEvent = null;
391             }
392             var node = null;
393             for (var i in this.roles) {
394                 if (node = this.get('contentNode').one('#add_assignable_role_'+this.roles[i])) {
395                     node.removeAttribute('disabled');
396                 }
397             }
398             this.roles = [];
399             this.user = null;
400             this.get('elementNode').removeClass('visible');
401             this.displayed = false;
402             return this;
403         },
404         submit : function(e, roleid) {
405             this.fire('submit', roleid, this.user.get(USERID));
406         }
407     });
408     Y.augment(ROLEPANEL, Y.EventTarget);
410     M.enrol = M.enrol || {};
411     M.enrol.rolemanager = {
412         instance : null,
413         init : function(config) {
414             M.enrol.rolemanager.instance = new ROLE(config);
415             return M.enrol.rolemanager.instance;
416         }
417     }
419 }, '@VERSION@', {requires:['base','node','io-base','json-parse','test','moodle-enrol-notification']});