Bug 29002: Use vis-timeline in bookings view

This patch uses vis-timeline to display a timeline of bookings on the
booking details display tab.

Test plan
1) Follow the steps from the previous patch test plans
2) Note the new visual timeline view of bookings on the bookings detail
   page.
3) Confirm that clicking the red cross next to a booking triggers the
   cancellation modal
4) Sign off

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Janet McGowan <janet.mcgowan@ptfs-europe.com>
Signed-off-by: Caroline Cyr La Rose <caroline.cyr-la-rose@inlibro.com>
Signed-off-by: Laurence Rault <laurence.rault@biblibre.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Martin Renvoize 2023-05-15 16:56:24 +01:00 committed by Tomas Cohen Arazi
parent 8741d07844
commit 662c4d6ba2
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
3 changed files with 104 additions and 0 deletions

View file

@ -38,6 +38,7 @@
<div class="row">
[% INCLUDE 'cat-toolbar.inc' %]
<h1>Bookings for [% INCLUDE 'biblio-title-head.inc' %]</h1>
<div class="page-section" id="bookings-timeline"></div>
<div class="page-section">
<table id="bookings_table"></table>
</div>
@ -56,6 +57,7 @@
[% MACRO jsinclude BLOCK %]
[% Asset.js("lib/dayjs/dayjs.min.js") | $raw %]
[% Asset.js("lib/vis-timeline/vis-timeline-graph2d.min.js") | $raw %]
[% INCLUDE 'datatables.inc' %]
[% INCLUDE 'columns_settings.inc' %]
[% INCLUDE 'calendar.inc' %]
@ -64,8 +66,93 @@
[% Asset.js("js/place_booking_modal.js") | $raw %]
[% Asset.js("js/cancel_booking_modal.js") | $raw %]
<script>
var cancel_success = 0;
var bookings_table;
var timeline;
$(document).ready(function(){
var items = $.ajax({
url: '/api/v1/biblios/[% biblionumber | uri %]/items?bookable=1',
dataType: 'json',
type: 'GET'
});
var bookings = $.ajax({
url: '/api/v1/biblios/[% biblionumber | uri %]/bookings',
dataType: 'json',
type: 'GET',
});
$.when(items, bookings).then(
function(items, bookings){
var itemsSet = new vis.DataSet([{
id: 0,
content: "Biblio level"
}]);
for (item of items[0]) {
itemsSet.add({
id: item.item_id,
content: "Item " + item.external_id,
});
}
var bookingsSet = new vis.DataSet();
for (booking of bookings[0]){
bookingsSet.add({
id: booking.booking_id,
booking: booking.booking_id,
start: dayjs(booking.start_date).toDate(),
end: dayjs(booking.end_date).toDate(),
content: 'Booking: ' + booking.booking_id,
editable: true,
type: 'range',
group: booking.item_id ? booking.item_id : 0
});
}
var container = document.getElementById('bookings-timeline');
var options = {
stack: true,
verticalScroll: true,
orientation: {
axis: "both",
item: "top"
},
timeAxis: {scale: 'day', step: 1},
dataAttributes: [ 'booking' ],
onMoving: function (item, callback) {
var overlapping = bookingsSet.get({
filter: function(testItem) {
if (testItem.id == item.id) {
return false;
}
if (testItem.group != item.group) {
return false;
}
return ((item.start <= testItem.end) && (item.end >= testItem.start));
}
});
if (overlapping.length == 0) {
callback(item);
}
},
onRemove: function (item, callback) {
$('#cancelBookingModal').modal('show', $('<button data-booking="'+item.id+'">'));
$('#cancelBookingModal').on('hide.bs.modal', function(e) {
if (cancel_success) {
cancel_success = 0;
callback(item);
}
});
}
};
timeline = new vis.Timeline(container, bookingsSet, itemsSet, options);
},
function(jqXHR, textStatus, errorThrown){
console.log("Fetch failed");
}
);
var bookings_table_url = "/api/v1/biblios/[% biblionumber | uri %]/bookings";
bookings_table = $('#bookings_table').kohaTable({
"ajax": {

View file

@ -16,9 +16,13 @@ $("#cancelBookingForm").on('submit', function(e) {
});
deleting.done(function(data) {
cancel_success = 1;
if (bookings_table) {
bookings_table.api().ajax.reload();
}
if (timeline) {
timeline.itemsData.remove(Number(booking_id));
}
$('#cancelBookingModal').modal('hide');
});

View file

@ -312,6 +312,19 @@ $("#placeBookingForm").on('submit', function(e) {
if (typeof bookings_table !== 'undefined' && bookings_table !== null) {
bookings_table.api().ajax.reload();
}
if (typeof timeline !== 'undefined' && timeline !== null) {
timeline.itemsData.add({
id: data.booking_id,
booking: data.booking_id,
patron: data.patron_id,
start: dayjs(data.start_date).toDate(),
end: dayjs(data.end_date).toDate(),
content: 'Booking: ' + data.booking_id,
editable: { remove: true, updateTime: true },
type: 'range',
group: data.item_id ? data.item_id : 0
});
}
// Close modal
$('#placeBookingModal').modal('hide');