Ignore:
Timestamp:
Oct 28, 2013, 5:25:46 PM (10 years ago)
Author:
plg
Message:

feature 1668, in progress: redesign user manager (jQuery datatables, AJAX calls)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/themes/default/template/user_list.tpl

    r12887 r25194  
     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{footer_script}
     7var selectedMessage_pattern = "{'%d of %d photos selected'|@translate}";
     8var selectedMessage_none = "{'No photo selected, %d photos in current set'|@translate}";
     9var selectedMessage_all = "{'All %d photos are selected'|@translate}";
     10var applyOnDetails_pattern = "{'on the %d selected users'|@translate}";
     11var missingConfirm = "{'You need to confirm deletion'|translate}";
     12
     13var allUsers = [{$all_users}];
     14var selection = [{$selection}];
     15{/footer_script}
     16
     17{footer_script}{literal}
     18jQuery(document).ready(function() {
     19  /* first column must be prefixed with the open/close icon */
     20  var aoColumns = [
     21    {
     22      'bVisible':false
     23    },
     24    {
     25      "mRender": function(data, type, full) {
     26        return '<label><input type="checkbox" data-user_id="'+full[0]+'"> '+data+'</label>';
     27      }
     28    }
     29  ];
     30
     31  for (i=2; i<jQuery("#userList thead tr th").length; i++) {
     32    aoColumns.push(null);
     33  }
     34
     35  var oTable = jQuery('#userList').dataTable({
     36    "iDisplayLength": 10,
     37    "bDeferRender": true,
     38    "bProcessing": true,
     39    "bServerSide": true,
     40    "sAjaxSource": "admin/user_list_backend.php",
     41    "fnDrawCallback": function( oSettings ) {
     42      jQuery("#userList input[type=checkbox]").each(function() {
     43        var user_id = jQuery(this).data("user_id");
     44        jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
     45      });
     46    },
     47    "aoColumns": aoColumns
     48  });
     49
     50  /**
     51   * Selection management
     52   */
     53  function checkSelection() {
     54    if (selection.length > 0) {
     55      jQuery("#forbidAction").hide();
     56      jQuery("#permitAction").show();
     57
     58      jQuery("#applyOnDetails").text(
     59        sprintf(
     60          applyOnDetails_pattern,
     61          selection.length
     62        )
     63      );
     64
     65      if (selection.length == allUsers.length) {
     66        jQuery("#selectedMessage").text(
     67          sprintf(
     68            selectedMessage_all,
     69            allUsers.length
     70          )
     71        );
     72      }
     73      else {
     74        jQuery("#selectedMessage").text(
     75          sprintf(
     76            selectedMessage_pattern,
     77            selection.length,
     78            allUsers.length
     79          )
     80        );
     81      }
     82    }
     83    else {
     84      jQuery("#forbidAction").show();
     85      jQuery("#permitAction").hide();
     86
     87      jQuery("#selectedMessage").text(
     88        sprintf(
     89          selectedMessage_none,
     90          allUsers.length
     91        )
     92      );
     93    }
     94
     95    jQuery("#applyActionBlock .infos").hide();
     96  }
     97
     98  jQuery(document).on('change', '#userList input[type=checkbox]',  function() {
     99    var user_id = jQuery(this).data("user_id");
     100
     101    array_delete(selection, user_id);
     102
     103    if (jQuery(this).is(":checked")) {
     104      selection.push(user_id);
     105    }
     106
     107    checkSelection();
     108  });
     109
     110  jQuery("#selectAll").click(function () {
     111    selection = allUsers;
     112    jQuery("#userList input[type=checkbox]").prop('checked', true);
     113    checkSelection();
     114    return false;
     115  });
     116
     117  jQuery("#selectNone").click(function () {
     118    selection = [];
     119    jQuery("#userList input[type=checkbox]").prop('checked', false);
     120    checkSelection();
     121    return false;
     122  });
     123
     124  jQuery("#selectInvert").click(function () {
     125    var newSelection = [];
     126    for(var i in allUsers)
     127    {
     128      if (selection.indexOf(allUsers[i]) == -1) {
     129        newSelection.push(allUsers[i]);
     130      }
     131    }
     132    selection = newSelection;
     133
     134    jQuery("#userList input[type=checkbox]").each(function() {
     135      var user_id = jQuery(this).data("user_id");
     136      jQuery(this).prop('checked', (selection.indexOf(user_id) != -1));
     137    });
     138
     139    checkSelection();
     140    return false;
     141  });
     142
     143  /**
     144   * Action management
     145   */
     146  jQuery("[id^=action_]").hide();
     147 
     148  jQuery("select[name=selectAction]").change(function () {
     149    jQuery("#applyActionBlock .infos").hide();
     150
     151    jQuery("[id^=action_]").hide();
     152
     153    jQuery("#action_"+$(this).prop("value")).show();
     154 
     155    if (jQuery(this).val() != -1) {
     156      jQuery("#applyActionBlock").show();
     157    }
     158    else {
     159      jQuery("#applyActionBlock").hide();
     160    }
     161  });
     162
     163  jQuery("#permitAction input, #permitAction select").click(function() {
     164    jQuery("#applyActionBlock .infos").hide();
     165  });
     166
     167  jQuery("#applyAction").click(function() {
     168    var action = jQuery("select[name=selectAction]").prop("value");
     169    var method = null;
     170    var data = {
     171      user_id: selection
     172    };
     173
     174    switch (action) {
     175      case 'delete':
     176        if (!jQuery("input[name=confirm_deletion]").is(':checked')) {
     177          alert(missingConfirm);
     178          return false;
     179        }
     180        method = 'pwg.users.delete';
     181        break;
     182      case 'group_associate':
     183        method = 'pwg.groups.addUser';
     184        data.group_id = jQuery("select[name=associate]").prop("value");
     185        break;
     186      case 'group_dissociate':
     187        method = 'pwg.groups.deleteUser';
     188        data.group_id = jQuery("select[name=dissociate]").prop("value");
     189        break;
     190    }
     191
     192    jQuery.ajax({
     193      url: "ws.php?format=json&method="+method,
     194      type:"POST",
     195      data: data,
     196      beforeSend: function() {
     197        jQuery("#applyActionLoading").show();
     198      },
     199      success:function(data) {
     200        oTable.fnDraw();
     201        jQuery("#applyActionLoading").hide();
     202        jQuery("#applyActionBlock .infos").show();
     203
     204        if (action == 'delete') {
     205          var allUsers_new = [];
     206          for(var i in allUsers)
     207          {
     208            if (selection.indexOf(allUsers[i]) == -1) {
     209              allUsers_new.push(allUsers[i]);
     210            }
     211          }
     212          allUsers = allUsers_new;
     213          console.log('allUsers_new.length = '+allUsers_new.length);
     214          selection = [];
     215          checkSelection();
     216        }
     217      },
     218      error:function(XMLHttpRequest, textStatus, errorThrows) {
     219        jQuery("#applyActionLoading").hide();
     220      }
     221    });
     222
     223    return false;
     224  });
     225
     226});
     227{/literal}{/footer_script}
     228
     229{literal}
     230<style>
     231.dataTables_wrapper, .dataTables_info {clear:none;}
     232table.dataTable {clear:right;padding-top:10px;}
     233.bulkAction {margin-top:10px;}
     234.actionButtons {margin-left:0;}
     235#applyActionBlock .infos {background-image:none; padding:2px 5px; margin:0;border-radius:5px;}
     236</style>
     237{/literal}
     238
    1239<div class="titrePage">
    2240  <h2>{'User list'|@translate}</h2>
    3241</div>
    4242
    5 <form class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
     243<form style="display:none" class="filter" method="post" name="add_user" action="{$F_ADD_ACTION}">
    6244  <fieldset>
    7245    <legend>{'Add a user'|@translate}</legend>
     
    19257</form>
    20258
    21 <form class="filter" method="get" name="filter" action="{$F_FILTER_ACTION}">
    22 <fieldset>
    23   <legend>{'Filter'|@translate}</legend>
    24   <input type="hidden" name="page" value="user_list">
    25 
    26   <label>{'Username'|@translate} <input type="text" name="username" value="{$F_USERNAME}"></label>
    27 
    28   <label>
    29   {'status'|@translate}
    30   {html_options name=status options=$status_options selected=$status_selected}
    31   </label>
    32 
    33   <label>
    34   {'Group'|@translate}
    35   {html_options name=group options=$group_options selected=$group_selected}
    36   </label>
    37 
    38   <label>
    39   {'Sort by'|@translate}
    40   {html_options name=order_by options=$order_options selected=$order_selected}
    41   </label>
    42 
    43   <label>
    44   {'Sort order'|@translate}
    45   {html_options name=direction options=$direction_options selected=$direction_selected}
    46   </label>
    47 
    48   <label>
    49   &nbsp;
    50   <input class="submit" type="submit" value="{'Submit'|@translate}">
    51   </label>
    52 
    53 </fieldset>
    54 
    55 </form>
    56 
    57259<form method="post" name="preferences" action="">
    58260
    59 {if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
    60 
    61 <table class="table2" width="97%">
     261<table id="userList">
    62262  <thead>
    63     <tr class="throw">
    64       <td>&nbsp;</td>
    65       <td>{'Username'|@translate}</td>
    66       <td>{'User status'|@translate}</td>
    67       <td>{'Email address'|@translate}</td>
    68       <td>{'Groups'|@translate}</td>
    69       <td>{'Properties'|@translate}</td>
    70       {if not empty($plugin_user_list_column_titles)}
    71       {foreach from=$plugin_user_list_column_titles item=title}
    72       <td>{$title}</td>
    73       {/foreach}
    74       {/if}
    75       <td>{'Actions'|@translate}</td>
     263    <tr>
     264      <th>id</th>
     265      <th>{'Username'|@translate}</th>
     266      <th>{'Status'|@translate}</th>
     267      <th>{'Email address'|@translate}</th>
    76268    </tr>
    77269  </thead>
    78 
    79   {foreach from=$users item=user name=users_loop}
    80   <tr class="{if $smarty.foreach.users_loop.index is odd}row1{else}row2{/if}">
    81     <td><input type="checkbox" name="selection[]" value="{$user.ID}" {$user.CHECKED} id="selection-{$user.ID}"></td>
    82     <td><label for="selection-{$user.ID}">{$user.USERNAME}</label></td>
    83     <td>{$user.STATUS}</td>
    84     <td>{$user.EMAIL}</td>
    85     <td>{$user.GROUPS}</td>
    86     <td>{$user.PROPERTIES}</td>
    87     {foreach from=$user.plugin_columns item=data}
    88     <td>{$data}</td>
    89     {/foreach}
    90     <td style="text-align:center;">
    91       <a href="{$user.U_PERM}"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/permissions.png" style="border:none" alt="{'Permissions'|@translate}" title="{'Permissions'|@translate}"></a>
    92       <a href="{$user.U_PROFILE}"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/edit_s.png" style="border:none" alt="{'Profile'|@translate}" title="{'Profile'|@translate}"></a>
    93       {foreach from=$user.plugin_actions item=data}
    94       {$data}
    95       {/foreach}
    96       </td>
    97   </tr>
    98   {/foreach}
    99270</table>
    100271
    101 {if !empty($navbar) }{include file='navigation_bar.tpl'|@get_extent:'navbar'}{/if}
    102 
    103 {* delete the selected users ? *}
    104 <fieldset>
    105   <legend>{'Deletions'|@translate}</legend>
    106   <label><input type="checkbox" name="confirm_deletion" value="1"> {'confirm'|@translate}</label>
    107   <input class="submit" type="submit" value="{'Delete selected users'|@translate}" name="delete">
    108 </fieldset>
    109 
    110 <fieldset>
    111   <legend>{'Status'|@translate}</legend>
    112 
    113   <table>
    114     <tr>
    115       <td>{'Status'|@translate}</td>
    116       <td>
    117         <label><input type="radio" name="status_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    118         <label><input type="radio" name="status_action" value="set" id="status_action_set"> {'set to'|@translate}</label>
    119         <select onchange="document.getElementById('status_action_set').checked = true;" name="status" size="1">
    120           {html_options options=$pref_status_options selected=$pref_status_selected}
    121         </select>
    122       </td>
    123     </tr>
    124   </table>
    125 </fieldset>
    126 
    127 {* form to set properties for many users at once *}
    128 <fieldset>
    129   <legend>{'Groups'|@translate}</legend>
    130 
    131 <table>
    132 
    133   <tr>
    134     <td>{'associate to group'|@translate}</td>
    135     <td>
     272<div style="clear:right"></div>
     273
     274<p class="checkActions">
     275  {'Select:'|@translate}
     276  <a href="#" id="selectAll">{'All'|@translate}</a>,
     277  <a href="#" id="selectNone">{'None'|@translate}</a>,
     278  <a href="#" id="selectInvert">{'Invert'|@translate}</a>
     279
     280  <span id="selectedMessage"></span>
     281</p>
     282
     283<fieldset id="action">
     284  <legend>{'Action'|@translate}</legend>
     285
     286  <div id="forbidAction"{if count($selection) != 0} style="display:none"{/if}>{'No user selected, no action possible.'|@translate}</div>
     287  <div id="permitAction"{if count($selection) == 0} style="display:none"{/if}>
     288
     289    <select name="selectAction">
     290      <option value="-1">{'Choose an action'|@translate}</option>
     291      <option disabled="disabled">------------------</option>
     292      <option value="delete" class="icon-trash">{'Delete selected users'|@translate}</option>
     293      <option value="status">{'Status'|@translate}</option>
     294      <option value="group_associate">{'associate to group'|translate}</option>
     295      <option value="group_dissociate">{'dissociate from group'|@translate}</option>
     296      <option value="enabled_high">{'High definition enabled'|@translate}</option>
     297      <option value="level">{'Privacy level'|@translate}</option>
     298      <option value="nb_image_page">{'Number of photos per page'|@translate}</option>
     299      <option value="theme">{'Interface theme'|@translate}</option>
     300      <option value="language">{'Language'|@translate}</option>
     301      <option value="recent_period">{'Recent period'|@translate}</option>
     302      <option value="expand">{'Expand all albums'|@translate}</option>
     303{if $ACTIVATE_COMMENTS}
     304      <option value="show_nb_comments">{'Show number of comments'|@translate}</option>
     305{/if}
     306      <option value="show_nb_hits">{'Show number of hits'|@translate}</option>
     307    </select>
     308
     309    {* delete *}
     310    <div id="action_delete" class="bulkAction">
     311      <p><label><input type="checkbox" name="confirm_deletion" value="1"> {'Are you sure?'|@translate}</label></p>
     312    </div>
     313
     314    {* status *}
     315    <div id="action_status" class="bulkAction">
     316      <select name="status">
     317        {html_options options=$pref_status_options selected=$pref_status_selected}
     318      </select>
     319    </div>
     320
     321    {* group_associate *}
     322    <div id="action_group_associate" class="bulkAction">
    136323      {html_options name=associate options=$association_options selected=$associate_selected}
    137     </td>
    138   </tr>
    139 
    140   <tr>
    141     <td>{'dissociate from group'|@translate}</td>
    142     <td>
     324    </div>
     325
     326    {* group_dissociate *}
     327    <div id="action_group_dissociate" class="bulkAction">
    143328      {html_options name=dissociate options=$association_options selected=$dissociate_selected}
    144     </td>
    145   </tr>
    146 
    147 </table>
    148 
    149 </fieldset>
    150 
    151 {* Properties *}
    152 <fieldset>
    153   <legend>{'Properties'|@translate}</legend>
    154 
    155   <table>
    156 
    157     <tr>
    158       <td>{'High definition enabled'|@translate}</td>
    159       <td>
    160         <label><input type="radio" name="enabled_high" value="leave" checked="checked"> {'leave'|@translate}</label>
    161         / {'set to'|@translate}
    162         <label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
    163         <label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
    164       </td>
    165     </tr>
    166 
    167     <tr>
    168       <td>{'Privacy level'|@translate}</td>
    169       <td>
    170         <label><input type="radio" name="level_action" value="leave" checked="checked">{'leave'|@translate}</label>
    171         <label><input type="radio" name="level_action" value="set" id="level_action_set">{'set to'|@translate}</label>
    172         <select onchange="document.getElementById('level_action_set').checked = true;" name="level" size="1">
    173           {html_options options=$level_options selected=$level_selected}
    174         </select>
    175       </td>
    176     </tr>
    177   </table>
    178 
    179 </fieldset>
    180 
    181 {* preference *}
    182 <fieldset>
    183   <legend>{'Preferences'|@translate}</legend>
    184 
    185 <table>
    186   <tr>
    187     <td>{'Number of photos per page'|@translate}</td>
    188     <td>
    189       <label><input type="radio" name="nb_image_page_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    190       <label><input type="radio" name="nb_image_page_action" value="set" id="nb_image_page_action_set"> {'set to'|@translate}</label>
    191       <input onmousedown="document.getElementById('nb_image_page_action_set').checked = true;"
    192              size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
    193     </td>
    194   </tr>
    195 
    196   <tr>
    197     <td>{'Interface theme'|@translate}</td>
    198     <td>
    199       <label><input type="radio" name="theme_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    200       <label><input type="radio" name="theme_action" value="set" id="theme_action_set"> {'set to'|@translate}</label>
    201       <select onchange="document.getElementById('theme_action_set').checked = true;" name="theme" size="1">
     329    </div>
     330
     331    {* enabled_high *}
     332    <div id="action_enabled_high" class="bulkAction">
     333      <label><input type="radio" name="enabled_high" value="true">{'Yes'|@translate}</label>
     334      <label><input type="radio" name="enabled_high" value="false">{'No'|@translate}</label>
     335    </div>
     336
     337    {* level *}
     338    <div id="action_level" class="bulkAction">
     339      <select name="level" size="1">
     340        {html_options options=$level_options selected=$level_selected}
     341      </select>
     342    </div>
     343
     344    {* nb_image_page *}
     345    <div id="action_nb_image_page" class="bulkAction">
     346      <input size="4" maxlength="3" type="text" name="nb_image_page" value="{$NB_IMAGE_PAGE}">
     347    </div>
     348
     349    {* theme *}
     350    <div id="action_theme" class="bulkAction">
     351      <select name="theme" size="1">
    202352        {html_options options=$theme_options selected=$theme_selected}
    203353      </select>
    204     </td>
    205   </tr>
    206 
    207   <tr>
    208     <td>{'Language'|@translate}</td>
    209     <td>
    210       <label><input type="radio" name="language_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    211       <label><input type="radio" name="language_action" value="set" id="language_action_set"> {'set to'|@translate}</label>
    212       <select onchange="document.getElementById('language_action_set').checked = true;" name="language" size="1">
     354    </div>
     355
     356    {* language *}
     357    <div id="action_language" class="bulkAction">
     358      <select name="language" size="1">
    213359        {html_options options=$language_options selected=$language_selected}
    214360      </select>
    215     </td>
    216   </tr>
    217 
    218   <tr>
    219     <td>{'Recent period'|@translate}</td>
    220     <td>
    221       <label><input type="radio" name="recent_period_action" value="leave" checked="checked"> {'leave'|@translate}</label>
    222       <label><input type="radio" name="recent_period_action" value="set" id="recent_period_action_set"> {'set to'|@translate}</label>
    223       <input onmousedown="document.getElementById('recent_period_action_set').checked = true;"
    224              type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
    225     </td>
    226   </tr>
    227 
    228   <tr>
    229     <td>{'Expand all albums'|@translate}</td>
    230     <td>
    231       <label><input type="radio" name="expand" value="leave" checked="checked"> {'leave'|@translate}</label>
    232       / {'set to'|@translate}
     361    </div>
     362
     363    {* recent_period *}
     364    <div id="action_recent_period" class="bulkAction">
     365      <input type="text" size="3" maxlength="2" name="recent_period" value="{$RECENT_PERIOD}">
     366    </div>
     367
     368    {* expand *}
     369    <div id="action_expand" class="bulkAction">
    233370      <label><input type="radio" name="expand" value="true">{'Yes'|@translate}</label>
    234371      <label><input type="radio" name="expand" value="false">{'No'|@translate}</label>
    235     </td>
    236   </tr>
    237 
    238 {if $ACTIVATE_COMMENTS}
    239   <tr>
    240     <td>{'Show number of comments'|@translate}</td>
    241     <td>
    242       <label><input type="radio" name="show_nb_comments" value="leave" checked="checked"> {'leave'|@translate}</label>
    243       / {'set to'|@translate}
     372    </div>
     373
     374    {* show_nb_comments *}
     375    <div id="action_show_nb_comments" class="bulkAction">
    244376      <label><input type="radio" name="show_nb_comments" value="true">{'Yes'|@translate}</label>
    245377      <label><input type="radio" name="show_nb_comments" value="false">{'No'|@translate}</label>
    246     </td>
    247   </tr>
    248 {/if}
    249 
    250   <tr>
    251     <td>{'Show number of hits'|@translate}</td>
    252     <td>
    253       <label><input type="radio" name="show_nb_hits" value="leave" checked="checked"> {'leave'|@translate}</label>
    254       / {'set to'|@translate}
     378    </div>
     379
     380    {* show_nb_hits *}
     381    <div id="action_show_nb_hits" class="bulkAction">
    255382      <label><input type="radio" name="show_nb_hits" value="true">{'Yes'|@translate}</label>
    256383      <label><input type="radio" name="show_nb_hits" value="false">{'No'|@translate}</label>
    257     </td>
    258   </tr>
    259 
    260 </table>
    261 
     384    </div>
     385
     386    <p id="applyActionBlock" style="display:none" class="actionButtons">
     387      <input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit"> <span id="applyOnDetails"></span>
     388      <span id="applyActionLoading" style="display:none"><img src="themes/default/images/ajax-loader-small.gif"></span>
     389      <span class="infos" style="display:none">&#x2714; Users modified</span>
     390    </p>
     391
     392  </div> {* #permitAction *}
    262393</fieldset>
    263394
    264 <p>
    265   {'target'|@translate}
    266   <label><input type="radio" name="target" value="all"> {'all'|@translate}</label>
    267   <label><input type="radio" name="target" value="selection" checked="checked"> {'selection'|@translate}</label>
    268 </p>
    269 
    270 <p>
    271   <input class="submit" type="submit" value="{'Submit'|@translate}" name="pref_submit">
    272   <input class="submit" type="reset" value="{'Reset'|@translate}" name="pref_reset">
    273 </p>
    274 
    275 </form>
    276 
    277 <script type="text/javascript">// <![CDATA[{literal}
    278 jQuery("form:last").submit( function() {
    279         if ( jQuery("input[name=target][value=selection]:checked", this).length > 0 )
    280         if ( jQuery("input[name='selection[]']:checked", this).length == 0)
    281         {
    282                 alert( {/literal}"{'Select at least one user'|@translate|escape:javascript}"{literal} );
    283                 return false;
    284         }
    285         return true;
    286 }
    287 );{/literal}
    288 // ]]>
    289 </script>
    290  
     395</form>
Note: See TracChangeset for help on using the changeset viewer.