source: trunk/admin/themes/default/template/user_list.tpl @ 26052

Last change on this file since 26052 was 26052, checked in by plg, 10 years ago

feature 1668, user manager redesign: do not let the administrator try to
modify the status of protected users (pwg.users.setInfo will deactivate
status change for these users anyway)

  • Property svn:eol-style set to LF
File size: 40.6 KB
Line 
1{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
2
3{combine_script id='jquery.dataTables' load='footer' path='themes/default/js/plugins/jquery.dataTables.js'}
4{combine_css path="themes/default/js/plugins/datatables/css/jquery.dataTables.css"}
5
6{combine_script id='jquery.chosen' load='footer' path='themes/default/js/plugins/chosen.jquery.min.js'}
7{combine_css path="themes/default/js/plugins/chosen.css"}
8
9{combine_script id='jquery.ui.slider' require='jquery.ui' load='footer' path='themes/default/js/ui/minified/jquery.ui.slider.min.js'}
10{combine_css path="themes/default/js/ui/theme/jquery.ui.slider.css"}
11
12{footer_script}
13var selectedMessage_pattern = "{'%d of %d users selected'|translate|escape:javascript}";
14var selectedMessage_none = "{'No user selected of %d users'|translate|escape:javascript}";
15var selectedMessage_all = "{'All %d users are selected'|translate|escape:javascript}";
16var applyOnDetails_pattern = "{'on the %d selected users'|translate|escape:javascript}";
17var newUser_pattern = "✔ {'User %s added'|translate|escape:javascript}";
18var registeredOn_pattern = "{'Registered on %s, %s.'|translate|escape:javascript}";
19var lastVisit_pattern = "{'Last visit on %s, %s.'|translate|escape:javascript}";
20var missingConfirm = "{'You need to confirm deletion'|translate|escape:javascript}";
21var missingUsername = "{'Please, enter a login'|translate|escape:javascript}";
22
23var allUsers = [{$all_users}];
24var selection = [{$selection}];
25var pwg_token = "{$PWG_TOKEN}";
26
27var protectedUsers = [{$protected_users}];
28var guestUser = {$guest_user};
29
30var truefalse = {
31  true:"{'Yes'|translate}",
32  false:"{'No'|translate}",
33};
34{/footer_script}
35
36{footer_script}{literal}
37jQuery(document).ready(function() {
38  /**
39   * Add user
40   */
41  jQuery("#addUser").click(function() {
42    jQuery("#addUserForm").toggle();
43    jQuery("#showAddUser .infos").hide();
44    jQuery("input[name=username]").focus();
45    return false;
46  });
47
48  jQuery("#addUserClose").click(function() {
49    jQuery("#addUserForm").hide();
50    return false;
51  });
52
53  jQuery("#addUserForm").submit(function() {
54    jQuery.ajax({
55      url: "ws.php?format=json&method=pwg.users.add",
56      type:"POST",
57      data: jQuery(this).serialize(),
58      beforeSend: function() {
59        jQuery("#addUserForm .errors").hide();
60
61        if (jQuery("input[name=username]").val() == "") {
62          jQuery("#addUserForm .errors").html('✘ '+missingUsername).show();
63          return false;
64        }
65
66        jQuery("#addUserForm .loading").show();
67      },
68      success:function(data) {
69        oTable.fnDraw();
70        jQuery("#addUserForm .loading").hide();
71
72        var data = jQuery.parseJSON(data);
73        if (data.stat == 'ok') {
74          jQuery("#addUserForm input[type=text], #addUserForm input[type=password]").val("");
75
76          var new_user = data.result.users[0];
77          allUsers.push(parseInt(new_user.id));
78          jQuery("#showAddUser .infos").html(sprintf(newUser_pattern, new_user.username)).show();
79          checkSelection();
80
81          jQuery("#addUserForm").hide();
82        }
83        else {
84          jQuery("#addUserForm .errors").html('✘ '+data.message).show();
85        }
86      },
87      error:function(XMLHttpRequest, textStatus, errorThrows) {
88        jQuery("#addUserForm .loading").hide();
89      }
90    });
91
92    return false;
93  });
94
95  /**
96   * Table with users
97   */
98  /**
99   * find the key from a value in the startStopValues array
100   */
101  function getSliderKeyFromValue(value, values) {
102    for (var key in values) {
103      if (values[key] >= value) {
104        return key;
105      }
106    }
107    return 0;
108  }
109
110  var recent_period_values = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,30,40,50,60,80,99];
111
112  function getRecentPeriodInfoFromIdx(idx) {
113    return sprintf(
114      "{/literal}{'%d days'|@translate}{literal}",
115      recent_period_values[idx]
116    );
117  }
118
119  var nb_image_page_values = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,35,40,45,50,60,70,80,90,100,200,300,500,999];
120
121  function getNbImagePageInfoFromIdx(idx) {
122    return sprintf(
123      "{/literal}{'%d photos per page'|@translate}{literal}",
124      nb_image_page_values[idx]
125    );
126  }
127
128  /* nb_image_page slider */
129  var nb_image_page_init = getSliderKeyFromValue(jQuery('#action_nb_image_page input[name=nb_image_page]').val(), nb_image_page_values);
130 
131  jQuery('#action_nb_image_page .nb_image_page_infos').html(getNbImagePageInfoFromIdx(nb_image_page_init));
132 
133  jQuery('#action_nb_image_page .nb_image_page').slider({
134    range: "min",
135    min: 0,
136    max: nb_image_page_values.length - 1,
137    value: nb_image_page_init,
138    slide: function( event, ui ) {
139      jQuery('#action_nb_image_page .nb_image_page_infos').html(getNbImagePageInfoFromIdx(ui.value));
140    },
141    stop: function( event, ui ) {
142      jQuery('#action_nb_image_page input[name=nb_image_page]').val(nb_image_page_values[ui.value]).trigger('change');
143    }
144  });
145
146  /* recent_period slider */
147  var recent_period_init = getSliderKeyFromValue(jQuery('#action_recent_period input[name=recent_period]').val(), recent_period_values);
148  jQuery('#action_recent_period .recent_period_infos').html(getRecentPeriodInfoFromIdx(recent_period_init));
149 
150  jQuery('#action_recent_period .recent_period').slider({
151    range: "min",
152    min: 0,
153    max: recent_period_values.length - 1,
154    value: recent_period_init,
155    slide: function( event, ui ) {
156      jQuery('#action_recent_period .recent_period_infos').html(getRecentPeriodInfoFromIdx(ui.value));
157    },
158    stop: function( event, ui ) {
159      jQuery('#action_recent_period input[name=recent_period]').val(recent_period_values[ui.value]).trigger('change');
160    }
161  });
162
163  /* Formating function for row details */
164  function fnFormatDetails(oTable, nTr) {
165    var userId = oTable.fnGetData(nTr)[0];
166    console.log("userId = "+userId);
167    var sOut = null;
168
169    jQuery.ajax({
170      url: "ws.php?format=json&method=pwg.users.getList",
171      type:"POST",
172      data: {
173        user_id: userId,
174        display: "all",
175      },
176      success:function(data) {
177        jQuery("#user"+userId+" .loading").hide();
178
179        var data = jQuery.parseJSON(data);
180        if (data.stat == 'ok') {
181          var user = data.result.users[0];
182
183          var userDetails = '<form>';
184          userDetails += '<div class="userActions">';
185
186          if (parseInt(userId) != guestUser) {
187            userDetails += '<span class="changePasswordDone infos" style="display:none">&#x2714; {/literal}{'Password updated'|translate|escape:javascript}{literal}</span>';
188            userDetails += '<span class="changePassword" style="display:none">{/literal}{'New password'|translate}{literal} <input type="text"> <a href="#" class="buttonLike updatePassword"><img src="themes/default/images/ajax-loader-small.gif" style="margin-bottom:-1px;margin-left:1px;display:none;"><span class="text">{/literal}{'Submit'|translate|escape:javascript}{literal}</span></a> <a href="#" class="cancel">{/literal}{'Cancel'|translate|escape:javascript}{literal}</a></span>';
189            userDetails += '<a class="icon-key changePasswordOpen" href="#">{/literal}{'Change password'|translate|escape:javascript}{literal}</a>';
190            userDetails += '<br>';
191          }
192
193          userDetails += '<a target="_blank" href="admin.php?page=user_perm&amp;user_id='+userId+'" class="icon-lock">{/literal}{'Permissions'|translate|escape:javascript}{literal}</a>';
194
195          if (protectedUsers.indexOf(parseInt(userId)) == -1) {
196            userDetails += '<br><span class="userDelete"><img class="loading" src="themes/default/images/ajax-loader-small.gif" style="display:none;"><a href="#" class="icon-trash" data-user_id="'+userId+'">{/literal}{'Delete'|translate|escape:javascript}{literal}</a></span>';
197          }
198
199          userDetails += '</div>';
200
201          userDetails += '<span class="changeUsernameOpen"><strong class="username">'+user.username+'</strong>';
202
203          if (parseInt(userId) != guestUser) {
204            userDetails += ' <a href="#" class="icon-pencil">{/literal}{'Change username'|translate|escape:javascript}{literal}</a></span>';
205            userDetails += '<span class="changeUsername" style="display:none">';
206            userDetails += '<input type="text"> <a href="#" class="buttonLike updateUsername"><img src="themes/default/images/ajax-loader-small.gif" style="margin-bottom:-1px;margin-left:1px;display:none;"><span class="text">{/literal}{'Submit'|translate}{literal}</span></a> <a href="#" class="cancel">{/literal}{'Cancel'|translate|escape:javascript}{literal}</a>';
207          }
208
209          userDetails += '</span>';
210
211          userDetails += '<div class="userStats">';
212          userDetails += sprintf(registeredOn_pattern, user.registration_date_string, user.registration_date_since);
213
214          if (typeof user.last_visit != 'undefined') {
215            userDetails += '<br>'+sprintf(lastVisit_pattern, user.last_visit_string, user.last_visit_since);
216          }
217
218          userDetails += '</div>';
219          userDetails += '<div class="userPropertiesContainer">';
220          userDetails += '<input type="hidden" name="user_id" value="'+user.id+'">';
221          userDetails += '<div class="userPropertiesSet">';
222          userDetails += '<div class="userPropertiesSetTitle">{/literal}{'Properties'|translate}{literal}</div>';
223
224          userDetails += '<div class="userProperty"><strong>{/literal}{'Email address'|translate}{literal}</strong>';
225          userDetails += '<br>';
226          if (parseInt(userId) != guestUser) {
227            userDetails += '<input name="email" type="text" value="'+ (user.email||'') +'">';
228          }
229          else {
230            userDetails += '{/literal}{'N/A'|translate}{literal}';
231          }
232          userDetails += '</div>';
233
234          userDetails += '<div class="userProperty"><strong>{/literal}{'Status'|translate}{literal}</strong>';
235          userDetails += '<br>';
236
237          if (protectedUsers.indexOf(parseInt(userId)) == -1) {
238            userDetails += '<select name="status">';
239            jQuery("#action select[name=status] option").each(function() {
240              var selected = '';
241              if (user.status == jQuery(this).val()) {
242                selected = ' selected="selected"';
243              }
244              userDetails += '<option value="'+jQuery(this).val()+'"'+selected+'>'+jQuery(this).html()+'</option>';
245            });
246            userDetails += '</select>';
247          }
248          else {
249            jQuery("#action select[name=status] option").each(function() {
250              if (user.status == jQuery(this).val()) {
251                userDetails += jQuery(this).html();
252              }
253            });
254          }
255          userDetails += '</div>';
256
257          userDetails += '<div class="userProperty"><strong>{/literal}{'Privacy level'|translate}{literal}</strong>';
258          userDetails += '<br><select name="level">';
259          jQuery("#action select[name=level] option").each(function() {
260            var selected = '';
261            if (user.level == jQuery(this).val()) {
262              selected = ' selected="selected"';
263            }
264            userDetails += '<option value="'+jQuery(this).val()+'"'+selected+'>'+jQuery(this).html()+'</option>';
265          });
266          userDetails += '</select></div>';
267
268          var checked = '';
269          if (user.enabled_high == 'true') {
270            checked = ' checked="checked"';
271          }
272          userDetails += '<div class="userProperty"><label><input type="checkbox" name="enabled_high"'+checked+'> <strong>{/literal}{'High definition enabled'|translate}{literal}</strong></label>';
273          userDetails += '</div>';
274
275          userDetails += '<div class="userProperty"><strong>{/literal}{'Groups'|translate}{literal}</strong>';
276          userDetails += '<br><select multiple class="chzn-select" style="width:340px;" name="group_id[]">';
277          jQuery("#action select[name=associate] option").each(function() {
278            var selected = '';
279            if (user.groups.indexOf( parseInt(jQuery(this).val()) ) != -1) {
280              selected = ' selected="selected"';
281            }
282            userDetails += '<option value="'+jQuery(this).val()+'"'+selected+'>'+jQuery(this).html()+'</option>';
283          });
284          userDetails += '</select></div>';
285          // userDetails += '<br>'+user.groups.join(",")+'</div>';
286
287          userDetails += '</div><div class="userPropertiesSet userPrefs">';
288          userDetails += '<div class="userPropertiesSetTitle">{/literal}{'Preferences'|translate}{literal}</div>';
289
290          userDetails += '<div class="userProperty"><strong class="nb_image_page_infos"></strong>';
291          userDetails += '<div class="nb_image_page"></div>';
292          userDetails += '<input type="hidden" name="nb_image_page" value="'+user.nb_image_page+'">';
293          userDetails += '</div>';
294
295          userDetails += '<div class="userProperty"><strong>{/literal}{'Theme'|translate|escape:javascript}{literal}</strong>';
296          userDetails += '<br><select name="theme">';
297          jQuery("#action select[name=theme] option").each(function() {
298            var selected = '';
299            if (user.theme == jQuery(this).val()) {
300              selected = ' selected="selected"';
301            }
302            userDetails += '<option value="'+jQuery(this).val()+'"'+selected+'>'+jQuery(this).html()+'</option>';
303          });
304          userDetails += '</select></div>';
305
306          userDetails += '<div class="userProperty"><strong>{/literal}{'Language'|translate}{literal}</strong>';
307          userDetails += '<br><select name="language">';
308          jQuery("#action select[name=language] option").each(function() {
309            var selected = '';
310            if (user.language == jQuery(this).val()) {
311              selected = ' selected="selected"';
312            }
313            userDetails += '<option value="'+jQuery(this).val()+'"'+selected+'>'+jQuery(this).html()+'</option>';
314          });
315          userDetails += '</select></div>';
316
317          userDetails += '<div class="userProperty"><strong>{/literal}{'Recent period'|translate}{literal}</strong> <span class="recent_period_infos"></span>';
318          userDetails += '<div class="recent_period"></div>';
319          userDetails += '<input type="hidden" name="recent_period" value="'+user.recent_period+'">';
320          userDetails += '</div>';
321
322          var checked = '';
323          if (user.expand == 'true') {
324            checked = ' checked="checked"';
325          }
326          userDetails += '<div class="userProperty"><label><input type="checkbox" name="expand"'+checked+'> <strong>{/literal}{'Expand all albums'|translate}{literal}</strong></label>';
327          userDetails += '</div>';
328
329          var checked = '';
330          if (user.show_nb_comments == 'true') {
331            checked = ' checked="checked"';
332          }
333          userDetails += '<div class="userProperty"><label><input type="checkbox" name="show_nb_comments"'+checked+'> <strong>{/literal}{'Show number of comments'|translate}{literal}</strong></label>';
334          userDetails += '</div>';
335
336          var checked = '';
337          if (user.show_nb_hits == 'true') {
338            checked = ' checked="checked"';
339          }
340          userDetails += '<div class="userProperty"><label><input type="checkbox" name="show_nb_hits"'+checked+'> <strong>{/literal}{'Show number of hits'|translate}{literal}</strong></label>';
341          userDetails += '</div>';
342          userDetails += '</div>';
343          userDetails += '<div style="clear:both"></div></div>';
344
345          userDetails += '<span class="infos propertiesUpdateDone" style="display:none">&#x2714; ';
346          userDetails += sprintf("{/literal}{'User %s updated'|translate|escape:javascript}{literal}", user.username);
347          userDetails += '</span>';
348          userDetails += '<input type="submit" value="{/literal}{'Update user'|translate|escape:javascript}{literal}" style="display:none;" data-user_id="'+userId+'">';
349          userDetails += '<img class="submitWait" src="themes/default/images/ajax-loader-small.gif" style="display:none">'
350          userDetails += '</form>';
351
352          jQuery("#user"+userId).append(userDetails);
353          jQuery(".chzn-select").chosen();
354
355          /* nb_image_page slider */
356          var nb_image_page_init = getSliderKeyFromValue(jQuery('#user'+userId+' input[name=nb_image_page]').val(), nb_image_page_values);
357         
358          jQuery('#user'+userId+' .nb_image_page_infos').html(getNbImagePageInfoFromIdx(nb_image_page_init));
359         
360          jQuery('#user'+userId+' .nb_image_page').slider({
361            range: "min",
362            min: 0,
363            max: nb_image_page_values.length - 1,
364            value: nb_image_page_init,
365            slide: function( event, ui ) {
366              jQuery('#user'+userId+' .nb_image_page_infos').html(getNbImagePageInfoFromIdx(ui.value));
367            },
368            stop: function( event, ui ) {
369              jQuery('#user'+userId+' input[name=nb_image_page]').val(nb_image_page_values[ui.value]).trigger('change');
370            }
371          });
372
373          /* recent_period slider */
374          var recent_period_init = getSliderKeyFromValue(jQuery('#user'+userId+' input[name=recent_period]').val(), recent_period_values);
375          jQuery('#user'+userId+' .recent_period_infos').html(getRecentPeriodInfoFromIdx(recent_period_init));
376         
377          jQuery('#user'+userId+' .recent_period').slider({
378            range: "min",
379            min: 0,
380            max: recent_period_values.length - 1,
381            value: recent_period_init,
382            slide: function( event, ui ) {
383              jQuery('#user'+userId+' .recent_period_infos').html(getRecentPeriodInfoFromIdx(ui.value));
384            },
385            stop: function( event, ui ) {
386              jQuery('#user'+userId+' input[name=recent_period]').val(recent_period_values[ui.value]).trigger('change');
387            }
388          });
389        }
390        else {
391          console.log('error loading user details');
392        }
393      },
394      error:function(XMLHttpRequest, textStatus, errorThrows) {
395        console.log('technical error loading user details');
396      }
397    });
398 
399    return '<div id="user'+userId+'" class="userProperties"><img class="loading" src="themes/default/images/ajax-loader-small.gif"></div>';
400  }
401
402  /* change password */
403  jQuery(document).on('click', '.changePasswordOpen',  function() {
404    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
405
406    jQuery(this).hide();
407    jQuery('#user'+userId+' .changePasswordDone').hide();
408    jQuery('#user'+userId+' .changePassword').show();
409    jQuery('#user'+userId+' .changePassword input[type=text]').focus();
410
411    return false;
412  });
413
414  jQuery(document).on('click', '.changePassword a.updatePassword',  function() {
415    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
416
417    jQuery('#user'+userId+' .changePassword a .text').hide();
418    jQuery('#user'+userId+' .changePassword a img').show();
419
420    jQuery.ajax({
421      url: "ws.php?format=json&method=pwg.users.setInfo",
422      type:"POST",
423      data: {
424        user_id:userId,
425        password: jQuery('#user'+userId+' .changePassword input[type=text]').val()
426      },
427      beforeSend: function() {
428        jQuery('#user'+userId+' .changePassword input[type=text]').val("");
429      },
430      success:function(data) {
431        jQuery('#user'+userId+' .changePassword a .text').show();
432        jQuery('#user'+userId+' .changePassword a img').hide();
433        jQuery('#user'+userId+' .changePassword').hide();
434        jQuery('#user'+userId+' .changePasswordOpen').show();
435        jQuery('#user'+userId+' .changePasswordDone').show();
436      },
437      error:function(XMLHttpRequest, textStatus, errorThrows) {
438      }
439    });
440
441    return false;
442  });
443
444  jQuery(document).on('click', '.changePassword a.cancel',  function() {
445    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
446
447    jQuery('#user'+userId+' .changePassword').hide();
448    jQuery('#user'+userId+' .changePasswordOpen').show();
449
450    return false;
451  });
452
453  /* change username */
454  jQuery(document).on('click', '.changeUsernameOpen a',  function() {
455    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
456    var username = jQuery('#user'+userId+' .username').html();
457
458    jQuery('#user'+userId+' .changeUsernameOpen').hide();
459    jQuery('#user'+userId+' .changeUsername').show();
460    jQuery('#user'+userId+' .changeUsername input[type=text]').val(username).focus();
461
462    return false;
463  });
464
465  jQuery(document).on('click', 'a.updateUsername',  function() {
466    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
467
468    jQuery('#user'+userId+' .changeUsername a .text').hide();
469    jQuery('#user'+userId+' .changeUsername a img').show();
470
471    jQuery.ajax({
472      url: "ws.php?format=json&method=pwg.users.setInfo",
473      type:"POST",
474      data: {
475        user_id:userId,
476        username: jQuery('#user'+userId+' .changeUsername input[type=text]').val()
477      },
478      success:function(data) {
479        jQuery('#user'+userId+' .changeUsername a .text').show();
480        jQuery('#user'+userId+' .changeUsername a img').hide();
481        jQuery('#user'+userId+' .changeUsername').hide();
482        jQuery('#user'+userId+' .changeUsernameOpen').show();
483
484        var data = jQuery.parseJSON(data);
485        jQuery('#user'+userId+' .username').html(data.result.users[0].username);
486      },
487      error:function(XMLHttpRequest, textStatus, errorThrows) {
488      }
489    });
490
491    return false;
492  });
493
494  jQuery(document).on('click', '.changeUsername a.cancel',  function() {
495    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
496
497    jQuery('#user'+userId+' .changeUsername').hide();
498    jQuery('#user'+userId+' .changeUsernameOpen').show();
499
500    return false;
501  });
502
503  /* display the "save" button when a field changes */
504  jQuery(document).on('change', '.userProperties input, .userProperties select',  function() {
505    var userId = jQuery(this).parentsUntil('form').parent().find('input[name=user_id]').val();
506
507    jQuery('#user'+userId+' input[type=submit]').show();
508    jQuery('#user'+userId+' .propertiesUpdateDone').hide();
509  });
510
511  /* delete user */
512  jQuery(document).on('click', '.userDelete a',  function() {
513    if (!confirm("{/literal}{'Are you sure?'|translate|escape:javascript}{literal}")) {
514      return false;
515    }
516
517    var userId = jQuery(this).data('user_id');
518    var username = jQuery('#user'+userId+' .username').html();
519
520    jQuery.ajax({
521      url: "ws.php?format=json&method=pwg.users.delete",
522      type:"POST",
523      data: {
524        user_id:userId,
525        pwg_token:pwg_token
526      },
527      beforeSend: function() {
528        jQuery('#user'+userId+' .userDelete .loading').show();
529      },
530      success:function(data) {
531        oTable.fnDraw();
532        jQuery('#showAddUser .infos').html('&#x2714; User '+username+' deleted').show();
533      },
534      error:function(XMLHttpRequest, textStatus, errorThrows) {
535        jQuery('#user'+userId+' .userDelete .loading').hide();
536      }
537    });
538
539    return false;
540  });
541
542  jQuery(document).on('click', '.userProperties input[type=submit]',  function() {
543    var userId = jQuery(this).data('user_id');
544
545    var formData = jQuery('#user'+userId+' form').serialize();
546
547    if (jQuery('#user'+userId+' form select[name="group_id[]"] option:selected').length == 0) {
548      formData += '&group_id=-1';
549    }
550
551    if (!jQuery('#user'+userId+' form input[name=enabled_high]').is(':checked')) {
552      formData += '&enabled_high=false';
553    }
554
555    if (!jQuery('#user'+userId+' form input[name=expand]').is(':checked')) {
556      formData += '&expand=false';
557    }
558
559    if (!jQuery('#user'+userId+' form input[name=show_nb_hits]').is(':checked')) {
560      formData += '&show_nb_hits=false';
561    }
562
563    if (!jQuery('#user'+userId+' form input[name=show_nb_comments]').is(':checked')) {
564      formData += '&show_nb_comments=false';
565    }
566
567    jQuery.ajax({
568      url: "ws.php?format=json&method=pwg.users.setInfo",
569      type:"POST",
570      data: formData,
571      beforeSend: function() {
572        jQuery('#user'+userId+' .submitWait').show();
573      },
574      success:function(data) {
575        jQuery('#user'+userId+' .submitWait').hide();
576        jQuery('#user'+userId+' input[type=submit]').hide();
577        jQuery('#user'+userId+' .propertiesUpdateDone').show();
578      },
579      error:function(XMLHttpRequest, textStatus, errorThrows) {
580        jQuery('#user'+userId+' .submitWait').hide();
581      }
582    });
583
584    return false;
585  });
586
587  /* Add event listener for opening and closing details
588   * Note that the indicator for showing which row is open is not controlled by DataTables,
589   * rather it is done here
590   */
591  jQuery(document).on('click', '#userList tbody td .openUserDetails',  function() {
592    var nTr = this.parentNode.parentNode;
593    if (jQuery(this).hasClass('icon-angle-circled-up')) {
594      /* This row is already open - close it */
595      jQuery(this).removeClass('icon-angle-circled-up').addClass('icon-angle-circled-down').attr('title', 'Open user details');
596      oTable.fnClose( nTr );
597    }
598    else {
599      /* Open this row */
600      jQuery(this).removeClass('icon-angle-circled-down').addClass('icon-angle-circled-up').attr('title', 'Close user details');
601      oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
602    }
603  });
604
605
606  /* first column must be prefixed with the open/close icon */
607  var aoColumns = [
608    {
609      'bVisible':false
610    },
611    {
612      "mRender": function(data, type, full) {
613        return '<span title="Open user details" class="icon-angle-circled-down openUserDetails"></span> <label><input type="checkbox" data-user_id="'+full[0]+'"> '+data+'</label>';
614      }
615    }
616  ];
617
618  for (i=2; i<jQuery("#userList thead tr th").length; i++) {
619    aoColumns.push(null);
620  }
621
622  var oTable = jQuery('#userList').dataTable({
623    "iDisplayLength": 10,
624    "bDeferRender": true,
625    "bProcessing": true,
626    "bServerSide": true,
627                "sServerMethod": "POST",
628    "sAjaxSource": "admin/user_list_backend.php",
629    "oLanguage": {
630      "sProcessing": "{/literal}{'Loading...'|translate|escape:'javascript'}{literal}",
631      "sLengthMenu": sprintf("{/literal}{'Show %s users'|translate|escape:'javascript'}{literal}", '_MENU_'),
632      "sZeroRecords": "{/literal}{'No matching user found'|translate|escape:'javascript'}{literal}",
633      "sInfo": sprintf("{/literal}{'Showing %s to %s of %s users'|translate|escape:'javascript'}{literal}", '_START_', '_END_', '_TOTAL_'),
634      "sInfoEmpty": "{/literal}{'No matching user found'|translate|escape:'javascript'}{literal}",
635      "sInfoFiltered": sprintf("{/literal}{'(filtered from %s total users)'|translate|escape:'javascript'}{literal}", '_MAX_'),
636      "sSearch": '<span class="icon-search"></span>'+"{/literal}{'Search'|translate|escape:'javascript'}{literal}",
637      "sLoadingRecords": "{/literal}{'Loading...'|translate|escape:'javascript'}{literal}",
638      "oPaginate": {
639          "sFirst":    "{/literal}{'First'|translate|escape:'javascript'}{literal}",
640          "sPrevious": '← '+"{/literal}{'Previous'|translate|escape:'javascript'}{literal}",
641          "sNext":     "{/literal}{'Next'|translate|escape:'javascript'}{literal}"+' →',
642          "sLast":     "{/literal}{'Last'|translate|escape:'javascript'}{literal}",
643      }
644    },
645    "fnDrawCallback": function( oSettings ) {
646      jQuery("#userList input[type=checkbox]").each(function() {
647        var user_id = jQuery(this).data("user_id");
648        jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
649      });
650    },
651    "aoColumns": aoColumns
652  });
653
654  /**
655   * Selection management
656   */
657  function checkSelection() {
658    if (selection.length > 0) {
659      jQuery("#forbidAction").hide();
660      jQuery("#permitAction").show();
661
662      jQuery("#applyOnDetails").text(
663        sprintf(
664          applyOnDetails_pattern,
665          selection.length
666        )
667      );
668
669      if (selection.length == allUsers.length) {
670        jQuery("#selectedMessage").text(
671          sprintf(
672            selectedMessage_all,
673            allUsers.length
674          )
675        );
676      }
677      else {
678        jQuery("#selectedMessage").text(
679          sprintf(
680            selectedMessage_pattern,
681            selection.length,
682            allUsers.length
683          )
684        );
685      }
686    }
687    else {
688      jQuery("#forbidAction").show();
689      jQuery("#permitAction").hide();
690
691      jQuery("#selectedMessage").text(
692        sprintf(
693          selectedMessage_none,
694          allUsers.length
695        )
696      );
697    }
698
699    jQuery("#applyActionBlock .infos").hide();
700  }
701
702  jQuery(document).on('change', '#userList input[type=checkbox]',  function() {
703    var user_id = jQuery(this).data("user_id");
704
705    array_delete(selection, user_id);
706
707    if (jQuery(this).is(":checked")) {
708      selection.push(user_id);
709    }
710
711    checkSelection();
712  });
713
714  jQuery("#selectAll").click(function () {
715    selection = allUsers;
716    jQuery("#userList input[type=checkbox]").prop('checked', true);
717    checkSelection();
718    return false;
719  });
720
721  jQuery("#selectNone").click(function () {
722    selection = [];
723    jQuery("#userList input[type=checkbox]").prop('checked', false);
724    checkSelection();
725    return false;
726  });
727
728  jQuery("#selectInvert").click(function () {
729    var newSelection = [];
730    for(var i in allUsers)
731    {
732      if (selection.indexOf(allUsers[i]) == -1) {
733        newSelection.push(allUsers[i]);
734      }
735    }
736    selection = newSelection;
737
738    jQuery("#userList input[type=checkbox]").each(function() {
739      var user_id = jQuery(this).data("user_id");
740      jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
741    });
742
743    checkSelection();
744    return false;
745  });
746
747  /**
748   * Action management
749   */
750  jQuery("[id^=action_]").hide();
751 
752  jQuery("select[name=selectAction]").change(function () {
753    jQuery("#applyActionBlock .infos").hide();
754
755    jQuery("[id^=action_]").hide();
756
757    jQuery("#action_"+$(this).prop("value")).show();
758 
759    if (jQuery(this).val() != -1) {
760      jQuery("#applyActionBlock").show();
761    }
762    else {
763      jQuery("#applyActionBlock").hide();
764    }
765  });
766
767  jQuery("#permitAction input, #permitAction select").click(function() {
768    jQuery("#applyActionBlock .infos").hide();
769  });
770
771  jQuery("#applyAction").click(function() {
772    var action = jQuery("select[name=selectAction]").prop("value");
773    var method = 'pwg.users.setInfo';
774    var data = {
775      user_id: selection
776    };
777
778    switch (action) {
779      case 'delete':
780        if (!jQuery("input[name=confirm_deletion]").is(':checked')) {
781          alert(missingConfirm);
782          return false;
783        }
784        method = 'pwg.users.delete';
785        data.pwg_token = pwg_token;
786        break;
787      case 'group_associate':
788        method = 'pwg.groups.addUser';
789        data.group_id = jQuery("select[name=associate]").prop("value");
790        break;
791      case 'group_dissociate':
792        method = 'pwg.groups.deleteUser';
793        data.group_id = jQuery("select[name=dissociate]").prop("value");
794        break;
795      case 'status':
796        data.status = jQuery("select[name=status]").prop("value");
797        break;
798      case 'enabled_high':
799        data.enabled_high = jQuery("input[name=enabled_high]:checked").val();
800        break;
801      case 'level':
802        data.level = jQuery("select[name=level]").val();
803        break;
804      case 'nb_image_page':
805        data.nb_image_page = jQuery("input[name=nb_image_page]").val();
806        break;
807      case 'theme':
808        data.theme = jQuery("select[name=theme]").val();
809        break;
810      case 'language':
811        data.language = jQuery("select[name=language]").val();
812        break;
813      case 'recent_period':
814        data.recent_period = jQuery("input[name=recent_period]").val();
815        break;
816      case 'expand':
817        data.expand = jQuery("input[name=expand]:checked").val();
818        break;
819      case 'show_nb_comments':
820        data.show_nb_comments = jQuery("input[name=show_nb_comments]:checked").val();
821        break;
822      case 'show_nb_hits':
823        data.show_nb_hits = jQuery("input[name=show_nb_hits]:checked").val();
824        break;
825      default:
826        alert("Unexpected action");
827        return false;
828    }
829
830    jQuery.ajax({
831      url: "ws.php?format=json&method="+method,
832      type:"POST",
833      data: data,
834      beforeSend: function() {
835        jQuery("#applyActionLoading").show();
836      },
837      success:function(data) {
838        oTable.fnDraw();
839        jQuery("#applyActionLoading").hide();
840        jQuery("#applyActionBlock .infos").show();
841
842        if (action == 'delete') {
843          var allUsers_new = [];
844          for(var i in allUsers)
845          {
846            if (selection.indexOf(allUsers[i]) == -1) {
847              allUsers_new.push(allUsers[i]);
848            }
849          }
850          allUsers = allUsers_new;
851          console.log('allUsers_new.length = '+allUsers_new.length);
852          selection = [];
853          checkSelection();
854        }
855      },
856      error:function(XMLHttpRequest, textStatus, errorThrows) {
857        jQuery("#applyActionLoading").hide();
858      }
859    });
860
861    return false;
862  });
863
864});
865{/literal}{/footer_script}
866
867{html_style}{literal}
868.dataTables_wrapper, .dataTables_info {clear:none;}
869table.dataTable {clear:right;padding-top:10px;}
870.dataTable td img {margin-bottom: -6px;margin-left: -6px;}
871.paginate_enabled_previous, .paginate_enabled_previous:hover, .paginate_disabled_previous, .paginate_enabled_next, .paginate_enabled_next:hover, .paginate_disabled_next {background:none;}
872.paginate_enabled_previous, .paginate_enabled_next {color:#005E89 !important;}
873.paginate_enabled_previous:hover, .paginate_enabled_next:hover {color:#D54E21 !important; text-decoration:underline !important;}
874
875.paginate_disabled_next, .paginate_enabled_next {padding-right:3px;}
876.bulkAction {margin-top:10px;}
877#addUserForm p {margin-left:0;}
878#applyActionBlock .actionButtons {margin-left:0;}
879span.infos, span.errors {background-image:none; padding:2px 5px; margin:0;border-radius:5px;}
880
881.userStats {margin-top:10px;}
882.recent_period_infos {margin-left:10px;}
883.nb_image_page, .recent_period {width:340px;margin-top:5px;}
884#action_recent_period .recent_period {display:inline-block;}
885{/literal}{/html_style}
886
887<div class="titrePage">
888  <h2>{'User list'|@translate}</h2>
889</div>
890
891<p class="showCreateAlbum" id="showAddUser">
892  <a href="#" id="addUser" class="icon-plus-circled">{'Add a user'|translate}</a>
893  <span class="infos" style="display:none"></span>
894</p>
895
896<form id="addUserForm" style="display:none" method="post" name="add_user" action="{$F_ADD_ACTION}">
897  <fieldset>
898    <legend>{'Add a user'|@translate}</legend>
899
900    <p>
901      <strong>{'Username'|translate}</strong><br>
902      <input type="text" name="username" maxlength="50" size="20">
903    </p>
904
905    <p>
906      <strong>{'Password'|translate}</strong><br>
907      <input type="{if $Double_Password}password{else}text{/if}" name="password">
908    </p>
909   
910{if $Double_Password}
911    <p>
912      <strong>{'Confirm Password'|@translate}</strong><br>
913      <input type="password" name="password_confirm">
914    </p>
915{/if}
916
917    <p>
918      <strong>{'Email address'|@translate}</strong><br>
919      <input type="text" name="email">
920    </p>
921
922    <p>
923      <label><input type="checkbox" name="send_password_by_mail"> <strong>{'Send connection settings by email'|@translate}</strong></label>
924    </p>
925
926    <p class="actionButtons">
927      <input class="submit" name="submit_add" type="submit" value="{'Submit'|@translate}">
928      <a href="#" id="addUserClose">{'Cancel'|@translate}</a>
929      <span class="loading" style="display:none"><img src="themes/default/images/ajax-loader-small.gif"></span>
930      <span class="errors" style="display:none"></span>
931    </p>
932  </fieldset>
933</form>
934
935<form method="post" name="preferences" action="">
936
937<table id="userList">
938  <thead>
939    <tr>
940      <th>id</th>
941      <th>{'Username'|@translate}</th>
942      <th>{'Status'|@translate}</th>
943      <th>{'Email address'|@translate}</th>
944      <th>{'registration date'|@translate}</th>
945    </tr>
946  </thead>
947</table>
948
949<div style="clear:right"></div>
950
951<p class="checkActions">
952  {'Select:'|@translate}
953  <a href="#" id="selectAll">{'All'|@translate}</a>,
954  <a href="#" id="selectNone">{'None'|@translate}</a>,
955  <a href="#" id="selectInvert">{'Invert'|@translate}</a>
956
957  <span id="selectedMessage"></span>
958</p>
959
960<fieldset id="action">
961  <legend>{'Action'|@translate}</legend>
962
963  <div id="forbidAction"{if count($selection) != 0} style="display:none"{/if}>{'No user selected, no action possible.'|@translate}</div>
964  <div id="permitAction"{if count($selection) == 0} style="display:none"{/if}>
965
966    <select name="selectAction">
967      <option value="-1">{'Choose an action'|@translate}</option>
968      <option disabled="disabled">------------------</option>
969      <option value="delete" class="icon-trash">{'Delete selected users'|@translate}</option>
970      <option value="status">{'Status'|@translate}</option>
971      <option value="group_associate">{'associate to group'|translate}</option>
972      <option value="group_dissociate">{'dissociate from group'|@translate}</option>
973      <option value="enabled_high">{'High definition enabled'|@translate}</option>
974      <option value="level">{'Privacy level'|@translate}</option>
975      <option value="nb_image_page">{'Number of photos per page'|@translate}</option>
976      <option value="theme">{'Theme'|@translate}</option>
977      <option value="language">{'Language'|@translate}</option>
978      <option value="recent_period">{'Recent period'|@translate}</option>
979      <option value="expand">{'Expand all albums'|@translate}</option>
980{if $ACTIVATE_COMMENTS}
981      <option value="show_nb_comments">{'Show number of comments'|@translate}</option>
982{/if}
983      <option value="show_nb_hits">{'Show number of hits'|@translate}</option>
984    </select>
985
986    {* delete *}
987    <div id="action_delete" class="bulkAction">
988      <p><label><input type="checkbox" name="confirm_deletion" value="1"> {'Are you sure?'|@translate}</label></p>
989    </div>
990
991    {* status *}
992    <div id="action_status" class="bulkAction">
993      <select name="status">
994        {html_options options=$pref_status_options selected=$pref_status_selected}
995      </select>
996    </div>
997
998    {* group_associate *}
999    <div id="action_group_associate" class="bulkAction">
1000      {html_options name=associate options=$association_options selected=$associate_selected}
1001    </div>
1002
1003    {* group_dissociate *}
1004    <div id="action_group_dissociate" class="bulkAction">
1005      {html_options name=dissociate options=$association_options selected=$dissociate_selected}
1006    </div>
1007
1008    {* enabled_high *}
1009    <div id="action_enabled_high" class="bulkAction">
1010      <label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
1011      <label><input type="radio" name="enabled_high" value="false" checked="checked">{'No'|@translate}</label>
1012    </div>
1013
1014    {* level *}
1015    <div id="action_level" class="bulkAction">
1016      <select name="level" size="1">
1017        {html_options options=$level_options selected=$level_selected}
1018      </select>
1019    </div>
1020
1021    {* nb_image_page *}
1022    <div id="action_nb_image_page" class="bulkAction">
1023      <strong class="nb_image_page_infos"></strong>
1024      <div class="nb_image_page"></div>
1025      <input type="hidden" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
1026    </div>
1027
1028    {* theme *}
1029    <div id="action_theme" class="bulkAction">
1030      <select name="theme" size="1">
1031        {html_options options=$theme_options selected=$theme_selected}
1032      </select>
1033    </div>
1034
1035    {* language *}
1036    <div id="action_language" class="bulkAction">
1037      <select name="language" size="1">
1038        {html_options options=$language_options selected=$language_selected}
1039      </select>
1040    </div>
1041
1042    {* recent_period *}
1043    <div id="action_recent_period" class="bulkAction">
1044      <div class="recent_period"></div>
1045      <span class="recent_period_infos"></span>
1046      <input type="hidden" name="recent_period" value="{$RECENT_PERIOD}">
1047    </div>
1048
1049    {* expand *}
1050    <div id="action_expand" class="bulkAction">
1051      <label><input type="radio" name="expand" value="true">{'Yes'|@translate}</label>
1052      <label><input type="radio" name="expand" value="false" checked="checked">{'No'|@translate}</label>
1053    </div>
1054
1055    {* show_nb_comments *}
1056    <div id="action_show_nb_comments" class="bulkAction">
1057      <label><input type="radio" name="show_nb_comments" value="true">{'Yes'|@translate}</label>
1058      <label><input type="radio" name="show_nb_comments" value="false" checked="checked">{'No'|@translate}</label>
1059    </div>
1060
1061    {* show_nb_hits *}
1062    <div id="action_show_nb_hits" class="bulkAction">
1063      <label><input type="radio" name="show_nb_hits" value="true">{'Yes'|@translate}</label>
1064      <label><input type="radio" name="show_nb_hits" value="false" checked="checked">{'No'|@translate}</label>
1065    </div>
1066
1067    <p id="applyActionBlock" style="display:none" class="actionButtons">
1068      <input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit"> <span id="applyOnDetails"></span>
1069      <span id="applyActionLoading" style="display:none"><img src="themes/default/images/ajax-loader-small.gif"></span>
1070      <span class="infos" style="display:none">&#x2714; {'Users modified'|translate}</span>
1071    </p>
1072
1073  </div> {* #permitAction *}
1074</fieldset>
1075
1076</form>
Note: See TracBrowser for help on using the repository browser.