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

Last change on this file since 26270 was 26270, checked in by plg, 7 years ago

feature 1668: use underscore.js to template the userDetails instead of
generating HTML directly in javascript. Will make work easier for plugins
modifying the user profile.

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