Bug 22990: Add CSRF protection to boraccount, pay and suggestion
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / members / member.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE Koha %]
4 [% USE TablesSettings %]
5 [% USE Branches %]
6 [% USE Categories %]
7 [% SET footerjs = 1 %]
8 [% PROCESS 'patronfields.inc' %]
9 [% SET libraries = Branches.all %]
10 [% SET categories = Categories.all.unblessed %]
11 [% SET columns = ['cardnumber', 'name-address', 'dateofbirth', 'branch', 'category', 'dateexpiry', 'checkouts', 'account_balance', 'borrowernotes', 'action'] %]
12 [% SET searchtype = Koha.Preference('DefaultPatronSearchMethod') %]
13 [% PROCESS 'patron-search.inc' %]
14 [% INCLUDE 'doc-head-open.inc' %]
15 <title>Patrons[% IF ( searching ) %] &rsaquo; Search results[% END %] &rsaquo; Koha</title>
16 [% INCLUDE 'doc-head-close.inc' %]
17 </head>
18
19 <body id="pat_member" class="pat">
20 [% WRAPPER 'header.inc' %]
21     [% INCLUDE 'patron-search-header.inc' %]
22 [% END %]
23
24 [% WRAPPER 'sub-header.inc' %]
25     [% WRAPPER breadcrumbs %]
26         [% WRAPPER breadcrumb_item bc_active= 1 %]
27             Patrons
28         [% END %]
29     [% END #/ WRAPPER breadcrumbs %]
30 [% END #/ WRAPPER sub-header.inc %]
31
32 <div class="main container-fluid">
33     <div class="row">
34         <div class="col-sm-10 col-sm-push-2">
35             <main>
36
37           [% IF CAN_user_tools_manage_patron_lists %]
38             <div id="patron_list_dialog" class="dialog message">
39               Added <span class="patrons-length"></span> patrons to <a></a>.
40             </div>
41           [% END %]
42
43           [% INCLUDE 'patron-toolbar.inc' %]
44           [% INCLUDE 'noadd-warnings.inc' %]
45
46           [% IF CAN_user_borrowers_edit_borrowers && pending_borrower_modifications %]
47             <div class="pending-info" id="patron_updates_pending">
48               <a href="/cgi-bin/koha/members/members-update.pl">Patrons requesting modifications</a>:
49               <span class="number_box"><a href="/cgi-bin/koha/members/members-update.pl">[% pending_borrower_modifications | html %]</a></span>
50             </div>
51           [% END %]
52
53           <div id="searchresults">
54             [% IF CAN_user_tools_manage_patron_lists || CAN_user_borrowers_edit_borrowers %]
55               <div class="searchheader fh-fixedHeader" id="searchheader" style="display:none;">
56                   <div>
57                       <a href="#" class="btn btn-link" id="select_all"><i class="fa fa-check"></i> Select all</a>
58                       |
59                       <a href="#" class="btn btn-link" id="clear_all"><i class="fa fa-times"></i> Clear all</a>
60                     [% IF CAN_user_tools_manage_patron_lists %]
61
62                     [% END %]
63
64                     [% IF CAN_user_tools_manage_patron_lists %]
65                         <div id="patronlist-dropdown" class="btn-group">
66                             <button id="patronlist-menu" type="button" class="btn btn-sm btn-default dropdown-toggle patron-edits disabled" disabled="disabled" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
67                                 Add to patron list <span class="caret"></span>
68                             </button>
69                             <ul class="dropdown-menu">
70                                 [% IF patron_lists %]
71                                     [% FOREACH pl IN patron_lists %]
72                                         <li><a href="#" class="patron-list-add" data-listid="[% pl.patron_list_id | html %]">[% pl.name | html %]</a></li>
73                                     [% END %]
74                                 [% END %]
75                                 <li role="separator" class="divider"></li>
76                                 <li><a href="#" class="patron-list-add" data-listid="new">New list</a></li>
77                             </ul>
78                         </div>
79                     [% END %]
80
81                     [% IF CAN_user_borrowers_edit_borrowers %]
82                         <div class="btn-group">
83                             <button id="merge-patrons" class="btn btn-sm btn-default disabled" disabled="disabled" type="submit"><i class="fa fa-compress" aria-hidden="true"></i> Merge selected patrons</button>
84                         </div>
85                     [% END %]
86
87                     [% IF CAN_user_tools_edit_patrons %]
88                         <div class="btn-group">
89                             <button id="batch-mod-patrons" class="btn btn-default btn-sm" type="button"><i class="fa fa-pencil" aria-hidden="true"></i> Batch patron modification</button>
90                         </div>
91                     [% END %]
92
93                     <div id="patron_search_selected" class="btn-group" style="display:none;">
94                         <span></span>
95                         <a href="#" id="clear-patron-selection"><i class="fa fa-times"></i> Clear</a>
96                     </div>
97                   </div>
98                 </div>
99             [% END %]
100
101             [% IF CAN_user_borrowers_edit_borrowers || CAN_user_tools_manage_patron_lists %]
102                 [% columns.unshift('checkbox') | html %]
103             [% END %]
104             [% PROCESS patron_search_table table_id => 'memberresultst' columns => columns %]
105           </div>
106         [% IF CAN_user_tools_edit_patrons %]
107             <form id="patron_batchmod_form" method="post" action="/cgi-bin/koha/tools/modborrowers.pl">
108                 <input type="hidden" name="op" value="show" />
109                 <textarea style="display:none" id="borrowernumberlist" name="borrowernumberlist"></textarea>
110             </form>
111         [% END %]
112
113             </main>
114         </div> <!-- /.col-sm-10.col-sm-push-2 -->
115
116         <div class="col-sm-2 col-sm-pull-10">
117             <aside>
118                 [% PROCESS patron_search_filters categories => categories, libraries => libraries, filters => ['search_field', 'search_type', 'category', 'branch'], search_filter => searchmember %]
119             </aside>
120         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
121     </div> <!-- /.row -->
122
123     <!-- New Patron List Modal -->
124     <div class="modal" id="new-patron-list" tabindex="-1" role="dialog" aria-labelledby="new-patron-listLabel">
125         <div class="modal-dialog" role="document">
126             <div class="modal-content">
127                 <div class="modal-header">
128                     <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
129                     <h4 class="modal-title" id="new-patron-listLabel">Add patrons to a new patron list</h4>
130                 </div>
131                 <form id="new-patron-list_form">
132                     <div class="modal-body">
133                         <div class="form-group">
134                             <label for="new_patron_list" class="required">Patron list name: </label>
135                             <input class="form-control required" type="text" name="new_patron_list" id="new_patron_list" required="required" />
136                             <input type="hidden" name="add_to_patron_list" id="add_to_patron_list" />
137                             <span class="required">Required</span>
138                         </div>
139                     </div> <!-- /.modal-body -->
140                     <div class="modal-footer">
141                         <button type="submit" id="add_to_patron_list_submit" class="btn btn-default approve">Submit</button>
142                         <button type="button" class="btn btn-default deny" data-dismiss="modal">Cancel</button>
143                     </div> <!-- /.modal-footer -->
144                 </form> <!-- /#new-patron-list_form -->
145             </div> <!-- /.modal-content -->
146         </div> <!-- /.modal-dialog -->
147     </div> <!-- /#new-patron-list -->
148
149 [% MACRO jsinclude BLOCK %]
150     [% INCLUDE 'datatables.inc' %]
151     [% INCLUDE 'columns_settings.inc' %]
152     [% INCLUDE 'str/members-menu.inc' %]
153     [% Asset.js("js/members-menu.js") | $raw %]
154     [% INCLUDE 'select2.inc' %]
155     <script>
156         function showPatronSelections( number ){
157             $("#patron_search_selected").show().find("span").text(_("Patrons selected: " + number ) );
158         }
159
160         $(document).ready(function() {
161             $('#merge-patrons, #batch-mod-patrons').prop('disabled', true);
162             $('#memberresultst').on('change', 'input.selection', function() {
163                 var patron_search_selections = JSON.parse( localStorage.getItem("patron_search_selections") ) || [];
164                 var borrowernumber = $(this).val();
165                 if( $(this).prop("checked") ){
166                     patron_search_selections.push( $(this).val() );
167                     localStorage.setItem('patron_search_selections', JSON.stringify( patron_search_selections ));
168                     showPatronSelections( patron_search_selections.length );
169                 } else {
170                     var filtered = patron_search_selections.filter(function( value ){
171                         return value !== borrowernumber;
172                     });
173                     if( filtered.length > 0 ){
174                         localStorage.setItem('patron_search_selections', JSON.stringify( filtered ));
175                         patron_search_selections = filtered;
176                         showPatronSelections( filtered.length );
177                     } else {
178                         patron_search_selections = [];
179                         localStorage.removeItem('patron_search_selections');
180                         $("#patron_search_selected").hide();
181                     }
182                 }
183                 if ( patron_search_selections.length > 1 ) {
184                     /* More than one checkbox has been checked. All batch options enabled */
185                     $("#batch-mod-patrons, #merge-patrons, #patronlist-menu").removeClass("disabled").prop("disabled", false);
186                 } else if ( patron_search_selections.length == 1 ) {
187                     /* Only one checkbox has been checked */
188                     $("#batch-mod-patrons, #patronlist-menu").removeClass("disabled").prop("disabled", false);
189                     /* Merge requires more than one selection */
190                     $('#merge-patrons').prop('disabled', true).addClass("disabled");
191                 } else {
192                     /* No checkbox has been checked. No batch options enabled */
193                     $("#batch-mod-patrons, #merge-patrons, #patronlist-menu").addClass("disabled").prop("disabled", true);
194                 }
195             });
196
197             $('#merge-patrons').on('click', function() {
198                 var patron_search_selections = JSON.parse( localStorage.getItem("patron_search_selections") ) || [];
199                 var merge_patrons_url = 'merge-patrons.pl?id=' + patron_search_selections.join("&id=");
200                 window.location.href = merge_patrons_url;
201             });
202
203             $("#clear-patron-selection").on("click", function(e){
204                 e.preventDefault();
205                 $("input.selection").prop("checked", false).change();
206                 localStorage.removeItem("patron_search_selections");
207                 $("#patron_search_selected").hide();
208                 $('#merge-patrons, #patronlist-menu, #batch-mod-patrons').prop('disabled', true).addClass("disabled");
209                 $("#borrowernumberlist").val("");
210             });
211
212             $("#patronlist-dropdown").on("click", ".patron-list-add", function(e){
213                 e.preventDefault();
214                 var patron_search_selections = JSON.parse( localStorage.getItem("patron_search_selections") ) || [];
215                 if ( patron_search_selections.length == 0 ) {
216                     alert( _("You have not selected any patrons to add to a list!") );
217                     $(".btn-group").removeClass("open"); /* Close button menu */
218                     return false;
219                 }
220
221                 var listid = $(this).data("listid");
222                 $("#add_to_patron_list").val( listid );
223                 if( listid == "new" ){
224                     /* #add_to_patron_list value "new" in the modal form will tell API to create a new list */
225                     $("#new-patron-list").modal("show");
226                 } else {
227                     /* Ajax submit the patrons to list */
228
229                     patronListAdd();
230                 }
231             });
232
233             $("#batch-mod-patrons").on("click", function(e) {
234                 e.preventDefault();
235                 var patron_search_selections = JSON.parse( localStorage.getItem("patron_search_selections") ) || [];
236                 if( patron_search_selections.length > 0 ){
237                     $("#borrowernumberlist").html( patron_search_selections.join('\n') );
238                     $("#patron_batchmod_form").submit();
239                 }
240             });
241
242             /* Submit selected patrons to a list via AJAX */
243             $("#new-patron-list_form").on('submit', function(e){
244                 e.preventDefault();
245                 /* Upon submitting modal patron list add form... */
246                 if ( $('#new_patron_list').val() ) {
247                     $(".patron-list-add").each(function() {
248                         /* Check each list name in the menu of patron lists */
249                         /* If submitted list name matches... */
250                         if ( $(this).text() == $('#new_patron_list').val() ) {
251                             alert( _("You already have a list with that name!") );
252                             return false;
253                         }
254                     });
255                 } else {
256                     alert( _("You must give your new patron list a name!") );
257                     return false;
258                 }
259                 $("#new-patron-list").modal("hide");
260                 patronListAdd();
261             });
262
263             $("#select_all").on("click",function(e){
264                 e.preventDefault();
265                 $("input.selection").each(function(){
266                     if( $(this).prop("checked") == false ){
267                         $(this).prop( "checked", true ).change();
268                     }
269                 });
270             });
271             $("#clear_all").on("click",function(e){
272                 e.preventDefault();
273                 $("input.selection").each(function(){
274                     if( $(this).prop("checked") ){
275                         $(this).prop("checked", false ).change();
276                     }
277                 });
278             });
279
280             [% IF searchmember %]
281                 $("#searchmember_filter").val("[% searchmember | html %]");
282             [% END %]
283             [% IF searchfieldstype %]
284                 $("searchfieldstype_filter").val("[% searchfieldstype | html %]");
285             [% END %]
286             [% IF searchtype %]
287                 $("#searchtype_filter option[value='[% searchtype | html %]']").prop("selected", true);
288             [% END %]
289             [% IF categorycode_filter %]
290                 $("#categorycode_filter").val("[% categorycode_filter | html %]");
291             [% END %]
292             [% IF branchcode_filter %]
293                 $("#branchcode_filter").val("[% branchcode_filter | html %]");
294             [% END %]
295
296             $("#searchheader").hide();
297             $("#patron_search_form").on('submit', function(){$("#searchheader").show();});
298             $("#clear_search").on("click",function(e){$("#searchheader").hide();});
299         });
300
301         function patronListAdd(){
302             var borrowernumbers = JSON.parse( localStorage.getItem("patron_search_selections") ) || [];
303             if ( borrowernumbers.length > 0 ){
304                 var data = {
305                     add_to_patron_list: $("#add_to_patron_list").val(),
306                     new_patron_list: $("#new_patron_list").val(),
307                     borrowernumbers: borrowernumbers
308                 };
309                 $.ajax({
310                     data: data,
311                     type: 'POST',
312                     url: '/cgi-bin/koha/svc/members/add_to_list',
313                     success: function(data) {
314                         $("#patron_list_dialog").show();
315                         $("#patron_list_dialog > span.patrons-length").html(data.patrons_added_to_list);
316                         $("#patron_list_dialog > a").attr("href", "/cgi-bin/koha/patron_lists/list.pl?patron_list_id=" + data.patron_list.patron_list_id);
317                         $("#patron_list_dialog > a").html(data.patron_list.name);
318
319                         if ( $('#add_to_patron_list').val() == 'new' ) {
320                             /* Add a new entry to the menu */
321                             $("#patronlist-dropdown .divider").before('<li><a class="patron-list-add" href="#" data-listid="' + data.patron_list.patron_list_id + '">' + data.patron_list.name + '</li>');
322                         }
323                     },
324                     error: function() {
325                         alert( _("An error occurred. Patron list could not be updated.") );
326                     }
327                 });
328                 return true;
329             } else {
330                 alert( _("You have not selected any patrons to add to a list!") );
331                 return false;
332             }
333         }
334
335         function prepSelections(){
336             var selected_patrons = JSON.parse( localStorage.getItem("patron_search_selections") );
337             if( selected_patrons && selected_patrons.length > 0 ){
338                 showPatronSelections( selected_patrons.length );
339
340                 $('#merge-patrons').prop('disabled', true);
341                 $("input.selection").each(function(){
342                     var cardnumber = $(this).val();
343                     if( selected_patrons.indexOf( cardnumber ) >= 0 ){
344                         $(this).prop("checked", true );
345                     }
346                 });
347
348                 if( selected_patrons.length > 1 ){
349                     $('#batch-mod-patrons, #merge-patrons, #patronlist-menu').removeClass("disabled").prop('disabled', false);
350                 }
351             }
352         }
353
354         $('#memberresultst tbody').on('click','td',function(e){
355             var $checkbox = $(this).find("input[type=checkbox]");
356             if (e.target.type != "checkbox") {
357                 $checkbox.prop('checked', !$checkbox.prop("checked"));
358                 $checkbox.change();
359             }
360         });
361
362     </script>
363
364     <script>
365         // Apply DataTables on the results table
366         var table_settings = [% TablesSettings.GetTableSettings( 'members', 'member', 'memberresultst', 'json' ) | $raw %];
367         [% UNLESS CAN_user_borrowers_edit_borrowers OR CAN_user_tools_manage_patron_lists %]
368             [%# Remove the first column if we do not display the checkbox %]
369             table_settings['columns'].splice(0, 1);
370         [% END %]
371     </script>
372
373     [% IF circsearch == 1 %]
374         [% SET redirect_url = '/cgi-bin/koha/circ/circulation.pl' %]
375     [% ELSE %]
376         [% SET redirect_url = '/cgi-bin/koha/members/moremember.pl' %]
377     [% END %]
378     [% PROCESS patron_search_js table_id => 'memberresultst', categories => categories, libraries => libraries, extended_attribute_types => attribute_type_codes, columns => columns,actions => ['edit', 'checkout'], redirect_if_one_result => 1, redirect_url => redirect_url, sticky_header => "searchheader", sticky_to => "searchresults", default_sort_column => 'name-address', display_search_description => 1, remember_selections => 1 %]
379
380 [% END %]
381
382 [% INCLUDE 'intranet-bottom.inc' %]