Martin Renvoize
771fedcaa8
Update the table display to include patron cardnumber to match that of the display in the timeline view above. 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>
276 lines
10 KiB
Text
276 lines
10 KiB
Text
[% USE raw %]
|
|
[% USE Asset %]
|
|
[% USE KohaDates %]
|
|
[% SET footerjs = 1 %]
|
|
[% INCLUDE 'doc-head-open.inc' %]
|
|
<title>Bookings for [% INCLUDE 'biblio-title-head.inc' %] › Bookings › Circulation › Koha</title>
|
|
[% INCLUDE 'doc-head-close.inc' %]
|
|
</head>
|
|
|
|
<body id="circ_request" class="catalog">
|
|
|
|
[% WRAPPER 'header.inc' %]
|
|
[% INCLUDE 'cat-search.inc' %]
|
|
[% END %]
|
|
|
|
[% WRAPPER 'sub-header.inc' %]
|
|
[% WRAPPER breadcrumbs %]
|
|
[% WRAPPER breadcrumb_item %]
|
|
<a href="/cgi-bin/koha/catalogue/search.pl">Catalog</a>
|
|
[% END %]
|
|
[% WRAPPER breadcrumb_item %]
|
|
[% INCLUDE 'biblio-title.inc' link = 1 %]
|
|
[% END %]
|
|
[% WRAPPER breadcrumb_item bc_active= 1 %]
|
|
<span>Bookings</span>
|
|
[% END %]
|
|
[% END #/ WRAPPER breadcrumbs %]
|
|
[% END #/ WRAPPER sub-header.inc %]
|
|
|
|
<div class="main container-fluid">
|
|
<div class="row">
|
|
<div class="col-sm-10 col-sm-push-2">
|
|
<main>
|
|
<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>
|
|
</div>
|
|
</main>
|
|
</div> <!-- /.col-sm-10.col-sm-push-2 -->
|
|
|
|
<div class="col-sm-2 col-sm-pull-10">
|
|
<aside>
|
|
[% INCLUDE 'biblio-view-menu.inc' %]
|
|
</aside>
|
|
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
|
|
</div> <!-- /.row -->
|
|
|
|
[% INCLUDE modals/cancel_booking.inc %]
|
|
|
|
[% 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' %]
|
|
[% INCLUDE 'select2.inc' %]
|
|
[% INCLUDE 'js-patron-format.inc' %]
|
|
[% INCLUDE 'js-date-format.inc' %]
|
|
[% Asset.js("js/place_booking_modal.js") | $raw %]
|
|
[% Asset.js("js/cancel_booking_modal.js") | $raw %]
|
|
<script>
|
|
var cancel_success = 0;
|
|
var update_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',
|
|
headers: { 'x-koha-embed': 'patron' },
|
|
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,
|
|
patron: booking.patron_id,
|
|
start: dayjs(booking.start_date).toDate(),
|
|
end: dayjs(booking.end_date).toDate(),
|
|
content: $patron_to_html(booking.patron, {
|
|
display_cardnumber: true,
|
|
url: false
|
|
}),
|
|
editable: { remove: true, updateTime: 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' ],
|
|
|
|
// always snap to full days, independent of the scale
|
|
snap: function (date, scale, step) {
|
|
let offset = date.getTimezoneOffset() * 60 * 1000;
|
|
let day = 24 * 60 * 60 * 1000;
|
|
let seconds = Math.round(date / day) * day;
|
|
return seconds + offset;
|
|
},
|
|
|
|
// prevent overlapping bookings
|
|
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);
|
|
}
|
|
},
|
|
|
|
// action events
|
|
onMove: function (item, callback) {
|
|
|
|
let startDate = new Date(item.start);
|
|
|
|
// set end datetime hours and minutes to the end of the day
|
|
let endDate = new Date(item.end);
|
|
endDate.setHours(endDate.getHours()+23);
|
|
endDate.setMinutes(endDate.getMinutes()+59);
|
|
|
|
let url = '/api/v1/bookings/'+item.booking;
|
|
var putting = $.ajax({
|
|
method: 'PUT',
|
|
url: url,
|
|
data: JSON.stringify({
|
|
"booking_id": item.booking,
|
|
"start_date": startDate.toISOString(),
|
|
"end_date": endDate.toISOString(),
|
|
"biblio_id": [% biblionumber | uri %],
|
|
"item_id": item.group != 0 ? item.group : null,
|
|
"patron_id": item.patron
|
|
})
|
|
});
|
|
|
|
putting.done(function(data) {
|
|
bookings_table.api().ajax.reload();
|
|
callback(item);
|
|
});
|
|
|
|
putting.fail(function(data) {
|
|
$('#booking_result').replaceWith('<div id="booking_result" class="alert alert-danger">Failure</div>');
|
|
});
|
|
},
|
|
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": {
|
|
"url": bookings_table_url
|
|
},
|
|
"embed": [
|
|
"item",
|
|
"patron"
|
|
],
|
|
"columns": [{
|
|
"data": "booking_id",
|
|
"title": "Booking ID",
|
|
"visible": false
|
|
},
|
|
{
|
|
"data": "item.external_id",
|
|
"title": "Item",
|
|
"searchable": true,
|
|
"orderable": true,
|
|
"defaultContent": "Any item",
|
|
"render": function(data,type,row,meta) {
|
|
if ( row.item ) {
|
|
return row.item.external_id;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"data": "patron.firstname:patron.surname",
|
|
"title": "Patron",
|
|
"searchable": true,
|
|
"orderable": true,
|
|
"render": function(data, type, row, meta) {
|
|
return $patron_to_html(row.patron, {
|
|
display_cardnumber: true,
|
|
url: true
|
|
});
|
|
}
|
|
},
|
|
{
|
|
"data": "start_date",
|
|
"title": "Start date",
|
|
"searchable": true,
|
|
"orderable": true,
|
|
"render": function(data, type, row, meta) {
|
|
return $date(row.start_date);
|
|
}
|
|
},
|
|
{
|
|
"data": "end_date",
|
|
"title": "End date",
|
|
"searchable": true,
|
|
"orderable": true,
|
|
"render": function(data, type, row, meta) {
|
|
return $date(row.end_date);
|
|
}
|
|
},
|
|
{
|
|
"data": "",
|
|
"title": "Actions",
|
|
"searchable": false,
|
|
"orderable": false,
|
|
"render": function(data, type, row, meta) {
|
|
var result = '<button type="button" class="btn btn-default btn-xs cancel-action" data-toggle="modal" data-target="#cancelBookingModal" data-booking="'+row.booking_id+'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Cancel")+'</button>';
|
|
return result;
|
|
}
|
|
}]
|
|
}, [], 0);
|
|
});
|
|
</script>
|
|
[% END %]
|
|
|
|
[% INCLUDE 'intranet-bottom.inc' %]
|