Lines 50-58
Link Here
|
50 |
<h1>Bookings for [% INCLUDE 'biblio-title-head.inc' %]</h1> |
50 |
<h1>Bookings for [% INCLUDE 'biblio-title-head.inc' %]</h1> |
51 |
<div class="page-section" id="bookings-timeline"></div> |
51 |
<div class="page-section" id="bookings-timeline"></div> |
52 |
<div class="page-section"> |
52 |
<div class="page-section"> |
53 |
<fieldset class="action filters" style="cursor:pointer; display: flex; flex-direction: column;"> |
53 |
<fieldset class="action filters d-flex gap-2" style="cursor: pointer;"> |
54 |
<a id="expired_filter" class="filtered"><i class="fa fa-bars"></i> Show expired</a> |
54 |
<a id="expired_filter" data-filter="expired"><i class="fa fa-bars"></i> Show expired</a> |
55 |
<a id="cancelled_filter" class="filtered"><i class="fa fa-bars"></i> Show cancelled</a> |
55 |
<a id="cancelled_filter" data-filter="cancelled"><i class="fa fa-bars"></i> Show cancelled</a> |
56 |
</fieldset> |
56 |
</fieldset> |
57 |
|
57 |
|
58 |
<table id="bookings_table"></table> |
58 |
<table id="bookings_table"></table> |
Lines 118-123
Link Here
|
118 |
|
118 |
|
119 |
var bookingsSet = new vis.DataSet(); |
119 |
var bookingsSet = new vis.DataSet(); |
120 |
for (booking of bookings[0]){ |
120 |
for (booking of bookings[0]){ |
|
|
121 |
const isActive = ["new", "pending", "active"].includes(booking.status); |
122 |
const patronContent = $patron_to_html(booking.patron, { |
123 |
display_cardnumber: true, |
124 |
url: false |
125 |
}); |
121 |
bookingsSet.add({ |
126 |
bookingsSet.add({ |
122 |
id: booking.booking_id, |
127 |
id: booking.booking_id, |
123 |
booking: booking.booking_id, |
128 |
booking: booking.booking_id, |
Lines 125-142
Link Here
|
125 |
pickup_library: booking.pickup_library_id, |
130 |
pickup_library: booking.pickup_library_id, |
126 |
start: dayjs(booking.start_date).toDate(), |
131 |
start: dayjs(booking.start_date).toDate(), |
127 |
end: dayjs(booking.end_date).toDate(), |
132 |
end: dayjs(booking.end_date).toDate(), |
128 |
content: $patron_to_html(booking.patron, { |
133 |
content: !isActive ? `<s>${patronContent}</s>` : patronContent, |
129 |
display_cardnumber: true, |
|
|
130 |
url: false |
131 |
}), |
132 |
[% IF CAN_user_circulate_manage_bookings %] |
134 |
[% IF CAN_user_circulate_manage_bookings %] |
133 |
editable: booking.status != 'cancelled' ? { remove: true, updateTime: true } : false, |
135 |
editable: booking.status !== "cancelled" ? { remove: true, updateTime: true } : false, |
134 |
[% ELSE %] |
136 |
[% ELSE %] |
135 |
editable: false, |
137 |
editable: false, |
136 |
[% END %] |
138 |
[% END %] |
137 |
type: 'range', |
139 |
type: 'range', |
138 |
group: booking.item_id ? booking.item_id : 0, |
140 |
group: booking.item_id ?? 0, |
139 |
className: booking.status, |
|
|
140 |
}); |
141 |
}); |
141 |
} |
142 |
} |
142 |
|
143 |
|
Lines 225-248
Link Here
|
225 |
} |
226 |
} |
226 |
); |
227 |
); |
227 |
|
228 |
|
228 |
let filter_expired = true; |
229 |
const filterStates = { expired: true, cancelled: false }; |
229 |
let filter_cancelled = false; |
230 |
const additional_filters = { |
230 |
let additional_filters = { |
231 |
end_date: () => { |
231 |
end_date: function(){ |
232 |
if (filterStates.expired) { |
232 |
if ( filter_expired ) { |
|
|
233 |
let today = new Date(); |
233 |
let today = new Date(); |
234 |
return { ">=": today.toISOString() } |
234 |
return { ">=": today.toISOString() }; |
235 |
} else { |
|
|
236 |
return; |
237 |
} |
235 |
} |
238 |
}, |
236 |
}, |
239 |
status: function(){ |
237 |
status: () => { |
240 |
if ( filter_cancelled ) { |
238 |
const defaults = ["new", "pending", "active"]; |
241 |
return { "=": 'cancelled' } |
239 |
if (filterStates.cancelled) { |
242 |
} else { |
240 |
const filtered = [...defaults, "cancelled"]; |
243 |
return; |
241 |
return { "-in": filtered }; |
244 |
} |
242 |
} |
245 |
} |
243 |
|
|
|
244 |
return { "-in": defaults }; |
245 |
}, |
246 |
}; |
246 |
}; |
247 |
|
247 |
|
248 |
var bookings_table_url = "/api/v1/biblios/[% biblionumber | uri %]/bookings"; |
248 |
var bookings_table_url = "/api/v1/biblios/[% biblionumber | uri %]/bookings"; |
Lines 268-282
Link Here
|
268 |
orderable: false, |
268 |
orderable: false, |
269 |
visible: false, |
269 |
visible: false, |
270 |
render: function (data, type, row, meta) { |
270 |
render: function (data, type, row, meta) { |
271 |
let is_expired = dayjs(row.end_date).isBefore(new Date()); |
271 |
const is_expired = dayjs(row.end_date).isBefore(new Date()); |
272 |
let is_cancelled = row.status == 'cancelled' ? 1 : 0; |
|
|
273 |
if (is_expired) { |
272 |
if (is_expired) { |
274 |
return '<span class="badge rounded-pill bg-secondary">' + _("Expired") + '</span>'; |
273 |
return `<span class="badge rounded-pill bg-secondary"> |
|
|
274 |
${_("Expired")} |
275 |
</span>`; |
275 |
} |
276 |
} |
|
|
277 |
|
278 |
const is_cancelled = row.status === "cancelled"; |
276 |
if (is_cancelled) { |
279 |
if (is_cancelled) { |
277 |
return '<span class="badge rounded-pill bg-secondary">' + _("Cancelled") + '</span>'; |
280 |
return `<span class="badge rounded-pill bg-secondary"> |
|
|
281 |
${_("Cancelled")} |
282 |
</span>`; |
278 |
} |
283 |
} |
279 |
return '<span class="badge rounded-pill bg-success">' + _("Active") + '</span>'; |
284 |
|
|
|
285 |
return `<span class="badge rounded-pill bg-success"> |
286 |
${_("New")} |
287 |
</span>`; |
280 |
} |
288 |
} |
281 |
}, |
289 |
}, |
282 |
{ |
290 |
{ |
Lines 340-348
Link Here
|
340 |
"orderable": false, |
348 |
"orderable": false, |
341 |
"render": function(data, type, row, meta) { |
349 |
"render": function(data, type, row, meta) { |
342 |
let result = ""; |
350 |
let result = ""; |
343 |
let is_cancelled = row.status == 'cancelled' ? 1 : 0; |
351 |
let is_cancelled = row.status === "cancelled"; |
344 |
[% IF CAN_user_circulate_manage_bookings %] |
352 |
[% IF CAN_user_circulate_manage_bookings %] |
345 |
if( !is_cancelled ){ |
353 |
if (!is_cancelled) { |
346 |
result += '<button type="button" class="btn btn-default btn-xs edit-action" data-bs-toggle="modal" data-bs-target="#placeBookingModal" data-booking="'+row.booking_id+'" data-biblionumber="[% biblionumber | uri %]" data-itemnumber="'+row.item_id+'" data-patron="'+row.patron_id+'" data-pickup_library="'+row.pickup_library_id+'" data-start_date="'+row.start_date+'" data-end_date="'+row.end_date+'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</button>'; |
354 |
result += '<button type="button" class="btn btn-default btn-xs edit-action" data-bs-toggle="modal" data-bs-target="#placeBookingModal" data-booking="'+row.booking_id+'" data-biblionumber="[% biblionumber | uri %]" data-itemnumber="'+row.item_id+'" data-patron="'+row.patron_id+'" data-pickup_library="'+row.pickup_library_id+'" data-start_date="'+row.start_date+'" data-end_date="'+row.end_date+'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</button>'; |
347 |
result += '<button type="button" class="btn btn-default btn-xs cancel-action" data-bs-toggle="modal" data-bs-target="#cancelBookingModal" data-booking="'+row.booking_id+'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Cancel")+'</button>'; |
355 |
result += '<button type="button" class="btn btn-default btn-xs cancel-action" data-bs-toggle="modal" data-bs-target="#cancelBookingModal" data-booking="'+row.booking_id+'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Cancel")+'</button>'; |
348 |
} |
356 |
} |
Lines 352-376
Link Here
|
352 |
}] |
360 |
}] |
353 |
}, [], 0, additional_filters); |
361 |
}, [], 0, additional_filters); |
354 |
|
362 |
|
355 |
function setupFilter(filterId, activeText, inactiveText, filterVariable) { |
363 |
document |
356 |
$(filterId).on("click", function() { |
364 |
.getElementById("expired_filter") |
357 |
if ($(this).hasClass('filtered')) { |
365 |
.addEventListener("click", (e) => |
358 |
filterVariable = false; |
366 |
handleFilter( |
359 |
$(this).html('<i class="fa fa-filter"></i> ' + inactiveText); |
367 |
e, |
360 |
} else { |
368 |
{ active: _("Hide expired"), inactive: _("Show expired") }, |
361 |
filterVariable = true; |
369 |
filterStates, |
362 |
$(this).html('<i class="fa fa-bars"></i> ' + activeText); |
370 |
), |
363 |
} |
371 |
); |
364 |
|
372 |
|
365 |
bookings_table.DataTable().ajax.reload(() => { |
373 |
document |
366 |
bookings_table.DataTable().column("status:name").visible(!filterVariable, false); |
374 |
.getElementById("cancelled_filter") |
367 |
}); |
375 |
.addEventListener("click", (e) => |
368 |
$(this).toggleClass('filtered'); |
376 |
handleFilter( |
|
|
377 |
e, |
378 |
{ active: _("Hide cancelled"), inactive: _("Show cancelled") }, |
379 |
filterStates, |
380 |
), |
381 |
); |
382 |
|
383 |
function handleFilter(e, text, filterStates) { |
384 |
const target = e.target; |
385 |
const { filter } = target.dataset; |
386 |
if (target.classList.contains("filtered")) { |
387 |
filterStates[filter] = false; |
388 |
target.innerHTML = `<i class="fa fa-bars"></i> ${text.inactive}`; |
389 |
} else { |
390 |
filterStates[filter] = true; |
391 |
target.innerHTML = `<i class="fa fa-filter"></i> ${text.active}`; |
392 |
} |
393 |
|
394 |
bookings_table.DataTable().ajax.reload(() => { |
395 |
bookings_table |
396 |
.DataTable() |
397 |
.column("status:name") |
398 |
.visible(filterStates[filter], false); |
369 |
}); |
399 |
}); |
370 |
} |
|
|
371 |
|
400 |
|
372 |
setupFilter("#expired_filter", _("Show expired"), _("Hide expired"), filter_expired); |
401 |
target.classList.toggle("filtered"); |
373 |
setupFilter("#cancelled_filter", _("Show cancelled"), _("Hide cancelled"), filter_cancelled); |
402 |
} |
374 |
|
403 |
|
375 |
}); |
404 |
}); |
376 |
</script> |
405 |
</script> |