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

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

feature 1668, user manager redesign:

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