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