Lines 1-60
Link Here
|
1 |
let dataFetched = false; |
1 |
let dataFetched = false; |
2 |
let bookable_items, bookings, checkouts, booking_id, booking_item_id, booking_patron; |
2 |
let bookable_items, |
3 |
|
3 |
bookings, |
4 |
$('#placeBookingModal').on('show.bs.modal', function(e) { |
4 |
checkouts, |
5 |
|
5 |
booking_id, |
|
|
6 |
booking_item_id, |
7 |
booking_patron; |
8 |
|
9 |
$("#placeBookingModal").on("show.bs.modal", function (e) { |
6 |
// Get context |
10 |
// Get context |
7 |
let button = $(e.relatedTarget); |
11 |
let button = $(e.relatedTarget); |
8 |
let biblionumber = button.data('biblionumber'); |
12 |
let biblionumber = button.data("biblionumber"); |
9 |
$('#booking_biblio_id').val(biblionumber); |
13 |
$("#booking_biblio_id").val(biblionumber); |
10 |
|
14 |
|
11 |
let patron_id = button.data('patron') || 0; |
15 |
let patron_id = button.data("patron") || 0; |
12 |
booking_item_id = button.data('itemnumber'); |
16 |
booking_item_id = button.data("itemnumber"); |
13 |
let start_date = button.data('start_date'); |
17 |
let start_date = button.data("start_date"); |
14 |
let end_date = button.data('end_date'); |
18 |
let end_date = button.data("end_date"); |
15 |
|
19 |
|
16 |
// Get booking id if this is an edit |
20 |
// Get booking id if this is an edit |
17 |
booking_id = button.data('booking'); |
21 |
booking_id = button.data("booking"); |
18 |
if (booking_id) { |
22 |
if (booking_id) { |
19 |
$('#placeBookingLabel').html(__("Edit booking")); |
23 |
$("#placeBookingLabel").html(__("Edit booking")); |
20 |
$('#booking_id').val(booking_id); |
24 |
$("#booking_id").val(booking_id); |
21 |
} else { |
25 |
} else { |
22 |
$('#placeBookingLabel').html(__("Place booking")); |
26 |
$("#placeBookingLabel").html(__("Place booking")); |
23 |
// Ensure we don't accidentally update a booking |
27 |
// Ensure we don't accidentally update a booking |
24 |
$('#booking_id').val(''); |
28 |
$("#booking_id").val(""); |
25 |
} |
29 |
} |
26 |
|
30 |
|
27 |
// Patron select2 |
31 |
// Patron select2 |
28 |
$("#booking_patron_id").kohaSelect({ |
32 |
$("#booking_patron_id").kohaSelect({ |
29 |
dropdownParent: $(".modal-content", "#placeBookingModal"), |
33 |
dropdownParent: $(".modal-content", "#placeBookingModal"), |
30 |
width: '50%', |
34 |
width: "50%", |
31 |
dropdownAutoWidth: true, |
35 |
dropdownAutoWidth: true, |
32 |
allowClear: true, |
36 |
allowClear: true, |
33 |
minimumInputLength: 3, |
37 |
minimumInputLength: 3, |
34 |
ajax: { |
38 |
ajax: { |
35 |
url: '/api/v1/patrons', |
39 |
url: "/api/v1/patrons", |
36 |
delay: 250, |
40 |
delay: 250, |
37 |
dataType: 'json', |
41 |
dataType: "json", |
38 |
headers: { |
42 |
headers: { |
39 |
"x-koha-embed": "library" |
43 |
"x-koha-embed": "library", |
40 |
}, |
44 |
}, |
41 |
data: function(params) { |
45 |
data: function (params) { |
42 |
let q = buildPatronSearchQuery(params.term); |
46 |
let q = buildPatronSearchQuery(params.term); |
43 |
let query = { |
47 |
let query = { |
44 |
'q': JSON.stringify(q), |
48 |
q: JSON.stringify(q), |
45 |
'_page': params.page, |
49 |
_page: params.page, |
46 |
'_order_by': '+me.surname,+me.firstname', |
50 |
_order_by: "+me.surname,+me.firstname", |
47 |
}; |
51 |
}; |
48 |
return query; |
52 |
return query; |
49 |
}, |
53 |
}, |
50 |
processResults: function(data, params) { |
54 |
processResults: function (data, params) { |
51 |
let results = []; |
55 |
let results = []; |
52 |
data.results.forEach(function(patron) { |
56 |
data.results.forEach(function (patron) { |
53 |
patron.id = patron.patron_id; |
57 |
patron.id = patron.patron_id; |
54 |
results.push(patron); |
58 |
results.push(patron); |
55 |
}); |
59 |
}); |
56 |
return { |
60 |
return { |
57 |
"results": results, "pagination": { "more": data.pagination.more } |
61 |
results: results, |
|
|
62 |
pagination: { more: data.pagination.more }, |
58 |
}; |
63 |
}; |
59 |
}, |
64 |
}, |
60 |
}, |
65 |
}, |
Lines 85-94
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
85 |
__("years") + |
90 |
__("years") + |
86 |
"</span>" |
91 |
"</span>" |
87 |
: "") + |
92 |
: "") + |
88 |
(patron.library ? |
93 |
(patron.library |
89 |
" <span class=\"ac-library\">" + |
94 |
? ' <span class="ac-library">' + |
90 |
escape_str(patron.library.name) + |
95 |
escape_str(patron.library.name) + |
91 |
"</span>" |
96 |
"</span>" |
92 |
: "") + |
97 |
: "") + |
93 |
"</small>" |
98 |
"</small>" |
94 |
) |
99 |
) |
Lines 99-145
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
99 |
if (!patron.surname) { |
104 |
if (!patron.surname) { |
100 |
return patron.text; |
105 |
return patron.text; |
101 |
} |
106 |
} |
102 |
return ( |
107 |
return patron.surname + ", " + patron.firstname; |
103 |
patron.surname + ", " + patron.firstname |
|
|
104 |
); |
105 |
}, |
108 |
}, |
106 |
placeholder: __("Search for a patron") |
109 |
placeholder: __("Search for a patron"), |
107 |
}); |
110 |
}); |
108 |
|
111 |
|
109 |
$('#booking_patron_id').on('select2:select', function (e) { |
112 |
$("#booking_patron_id").on("select2:select", function (e) { |
110 |
booking_patron = e.params.data; |
113 |
booking_patron = e.params.data; |
111 |
}); |
114 |
}); |
112 |
|
115 |
|
113 |
// Adopt periodPicker |
116 |
// Adopt periodPicker |
114 |
let periodPicker = $("#period").get(0)._flatpickr; |
117 |
let periodPicker = $("#period").get(0)._flatpickr; |
115 |
|
118 |
|
116 |
if ( !dataFetched ) { |
119 |
if (!dataFetched) { |
117 |
|
|
|
118 |
// Fetch list of bookable items |
120 |
// Fetch list of bookable items |
119 |
let itemsFetch = $.ajax({ |
121 |
let itemsFetch = $.ajax({ |
120 |
url: '/api/v1/biblios/' + biblionumber + '/items?bookable=1' + '&_per_page=-1', |
122 |
url: |
121 |
dataType: 'json', |
123 |
"/api/v1/biblios/" + |
122 |
type: 'GET' |
124 |
biblionumber + |
|
|
125 |
"/items?bookable=1" + |
126 |
"&_per_page=-1", |
127 |
dataType: "json", |
128 |
type: "GET", |
123 |
}); |
129 |
}); |
124 |
|
130 |
|
125 |
// Fetch list of existing bookings |
131 |
// Fetch list of existing bookings |
126 |
let bookingsFetch = $.ajax({ |
132 |
let bookingsFetch = $.ajax({ |
127 |
url: '/api/v1/bookings?biblio_id=' + biblionumber + '&_per_page=-1', |
133 |
url: "/api/v1/bookings?biblio_id=" + biblionumber + "&_per_page=-1", |
128 |
dataType: 'json', |
134 |
dataType: "json", |
129 |
type: 'GET' |
135 |
type: "GET", |
130 |
}); |
136 |
}); |
131 |
|
137 |
|
132 |
// Fetch list of current checkouts |
138 |
// Fetch list of current checkouts |
133 |
let checkoutsFetch = $.ajax({ |
139 |
let checkoutsFetch = $.ajax({ |
134 |
url: '/api/v1/biblios/' + biblionumber + '/checkouts?_per_page=-1', |
140 |
url: "/api/v1/biblios/" + biblionumber + "/checkouts?_per_page=-1", |
135 |
dataType: 'json', |
141 |
dataType: "json", |
136 |
type: 'GET' |
142 |
type: "GET", |
137 |
}); |
143 |
}); |
138 |
|
144 |
|
139 |
// Update item select2 and period flatpickr |
145 |
// Update item select2 and period flatpickr |
140 |
$.when(itemsFetch, bookingsFetch, checkoutsFetch).then( |
146 |
$.when(itemsFetch, bookingsFetch, checkoutsFetch).then( |
141 |
function(itemsFetch,bookingsFetch, checkoutsFetch){ |
147 |
function (itemsFetch, bookingsFetch, checkoutsFetch) { |
142 |
|
|
|
143 |
// Set variables |
148 |
// Set variables |
144 |
bookable_items = itemsFetch[0]; |
149 |
bookable_items = itemsFetch[0]; |
145 |
bookings = bookingsFetch[0]; |
150 |
bookings = bookingsFetch[0]; |
Lines 161-174
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
161 |
// Item select2 |
166 |
// Item select2 |
162 |
$("#booking_item_id").select2({ |
167 |
$("#booking_item_id").select2({ |
163 |
dropdownParent: $(".modal-content", "#placeBookingModal"), |
168 |
dropdownParent: $(".modal-content", "#placeBookingModal"), |
164 |
width: '50%', |
169 |
width: "50%", |
165 |
dropdownAutoWidth: true, |
170 |
dropdownAutoWidth: true, |
166 |
minimumResultsForSearch: 20, |
171 |
minimumResultsForSearch: 20, |
167 |
placeholder: __("Select item") |
172 |
placeholder: __("Select item"), |
168 |
}); |
173 |
}); |
169 |
|
174 |
|
170 |
// Update flatpickr mode |
175 |
// Update flatpickr mode |
171 |
periodPicker.set('mode', 'range'); |
176 |
periodPicker.set("mode", "range"); |
172 |
|
177 |
|
173 |
// Total bookable items |
178 |
// Total bookable items |
174 |
let bookable = 0; |
179 |
let bookable = 0; |
Lines 176-194
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
176 |
for (item of bookable_items) { |
181 |
for (item of bookable_items) { |
177 |
bookable++; |
182 |
bookable++; |
178 |
// Populate item select (NOTE: Do we still need this check for pre-existing select option here?) |
183 |
// Populate item select (NOTE: Do we still need this check for pre-existing select option here?) |
179 |
if (!($('#booking_item_id').find("option[value='" + item.item_id + "']").length)) { |
184 |
if ( |
|
|
185 |
!$("#booking_item_id").find( |
186 |
"option[value='" + item.item_id + "']" |
187 |
).length |
188 |
) { |
180 |
// Create a DOM Option and de-select by default |
189 |
// Create a DOM Option and de-select by default |
181 |
let newOption = new Option(escape_str(item.external_id), item.item_id, false, false); |
190 |
let newOption = new Option( |
|
|
191 |
escape_str(item.external_id), |
192 |
item.item_id, |
193 |
false, |
194 |
false |
195 |
); |
182 |
// Append it to the select |
196 |
// Append it to the select |
183 |
$('#booking_item_id').append(newOption); |
197 |
$("#booking_item_id").append(newOption); |
184 |
} |
198 |
} |
185 |
} |
199 |
} |
186 |
|
200 |
|
187 |
// Set disable function for periodPicker |
201 |
// Set disable function for periodPicker |
188 |
let disableExists = periodPicker.config.disable.filter(f => f.name === 'dateDisable'); |
202 |
let disableExists = periodPicker.config.disable.filter( |
189 |
if ( disableExists.length === 0 ) { |
203 |
f => f.name === "dateDisable" |
190 |
periodPicker.config.disable.push(function dateDisable(date){ |
204 |
); |
191 |
|
205 |
if (disableExists.length === 0) { |
|
|
206 |
periodPicker.config.disable.push(function dateDisable( |
207 |
date |
208 |
) { |
192 |
// set local copy of selectedDates |
209 |
// set local copy of selectedDates |
193 |
let selectedDates = periodPicker.selectedDates; |
210 |
let selectedDates = periodPicker.selectedDates; |
194 |
|
211 |
|
Lines 202-260
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
202 |
let biblio_bookings = []; |
219 |
let biblio_bookings = []; |
203 |
|
220 |
|
204 |
// disable dates before selected date |
221 |
// disable dates before selected date |
205 |
if (!selectedDates[1] && (selectedDates[0] && selectedDates[0] > date)) { |
222 |
if ( |
|
|
223 |
!selectedDates[1] && |
224 |
selectedDates[0] && |
225 |
selectedDates[0] > date |
226 |
) { |
206 |
return true; |
227 |
return true; |
207 |
} |
228 |
} |
208 |
|
229 |
|
209 |
// iterate existing bookings |
230 |
// iterate existing bookings |
210 |
for (booking of bookings) { |
231 |
for (booking of bookings) { |
211 |
|
|
|
212 |
// Skip if we're editing this booking |
232 |
// Skip if we're editing this booking |
213 |
if (booking_id && booking_id == booking.booking_id){ |
233 |
if ( |
|
|
234 |
booking_id && |
235 |
booking_id == booking.booking_id |
236 |
) { |
214 |
continue; |
237 |
continue; |
215 |
} |
238 |
} |
216 |
|
239 |
|
217 |
let start_date = flatpickr.parseDate(booking.start_date); |
240 |
let start_date = flatpickr.parseDate( |
218 |
let end_date = flatpickr.parseDate(booking.end_date); |
241 |
booking.start_date |
|
|
242 |
); |
243 |
let end_date = flatpickr.parseDate( |
244 |
booking.end_date |
245 |
); |
219 |
|
246 |
|
220 |
// patron has selected a start date (end date checks) |
247 |
// patron has selected a start date (end date checks) |
221 |
if (selectedDates[0]) { |
248 |
if (selectedDates[0]) { |
222 |
|
|
|
223 |
// new booking start date is between existing booking start and end dates |
249 |
// new booking start date is between existing booking start and end dates |
224 |
if (selectedDates[0] >= start_date && selectedDates[0] <= end_date) { |
250 |
if ( |
|
|
251 |
selectedDates[0] >= start_date && |
252 |
selectedDates[0] <= end_date |
253 |
) { |
225 |
if (booking.item_id) { |
254 |
if (booking.item_id) { |
226 |
if (unavailable_items.indexOf(booking.item_id) === -1) { |
255 |
if ( |
227 |
unavailable_items.push(booking.item_id); |
256 |
unavailable_items.indexOf( |
|
|
257 |
booking.item_id |
258 |
) === -1 |
259 |
) { |
260 |
unavailable_items.push( |
261 |
booking.item_id |
262 |
); |
228 |
} |
263 |
} |
229 |
} else { |
264 |
} else { |
230 |
if (biblio_bookings.indexOf(booking.booking_id) === -1) { |
265 |
if ( |
231 |
biblio_bookings.push(booking.booking_id); |
266 |
biblio_bookings.indexOf( |
|
|
267 |
booking.booking_id |
268 |
) === -1 |
269 |
) { |
270 |
biblio_bookings.push( |
271 |
booking.booking_id |
272 |
); |
232 |
} |
273 |
} |
233 |
} |
274 |
} |
234 |
} |
275 |
} |
235 |
|
276 |
|
236 |
// new booking end date would be between existing booking start and end dates |
277 |
// new booking end date would be between existing booking start and end dates |
237 |
else if (date >= start_date && date <= end_date) { |
278 |
else if ( |
|
|
279 |
date >= start_date && |
280 |
date <= end_date |
281 |
) { |
238 |
if (booking.item_id) { |
282 |
if (booking.item_id) { |
239 |
if (unavailable_items.indexOf(booking.item_id) === -1) { |
283 |
if ( |
240 |
unavailable_items.push(booking.item_id); |
284 |
unavailable_items.indexOf( |
|
|
285 |
booking.item_id |
286 |
) === -1 |
287 |
) { |
288 |
unavailable_items.push( |
289 |
booking.item_id |
290 |
); |
241 |
} |
291 |
} |
242 |
} else { |
292 |
} else { |
243 |
if (biblio_bookings.indexOf(booking.booking_id) === -1) { |
293 |
if ( |
244 |
biblio_bookings.push(booking.booking_id); |
294 |
biblio_bookings.indexOf( |
|
|
295 |
booking.booking_id |
296 |
) === -1 |
297 |
) { |
298 |
biblio_bookings.push( |
299 |
booking.booking_id |
300 |
); |
245 |
} |
301 |
} |
246 |
} |
302 |
} |
247 |
} |
303 |
} |
248 |
|
304 |
|
249 |
// new booking would span existing booking |
305 |
// new booking would span existing booking |
250 |
else if (selectedDates[0] <= start_date && date >= end_date) { |
306 |
else if ( |
|
|
307 |
selectedDates[0] <= start_date && |
308 |
date >= end_date |
309 |
) { |
251 |
if (booking.item_id) { |
310 |
if (booking.item_id) { |
252 |
if (unavailable_items.indexOf(booking.item_id) === -1) { |
311 |
if ( |
253 |
unavailable_items.push(booking.item_id); |
312 |
unavailable_items.indexOf( |
|
|
313 |
booking.item_id |
314 |
) === -1 |
315 |
) { |
316 |
unavailable_items.push( |
317 |
booking.item_id |
318 |
); |
254 |
} |
319 |
} |
255 |
} else { |
320 |
} else { |
256 |
if (biblio_bookings.indexOf(booking.booking_id) === -1) { |
321 |
if ( |
257 |
biblio_bookings.push(booking.booking_id); |
322 |
biblio_bookings.indexOf( |
|
|
323 |
booking.booking_id |
324 |
) === -1 |
325 |
) { |
326 |
biblio_bookings.push( |
327 |
booking.booking_id |
328 |
); |
258 |
} |
329 |
} |
259 |
} |
330 |
} |
260 |
} |
331 |
} |
Lines 266-272
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
266 |
|
337 |
|
267 |
// check that there are available items |
338 |
// check that there are available items |
268 |
// available = all bookable items - booked items - booked biblios |
339 |
// available = all bookable items - booked items - booked biblios |
269 |
let total_available = bookable_items.length - unavailable_items.length - biblio_bookings.length; |
340 |
let total_available = |
|
|
341 |
bookable_items.length - |
342 |
unavailable_items.length - |
343 |
biblio_bookings.length; |
270 |
if (total_available === 0) { |
344 |
if (total_available === 0) { |
271 |
return true; |
345 |
return true; |
272 |
} |
346 |
} |
Lines 274-282
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
274 |
|
348 |
|
275 |
// patron has not yet selected a start date (start date checks) |
349 |
// patron has not yet selected a start date (start date checks) |
276 |
else if (date <= end_date && date >= start_date) { |
350 |
else if (date <= end_date && date >= start_date) { |
277 |
|
|
|
278 |
// same item, disable date |
351 |
// same item, disable date |
279 |
if (booking.item_id && booking.item_id == booking_item_id) { |
352 |
if ( |
|
|
353 |
booking.item_id && |
354 |
booking.item_id == booking_item_id |
355 |
) { |
280 |
return true; |
356 |
return true; |
281 |
} |
357 |
} |
282 |
|
358 |
|
Lines 290-296
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
290 |
// cases where an item must be used for a biblio level booking |
366 |
// cases where an item must be used for a biblio level booking |
291 |
// due to all other items being booking within the biblio level |
367 |
// due to all other items being booking within the biblio level |
292 |
// booking period... we end up with a clash |
368 |
// booking period... we end up with a clash |
293 |
// To reproduce: |
369 |
// To reproduce: |
294 |
// * One bib with two bookable items. |
370 |
// * One bib with two bookable items. |
295 |
// * Add item level booking |
371 |
// * Add item level booking |
296 |
// * Add biblio level booking that extends one day beyond the item level booking |
372 |
// * Add biblio level booking that extends one day beyond the item level booking |
Lines 300-474
$('#placeBookingModal').on('show.bs.modal', function(e) {
Link Here
|
300 |
} |
376 |
} |
301 |
} |
377 |
} |
302 |
}); |
378 |
}); |
303 |
}; |
379 |
} |
304 |
|
380 |
|
305 |
// Setup listener for item select2 |
381 |
// Setup listener for item select2 |
306 |
$('#booking_item_id').on('select2:select', function(e) { |
382 |
$("#booking_item_id").on("select2:select", function (e) { |
307 |
booking_item_id = e.params.data.id ? e.params.data.id : null; |
383 |
booking_item_id = e.params.data.id |
|
|
384 |
? e.params.data.id |
385 |
: null; |
308 |
|
386 |
|
309 |
// redraw pariodPicker taking selected item into account |
387 |
// redraw pariodPicker taking selected item into account |
310 |
periodPicker.redraw(); |
388 |
periodPicker.redraw(); |
311 |
}); |
389 |
}); |
312 |
|
390 |
|
313 |
// Set onChange for flatpickr |
391 |
// Set onChange for flatpickr |
314 |
let changeExists = periodPicker.config.onChange.filter(f => f.name ==='periodChange'); |
392 |
let changeExists = periodPicker.config.onChange.filter( |
315 |
if(changeExists.length === 0) { |
393 |
f => f.name === "periodChange" |
316 |
periodPicker.config.onChange.push(function periodChange(selectedDates, dateStr, instance) { |
394 |
); |
|
|
395 |
if (changeExists.length === 0) { |
396 |
periodPicker.config.onChange.push(function periodChange( |
397 |
selectedDates, |
398 |
dateStr, |
399 |
instance |
400 |
) { |
317 |
// Range set, update hidden fields and set available items |
401 |
// Range set, update hidden fields and set available items |
318 |
if ( selectedDates[0] && selectedDates[1] ) { |
402 |
if (selectedDates[0] && selectedDates[1]) { |
319 |
// set form fields from picker |
403 |
// set form fields from picker |
320 |
let picker_start = dayjs(selectedDates[0]); |
404 |
let picker_start = dayjs(selectedDates[0]); |
321 |
let picker_end = dayjs(selectedDates[1]).endOf('day'); |
405 |
let picker_end = dayjs(selectedDates[1]).endOf( |
322 |
$('#booking_start_date').val(picker_start.toISOString()); |
406 |
"day" |
323 |
$('#booking_end_date').val(picker_end.toISOString()); |
407 |
); |
|
|
408 |
$("#booking_start_date").val( |
409 |
picker_start.toISOString() |
410 |
); |
411 |
$("#booking_end_date").val( |
412 |
picker_end.toISOString() |
413 |
); |
324 |
|
414 |
|
325 |
// set available items in select2 |
415 |
// set available items in select2 |
326 |
let booked_items = bookings.filter(function(booking) { |
416 |
let booked_items = bookings.filter(function ( |
327 |
let start_date = flatpickr.parseDate(booking.start_date); |
417 |
booking |
328 |
let end_date = flatpickr.parseDate(booking.end_date); |
418 |
) { |
|
|
419 |
let start_date = flatpickr.parseDate( |
420 |
booking.start_date |
421 |
); |
422 |
let end_date = flatpickr.parseDate( |
423 |
booking.end_date |
424 |
); |
329 |
// This booking ends before the start of the new booking |
425 |
// This booking ends before the start of the new booking |
330 |
if ( end_date <= selectedDates[0] ) { |
426 |
if (end_date <= selectedDates[0]) { |
331 |
return false; |
427 |
return false; |
332 |
} |
428 |
} |
333 |
// This booking starts after then end of the new booking |
429 |
// This booking starts after then end of the new booking |
334 |
if ( start_date >= selectedDates[1] ) { |
430 |
if (start_date >= selectedDates[1]) { |
335 |
return false; |
431 |
return false; |
336 |
} |
432 |
} |
337 |
// This booking overlaps |
433 |
// This booking overlaps |
338 |
return true; |
434 |
return true; |
339 |
}); |
435 |
}); |
340 |
$("#booking_item_id > option").each(function() { |
436 |
$("#booking_item_id > option").each(function () { |
341 |
let option = $(this); |
437 |
let option = $(this); |
342 |
if ( booking_item_id && booking_item_id == option.val() ) { |
438 |
if ( |
343 |
option.prop('disabled',false); |
439 |
booking_item_id && |
344 |
} else if ( booked_items.some(function(booked_item){ |
440 |
booking_item_id == option.val() |
345 |
return option.val() == booked_item.item_id; |
441 |
) { |
346 |
}) ) { |
442 |
option.prop("disabled", false); |
347 |
option.prop('disabled',true); |
443 |
} else if ( |
|
|
444 |
booked_items.some(function (booked_item) { |
445 |
return ( |
446 |
option.val() == booked_item.item_id |
447 |
); |
448 |
}) |
449 |
) { |
450 |
option.prop("disabled", true); |
348 |
} else { |
451 |
} else { |
349 |
option.prop('disabled',false); |
452 |
option.prop("disabled", false); |
350 |
} |
453 |
} |
351 |
}); |
454 |
}); |
352 |
$('#booking_item_id').trigger('change.select2'); |
455 |
$("#booking_item_id").trigger("change.select2"); |
353 |
} |
456 |
} |
354 |
// Range not set, reset field options |
457 |
// Range not set, reset field options |
355 |
else { |
458 |
else { |
356 |
$('#booking_item_id > option').each(function() { |
459 |
$("#booking_item_id > option").each(function () { |
357 |
$(this).prop('disabled', false); |
460 |
$(this).prop("disabled", false); |
358 |
}); |
461 |
}); |
359 |
$('#booking_item_id').trigger('change.select2'); |
462 |
$("#booking_item_id").trigger("change.select2"); |
360 |
} |
463 |
} |
361 |
}); |
464 |
}); |
362 |
}; |
465 |
} |
363 |
|
466 |
|
364 |
// Enable flatpickr now we have date function populated |
467 |
// Enable flatpickr now we have date function populated |
365 |
periodPicker.redraw(); |
468 |
periodPicker.redraw(); |
366 |
$("#period_fields :input").prop('disabled', false); |
469 |
$("#period_fields :input").prop("disabled", false); |
367 |
|
470 |
|
368 |
// Redraw select with new options and enable |
471 |
// Redraw select with new options and enable |
369 |
$('#booking_item_id').trigger('change'); |
472 |
$("#booking_item_id").trigger("change"); |
370 |
$("#booking_item_id").prop("disabled", false); |
473 |
$("#booking_item_id").prop("disabled", false); |
371 |
|
474 |
|
372 |
// Set the flag to indicate that data has been fetched |
475 |
// Set the flag to indicate that data has been fetched |
373 |
dataFetched = true; |
476 |
dataFetched = true; |
374 |
|
477 |
|
375 |
// Set form values |
478 |
// Set form values |
376 |
setFormValues(patron_id,booking_item_id,start_date,end_date,periodPicker); |
479 |
setFormValues( |
|
|
480 |
patron_id, |
481 |
booking_item_id, |
482 |
start_date, |
483 |
end_date, |
484 |
periodPicker |
485 |
); |
377 |
}, |
486 |
}, |
378 |
function(jqXHR, textStatus, errorThrown){ |
487 |
function (jqXHR, textStatus, errorThrown) { |
379 |
console.log("Fetch failed"); |
488 |
console.log("Fetch failed"); |
380 |
} |
489 |
} |
381 |
); |
490 |
); |
382 |
} else { |
491 |
} else { |
383 |
setFormValues(patron_id,booking_item_id,start_date,end_date,periodPicker); |
492 |
setFormValues( |
384 |
}; |
493 |
patron_id, |
|
|
494 |
booking_item_id, |
495 |
start_date, |
496 |
end_date, |
497 |
periodPicker |
498 |
); |
499 |
} |
385 |
}); |
500 |
}); |
386 |
|
501 |
|
387 |
function setFormValues(patron_id,booking_item_id,start_date,end_date,periodPicker){ |
502 |
function setFormValues( |
388 |
|
503 |
patron_id, |
|
|
504 |
booking_item_id, |
505 |
start_date, |
506 |
end_date, |
507 |
periodPicker |
508 |
) { |
389 |
// If passed patron, pre-select |
509 |
// If passed patron, pre-select |
390 |
if (patron_id) { |
510 |
if (patron_id) { |
391 |
let patronSelect = $('#booking_patron_id'); |
511 |
let patronSelect = $("#booking_patron_id"); |
392 |
let patron = $.ajax({ |
512 |
let patron = $.ajax({ |
393 |
url: '/api/v1/patrons/' + patron_id, |
513 |
url: "/api/v1/patrons/" + patron_id, |
394 |
dataType: 'json', |
514 |
dataType: "json", |
395 |
type: 'GET' |
515 |
type: "GET", |
396 |
}); |
516 |
}); |
397 |
|
517 |
|
398 |
$.when(patron).done( |
518 |
$.when(patron).done(function (patron) { |
399 |
function(patron){ |
519 |
// clone patron_id to id (select2 expects an id field) |
400 |
|
520 |
patron.id = patron.patron_id; |
401 |
// clone patron_id to id (select2 expects an id field) |
521 |
patron.text = |
402 |
patron.id = patron.patron_id; |
522 |
escape_str(patron.surname) + |
403 |
patron.text = escape_str(patron.surname) + ", " + escape_str(patron.firstname); |
523 |
", " + |
404 |
|
524 |
escape_str(patron.firstname); |
405 |
// Add and select new option |
525 |
|
406 |
let newOption = new Option(patron.text, patron.id, true, true); |
526 |
// Add and select new option |
407 |
patronSelect.append(newOption).trigger('change'); |
527 |
let newOption = new Option(patron.text, patron.id, true, true); |
408 |
|
528 |
patronSelect.append(newOption).trigger("change"); |
409 |
// manually trigger the `select2:select` event |
529 |
|
410 |
patronSelect.trigger({ |
530 |
// manually trigger the `select2:select` event |
411 |
type: 'select2:select', |
531 |
patronSelect.trigger({ |
412 |
params: { |
532 |
type: "select2:select", |
413 |
data: patron |
533 |
params: { |
414 |
} |
534 |
data: patron, |
415 |
}); |
535 |
}, |
416 |
} |
536 |
}); |
417 |
); |
537 |
}); |
418 |
} |
538 |
} |
419 |
|
539 |
|
420 |
// Set booking start & end if this is an edit |
540 |
// Set booking start & end if this is an edit |
421 |
if ( start_date ) { |
541 |
if (start_date) { |
422 |
// Allow invalid pre-load so setDate can set date range |
542 |
// Allow invalid pre-load so setDate can set date range |
423 |
// periodPicker.set('allowInvalidPreload', true); |
543 |
// periodPicker.set('allowInvalidPreload', true); |
424 |
// FIXME: Why is this the case.. we're passing two valid Date objects |
544 |
// FIXME: Why is this the case.. we're passing two valid Date objects |
425 |
let start = new Date(start_date); |
545 |
let start = new Date(start_date); |
426 |
let end = new Date(end_date); |
546 |
let end = new Date(end_date); |
427 |
|
547 |
|
428 |
let dates = [ new Date(start_date), new Date(end_date) ]; |
548 |
let dates = [new Date(start_date), new Date(end_date)]; |
429 |
periodPicker.setDate(dates, true); |
549 |
periodPicker.setDate(dates, true); |
430 |
} |
550 |
} |
431 |
// Reset periodPicker, biblio_id may have been nulled |
551 |
// Reset periodPicker, biblio_id may have been nulled |
432 |
else { |
552 |
else { |
433 |
periodPicker.redraw(); |
553 |
periodPicker.redraw(); |
434 |
}; |
554 |
} |
435 |
|
555 |
|
436 |
// If passed an itemnumber, pre-select |
556 |
// If passed an itemnumber, pre-select |
437 |
if (booking_item_id) { |
557 |
if (booking_item_id) { |
438 |
$('#booking_item_id').val(booking_item_id).trigger('change'); |
558 |
$("#booking_item_id").val(booking_item_id).trigger("change"); |
439 |
} |
559 |
} |
440 |
} |
560 |
} |
441 |
|
561 |
|
442 |
$("#placeBookingForm").on('submit', function(e) { |
562 |
$("#placeBookingForm").on("submit", function (e) { |
443 |
e.preventDefault(); |
563 |
e.preventDefault(); |
444 |
|
564 |
|
445 |
let url = '/api/v1/bookings'; |
565 |
let url = "/api/v1/bookings"; |
446 |
|
566 |
|
447 |
let start_date = $('#booking_start_date').val(); |
567 |
let start_date = $("#booking_start_date").val(); |
448 |
let end_date = $('#booking_end_date').val(); |
568 |
let end_date = $("#booking_end_date").val(); |
449 |
let item_id = $('#booking_item_id').val(); |
569 |
let item_id = $("#booking_item_id").val(); |
450 |
|
570 |
|
451 |
if (!booking_id) { |
571 |
if (!booking_id) { |
452 |
let posting = $.post( |
572 |
let posting = $.post( |
453 |
url, |
573 |
url, |
454 |
JSON.stringify({ |
574 |
JSON.stringify({ |
455 |
"start_date": start_date, |
575 |
start_date: start_date, |
456 |
"end_date": end_date, |
576 |
end_date: end_date, |
457 |
"biblio_id": $('#booking_biblio_id').val(), |
577 |
biblio_id: $("#booking_biblio_id").val(), |
458 |
"item_id": item_id != 0 ? item_id : null, |
578 |
item_id: item_id != 0 ? item_id : null, |
459 |
"patron_id": $('#booking_patron_id').find(':selected').val() |
579 |
patron_id: $("#booking_patron_id").find(":selected").val(), |
460 |
}) |
580 |
}) |
461 |
); |
581 |
); |
462 |
|
582 |
|
463 |
posting.done(function(data) { |
583 |
posting.done(function (data) { |
464 |
// Update bookings store for subsequent bookings |
584 |
// Update bookings store for subsequent bookings |
465 |
bookings.push(data); |
585 |
bookings.push(data); |
466 |
|
586 |
|
467 |
// Update bookings page as required |
587 |
// Update bookings page as required |
468 |
if (typeof bookings_table !== 'undefined' && bookings_table !== null) { |
588 |
if ( |
|
|
589 |
typeof bookings_table !== "undefined" && |
590 |
bookings_table !== null |
591 |
) { |
469 |
bookings_table.api().ajax.reload(); |
592 |
bookings_table.api().ajax.reload(); |
470 |
} |
593 |
} |
471 |
if (typeof timeline !== 'undefined' && timeline !== null) { |
594 |
if (typeof timeline !== "undefined" && timeline !== null) { |
472 |
timeline.itemsData.add({ |
595 |
timeline.itemsData.add({ |
473 |
id: data.booking_id, |
596 |
id: data.booking_id, |
474 |
booking: data.booking_id, |
597 |
booking: data.booking_id, |
Lines 477-528
$("#placeBookingForm").on('submit', function(e) {
Link Here
|
477 |
end: dayjs(data.end_date).toDate(), |
600 |
end: dayjs(data.end_date).toDate(), |
478 |
content: $patron_to_html(booking_patron, { |
601 |
content: $patron_to_html(booking_patron, { |
479 |
display_cardnumber: true, |
602 |
display_cardnumber: true, |
480 |
url: false |
603 |
url: false, |
481 |
}), |
604 |
}), |
482 |
editable: { remove: true, updateTime: true }, |
605 |
editable: { remove: true, updateTime: true }, |
483 |
type: 'range', |
606 |
type: "range", |
484 |
group: data.item_id ? data.item_id : 0 |
607 |
group: data.item_id ? data.item_id : 0, |
485 |
}); |
608 |
}); |
486 |
timeline.focus(data.booking_id); |
609 |
timeline.focus(data.booking_id); |
487 |
} |
610 |
} |
488 |
|
611 |
|
489 |
// Update bookings counts |
612 |
// Update bookings counts |
490 |
$('.bookings_count').html(parseInt($('.bookings_count').html(), 10)+1); |
613 |
$(".bookings_count").html( |
|
|
614 |
parseInt($(".bookings_count").html(), 10) + 1 |
615 |
); |
491 |
|
616 |
|
492 |
// Close modal |
617 |
// Close modal |
493 |
$('#placeBookingModal').modal('hide'); |
618 |
$("#placeBookingModal").modal("hide"); |
494 |
}); |
619 |
}); |
495 |
|
620 |
|
496 |
posting.fail(function(data) { |
621 |
posting.fail(function (data) { |
497 |
$('#booking_result').replaceWith('<div id="booking_result" class="alert alert-danger">'+_("Failure")+'</div>'); |
622 |
$("#booking_result").replaceWith( |
|
|
623 |
'<div id="booking_result" class="alert alert-danger">' + |
624 |
_("Failure") + |
625 |
"</div>" |
626 |
); |
498 |
}); |
627 |
}); |
499 |
} else { |
628 |
} else { |
500 |
url += '/' + booking_id; |
629 |
url += "/" + booking_id; |
501 |
let putting = $.ajax({ |
630 |
let putting = $.ajax({ |
502 |
'method': 'PUT', |
631 |
method: "PUT", |
503 |
'url': url, |
632 |
url: url, |
504 |
'data': JSON.stringify({ |
633 |
data: JSON.stringify({ |
505 |
"booking_id": booking_id, |
634 |
booking_id: booking_id, |
506 |
"start_date": start_date, |
635 |
start_date: start_date, |
507 |
"end_date": end_date, |
636 |
end_date: end_date, |
508 |
"biblio_id": $('#booking_biblio_id').val(), |
637 |
biblio_id: $("#booking_biblio_id").val(), |
509 |
"item_id": item_id != 0 ? item_id : null, |
638 |
item_id: item_id != 0 ? item_id : null, |
510 |
"patron_id": $('#booking_patron_id').find(':selected').val() |
639 |
patron_id: $("#booking_patron_id").find(":selected").val(), |
511 |
}) |
640 |
}), |
512 |
}); |
641 |
}); |
513 |
|
642 |
|
514 |
putting.done(function(data) { |
643 |
putting.done(function (data) { |
515 |
update_success = 1; |
644 |
update_success = 1; |
516 |
|
645 |
|
517 |
// Update bookings store for subsequent bookings |
646 |
// Update bookings store for subsequent bookings |
518 |
let target = bookings.find((obj) => obj.booking_id === data.booking_id); |
647 |
let target = bookings.find( |
519 |
Object.assign(target,data); |
648 |
obj => obj.booking_id === data.booking_id |
|
|
649 |
); |
650 |
Object.assign(target, data); |
520 |
|
651 |
|
521 |
// Update bookings page as required |
652 |
// Update bookings page as required |
522 |
if (typeof bookings_table !== 'undefined' && bookings_table !== null) { |
653 |
if ( |
|
|
654 |
typeof bookings_table !== "undefined" && |
655 |
bookings_table !== null |
656 |
) { |
523 |
bookings_table.api().ajax.reload(); |
657 |
bookings_table.api().ajax.reload(); |
524 |
} |
658 |
} |
525 |
if (typeof timeline !== 'undefined' && timeline !== null) { |
659 |
if (typeof timeline !== "undefined" && timeline !== null) { |
526 |
timeline.itemsData.update({ |
660 |
timeline.itemsData.update({ |
527 |
id: data.booking_id, |
661 |
id: data.booking_id, |
528 |
booking: data.booking_id, |
662 |
booking: data.booking_id, |
Lines 531-561
$("#placeBookingForm").on('submit', function(e) {
Link Here
|
531 |
end: dayjs(data.end_date).toDate(), |
665 |
end: dayjs(data.end_date).toDate(), |
532 |
content: $patron_to_html(booking_patron, { |
666 |
content: $patron_to_html(booking_patron, { |
533 |
display_cardnumber: true, |
667 |
display_cardnumber: true, |
534 |
url: false |
668 |
url: false, |
535 |
}), |
669 |
}), |
536 |
editable: { remove: true, updateTime: true }, |
670 |
editable: { remove: true, updateTime: true }, |
537 |
type: 'range', |
671 |
type: "range", |
538 |
group: data.item_id ? data.item_id : 0 |
672 |
group: data.item_id ? data.item_id : 0, |
539 |
}); |
673 |
}); |
540 |
timeline.focus(data.booking_id); |
674 |
timeline.focus(data.booking_id); |
541 |
} |
675 |
} |
542 |
|
676 |
|
543 |
// Close modal |
677 |
// Close modal |
544 |
$('#placeBookingModal').modal('hide'); |
678 |
$("#placeBookingModal").modal("hide"); |
545 |
}); |
679 |
}); |
546 |
|
680 |
|
547 |
putting.fail(function(data) { |
681 |
putting.fail(function (data) { |
548 |
$('#booking_result').replaceWith('<div id="booking_result" class="alert alert-danger">'+__("Failure")+'</div>'); |
682 |
$("#booking_result").replaceWith( |
|
|
683 |
'<div id="booking_result" class="alert alert-danger">' + |
684 |
__("Failure") + |
685 |
"</div>" |
686 |
); |
549 |
}); |
687 |
}); |
550 |
} |
688 |
} |
551 |
}); |
689 |
}); |
552 |
|
690 |
|
553 |
$('#placeBookingModal').on('hidden.bs.modal', function (e) { |
691 |
$("#placeBookingModal").on("hidden.bs.modal", function (e) { |
554 |
$('#booking_patron_id').val(null).trigger('change'); |
692 |
$("#booking_patron_id").val(null).trigger("change"); |
555 |
$('#booking_patron_id').empty(); |
693 |
$("#booking_patron_id").empty(); |
556 |
$('#booking_item_id').val(0).trigger('change'); |
694 |
$("#booking_item_id").val(0).trigger("change"); |
557 |
$('#period').get(0)._flatpickr.clear(); |
695 |
$("#period").get(0)._flatpickr.clear(); |
558 |
$('#booking_start_date').val(''); |
696 |
$("#booking_start_date").val(""); |
559 |
$('#booking_end_date').val(''); |
697 |
$("#booking_end_date").val(""); |
560 |
$('#booking_id').val(''); |
698 |
$("#booking_id").val(""); |
561 |
}); |
699 |
}); |
562 |
- |
|
|