|
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> |