Bug 29002: Hide search header in bookings table
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / bookings / list.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE KohaDates %]
4 [% SET footerjs = 1 %]
5 [% INCLUDE 'doc-head-open.inc' %]
6 <title>Bookings for [% INCLUDE 'biblio-title-head.inc' %] &rsaquo; Bookings &rsaquo; Circulation &rsaquo; Koha</title>
7 [% INCLUDE 'doc-head-close.inc' %]
8 </head>
9
10 <body id="circ_request" class="catalog">
11
12 [% WRAPPER 'header.inc' %]
13     [% INCLUDE 'cat-search.inc' %]
14 [% END %]
15
16 [% WRAPPER 'sub-header.inc' %]
17     [% WRAPPER breadcrumbs %]
18         [% WRAPPER breadcrumb_item %]
19             <a href="/cgi-bin/koha/catalogue/search.pl">Catalog</a>
20         [% END %]
21         [% WRAPPER breadcrumb_item %]
22             [% INCLUDE 'biblio-title.inc' link = 1 %]
23         [% END %]
24         [% WRAPPER breadcrumb_item bc_active= 1 %]
25             <span>Bookings</span>
26         [% END %]
27     [% END #/ WRAPPER breadcrumbs %]
28 [% END #/ WRAPPER sub-header.inc %]
29
30 <div class="main container-fluid">
31     <div class="row">
32         <div class="col-sm-10 col-sm-push-2">
33             <main>
34                 <div class="row">
35                     [% INCLUDE 'cat-toolbar.inc' %]
36                     <h1>Bookings for [% INCLUDE 'biblio-title-head.inc' %]</h1>
37                     <div class="page-section" id="bookings-timeline"></div>
38                     <div class="page-section">
39                         <table id="bookings_table"></table>
40                     </div>
41                 </div>
42             </main>
43         </div> <!-- /.col-sm-10.col-sm-push-2 -->
44
45         <div class="col-sm-2 col-sm-pull-10">
46             <aside>
47                 [% INCLUDE 'biblio-view-menu.inc' %]
48             </aside>
49         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
50     </div> <!-- /.row -->
51
52     [% INCLUDE modals/cancel_booking.inc %]
53
54     [% MACRO jsinclude BLOCK %]
55     [% Asset.js("lib/dayjs/dayjs.min.js") | $raw %]
56     [% Asset.js("lib/vis-timeline/vis-timeline-graph2d.min.js") | $raw %]
57     [% INCLUDE 'datatables.inc' %]
58     [% INCLUDE 'columns_settings.inc' %]
59     [% INCLUDE 'calendar.inc' %]
60     [% INCLUDE 'select2.inc' %]
61     [% INCLUDE 'js-patron-format.inc' %]
62     [% INCLUDE 'js-date-format.inc' %]
63     [% Asset.js("js/place_booking_modal.js") | $raw %]
64     [% Asset.js("js/cancel_booking_modal.js") | $raw %]
65 <script>
66     var cancel_success = 0;
67     var update_success = 0;
68     var bookings_table;
69     var timeline;
70     $(document).ready(function(){
71
72         var items = $.ajax({
73             url: '/api/v1/biblios/[% biblionumber | uri %]/items?bookable=1',
74             dataType: 'json',
75             type: 'GET'
76         });
77         var bookings = $.ajax({
78             url: '/api/v1/biblios/[% biblionumber | uri %]/bookings',
79             headers: { 'x-koha-embed': 'patron' },
80             dataType: 'json',
81             type: 'GET',
82         });
83
84         $.when(items, bookings).then(
85             function(items, bookings){
86                 var itemsSet = new vis.DataSet([{
87                     id: 0,
88                     content: "Biblio level"
89                 }]);
90                 for (item of items[0]) {
91                     itemsSet.add({
92                         id: item.item_id,
93                         content: "Item " + item.external_id,
94                     });
95                 }
96
97                 var bookingsSet = new vis.DataSet();
98                 for (booking of bookings[0]){
99                     bookingsSet.add({
100                         id: booking.booking_id,
101                         booking: booking.booking_id,
102                         patron: booking.patron_id,
103                         start: dayjs(booking.start_date).toDate(),
104                         end: dayjs(booking.end_date).toDate(),
105                         content: $patron_to_html(booking.patron, {
106                             display_cardnumber: true,
107                             url: false
108                         }),
109                         editable: { remove: true, updateTime: true },
110                         type: 'range',
111                         group: booking.item_id ? booking.item_id : 0
112                     });
113                 }
114
115                 var container = document.getElementById('bookings-timeline');
116                 var options = {
117                     stack: true,
118                     verticalScroll: true,
119                     orientation: {
120                         axis: "both",
121                         item: "top"
122                     },
123                     timeAxis: {scale: 'day', step: 1},
124                     dataAttributes: [ 'booking' ],
125
126                     // always snap to full days, independent of the scale
127                     snap: function (date, scale, step) {
128                         let offset = date.getTimezoneOffset() * 60 * 1000;
129                         let day = 24 * 60 * 60 * 1000;
130                         let seconds = Math.round(date / day) * day;
131                         return seconds + offset;
132                     },
133
134                     // prevent overlapping bookings
135                     onMoving: function (item, callback) {
136                         var overlapping = bookingsSet.get({
137                             filter: function(testItem) {
138                                 if (testItem.id == item.id) {
139                                     return false;
140                                 }
141                                 if (testItem.group != item.group) {
142                                     return false;
143                                 }
144                                 return ((item.start < testItem.end) && (item.end > testItem.start));
145                             }
146                         });
147
148                         if (overlapping.length == 0) {
149                             callback(item);
150                         }
151                     },
152
153                     // action events
154                     onMove: function (item, callback) {
155
156                         let startDate = new Date(item.start);
157                         
158                         // set end datetime hours and minutes to the end of the day
159                         let endDate = new Date(item.end);
160                         endDate.setHours(endDate.getHours()+23);
161                         endDate.setMinutes(endDate.getMinutes()+59);
162
163                         let url = '/api/v1/bookings/'+item.booking;
164                         var putting = $.ajax({
165                             method: 'PUT',
166                             url: url,
167                             data: JSON.stringify({
168                                 "booking_id": item.booking,
169                                 "start_date": startDate.toISOString(),
170                                 "end_date": endDate.toISOString(),
171                                 "biblio_id": [% biblionumber | uri %],
172                                 "item_id": item.group != 0 ? item.group : null,
173                                 "patron_id": item.patron
174                             })
175                         });
176
177                         putting.done(function(data) {
178                             bookings_table.api().ajax.reload();
179                             callback(item);
180                         });
181
182                         putting.fail(function(data) {
183                             $('#booking_result').replaceWith('<div id="booking_result" class="alert alert-danger">Failure</div>');
184                         });
185                     },
186                     onRemove: function (item, callback) {
187                         $('#cancelBookingModal').modal('show', $('<button data-booking="'+item.id+'">'));
188                         $('#cancelBookingModal').on('hide.bs.modal', function(e) {
189                             if (cancel_success) {
190                                 cancel_success = 0;
191                                 callback(item);
192                             }
193                         });
194                     }
195                 };
196                 timeline = new vis.Timeline(container, bookingsSet, itemsSet, options);
197             },
198             function(jqXHR, textStatus, errorThrown){
199                 console.log("Fetch failed");
200             }
201         );
202
203         var bookings_table_url = "/api/v1/biblios/[% biblionumber | uri %]/bookings";
204         bookings_table = $('#bookings_table').kohaTable({
205             "ajax": {
206                 "url": bookings_table_url
207             },
208             "embed": [
209                 "item",
210                 "patron"
211             ],
212             "columns": [{
213                 "data": "booking_id",
214                 "title": "Booking ID",
215                 "visible": false
216             },
217             {
218                 "data": "item.external_id",
219                 "title": "Item",
220                 "searchable": true,
221                 "orderable": true,
222                 "defaultContent": "Any item",
223                 "render": function(data,type,row,meta) {
224                     if ( row.item ) {
225                         return row.item.external_id;
226                     } else {
227                         return null;
228                     }
229                 }
230             },
231             {
232                 "data": "patron.firstname:patron.surname",
233                 "title": "Patron",
234                 "searchable": true,
235                 "orderable": true,
236                 "render": function(data, type, row, meta) {
237                     return $patron_to_html(row.patron, {
238                         display_cardnumber: false,
239                         url: true
240                     });
241                 }
242             },
243             {
244                 "data": "start_date",
245                 "title": "Start date",
246                 "searchable": true,
247                 "orderable": true,
248                 "render": function(data, type, row, meta) {
249                     return $date(row.start_date);
250                 }
251             },
252             {
253                 "data": "end_date",
254                 "title": "End date",
255                 "searchable": true,
256                 "orderable": true,
257                 "render": function(data, type, row, meta) {
258                     return $date(row.end_date);
259                 }
260             },
261             {
262                 "data": "",
263                 "title": "Actions",
264                 "searchable": false,
265                 "orderable": false,
266                 "render": function(data, type, row, meta) {
267                     var result = '<button type="button" class="btn btn-default btn-xs cancel-action" data-toggle="modal" data-target="#cancelBookingModal" data-booking="'+row.booking_id+'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Cancel")+'</button>';
268                     return result;
269                 }
270             }]
271         }, [], 0);
272     });
273 </script>
274     [% END %]
275
276 [% INCLUDE 'intranet-bottom.inc' %]