Bug 35475: Makes strings in booking JS file translatable
[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                         [% IF CAN_user_circulate_manage_bookings %]
110                         editable: { remove: true, updateTime: true },
111                         [% ELSE %]
112                         editable: false,
113                         [% END %]
114                         type: 'range',
115                         group: booking.item_id ? booking.item_id : 0
116                     });
117                 }
118
119                 var container = document.getElementById('bookings-timeline');
120                 var options = {
121                     stack: true,
122                     verticalScroll: true,
123                     orientation: {
124                         axis: "both",
125                         item: "top"
126                     },
127                     timeAxis: {scale: 'day', step: 1},
128                     dataAttributes: [ 'booking' ],
129
130                     // always snap to full days, independent of the scale
131                     snap: function (date, scale, step) {
132                         let offset = date.getTimezoneOffset() * 60 * 1000;
133                         let day = 24 * 60 * 60 * 1000;
134                         let seconds = Math.round(date / day) * day;
135                         return seconds + offset;
136                     },
137
138                     // prevent overlapping bookings
139                     onMoving: function (item, callback) {
140                         var overlapping = bookingsSet.get({
141                             filter: function(testItem) {
142                                 if (testItem.id == item.id) {
143                                     return false;
144                                 }
145                                 if (testItem.group != item.group) {
146                                     return false;
147                                 }
148                                 return ((item.start < testItem.end) && (item.end > testItem.start));
149                             }
150                         });
151
152                         if (overlapping.length == 0) {
153                             callback(item);
154                         }
155                     },
156
157                     // action events
158                     onMove: function (data, callback) {
159                         let startDate = dayjs(data.start);
160
161                         // set end datetime hours and minutes to the end of the day
162                         let endDate = dayjs(data.end).endOf('day');
163
164                         $('#placeBookingModal').modal('show', $('<button data-booking="'+data.id+'"  data-biblionumber="[% biblionumber | uri %]"  data-itemnumber="'+data.group+'" data-patron="'+data.patron+'" data-start_date="'+startDate.toISOString()+'" data-end_date="'+endDate.toISOString()+'">'));
165                         $('#placeBookingModal').on('hide.bs.modal', function(e) {
166                             if (update_success) {
167                                 update_success = 0;
168                                 callback(data);
169                             } else {
170                                 callback(null);
171                             }
172                         });
173                     },
174                     onRemove: function (item, callback) {
175                         $('#cancelBookingModal').modal('show', $('<button data-booking="'+item.id+'">'));
176                         $('#cancelBookingModal').on('hide.bs.modal', function(e) {
177                             if (cancel_success) {
178                                 cancel_success = 0;
179                                 callback(item);
180                             } else {
181                                 callback(null);
182                             }
183                         });
184                     }
185                 };
186                 timeline = new vis.Timeline(container, bookingsSet, itemsSet, options);
187             },
188             function(jqXHR, textStatus, errorThrown){
189                 console.log("Fetch failed");
190             }
191         );
192
193         var bookings_table_url = "/api/v1/biblios/[% biblionumber | uri %]/bookings";
194         bookings_table = $('#bookings_table').kohaTable({
195             "ajax": {
196                 "url": bookings_table_url
197             },
198             "embed": [
199                 "item",
200                 "patron"
201             ],
202             "columns": [{
203                 "data": "booking_id",
204                 "title": _("Booking ID"),
205                 "visible": false
206             },
207             {
208                 "data": "item.external_id",
209                 "title": _("Item"),
210                 "searchable": true,
211                 "orderable": true,
212                 "defaultContent": _("Any item"),
213                 "render": function(data,type,row,meta) {
214                     if ( row.item ) {
215                         return row.item.external_id + " (" + row.booking_id + ")";
216                     } else {
217                         return null;
218                     }
219                 }
220             },
221             {
222                 "data": "patron.firstname:patron.surname",
223                 "title": _("Patron"),
224                 "searchable": true,
225                 "orderable": true,
226                 "render": function(data, type, row, meta) {
227                     return $patron_to_html(row.patron, {
228                         display_cardnumber: true,
229                         url: true
230                     });
231                 }
232             },
233             {
234                 "data": "start_date",
235                 "title": _("Start date"),
236                 "searchable": true,
237                 "orderable": true,
238                 "render": function(data, type, row, meta) {
239                     return $date(row.start_date);
240                 }
241             },
242             {
243                 "data": "end_date",
244                 "title": _("End date"),
245                 "searchable": true,
246                 "orderable": true,
247                 "render": function(data, type, row, meta) {
248                     return $date(row.end_date);
249                 }
250             },
251             {
252                 "data": "",
253                 "title": _("Actions"),
254                 "class": "actions",
255                 "searchable": false,
256                 "orderable": false,
257                 "render": function(data, type, row, meta) {
258                     let result = "";
259                     [% IF CAN_user_circulate_manage_bookings %]
260                     result += '<button type="button" class="btn btn-default btn-xs edit-action" data-toggle="modal" data-target="#placeBookingModal" data-booking="'+row.booking_id+'" data-biblionumber="[% biblionumber | uri %]" data-itemnumber="'+row.item_id+'" data-patron="'+row.patron_id+'" data-start_date="'+row.start_date+'" data-end_date="'+row.end_date+'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</button>';
261                     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>';
262                     [% END %]
263                     return result;
264                 }
265             }]
266         }, [], 0);
267     });
268 </script>
269     [% END %]
270
271 [% INCLUDE 'intranet-bottom.inc' %]