View | Details | Raw Unified | Return to bug 36374
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/prog/js/place_booking_modal.js (-198 / +335 lines)
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
- 

Return to bug 36374