From fe4720d8ab1bb5dd4e063bea32082052277f7b52 Mon Sep 17 00:00:00 2001 From: Owen Leonard Date: Tue, 31 Aug 2021 19:23:21 +0000 Subject: [PATCH] Bug 28937: Use Flatpickr on circulation and patron pages This patch replaces the use of jQueryUI's datepicker on circulation and patron-related pages. The patch modifies Flatpickr's default configuration (in calendar.inc) so that it has the following features: - A Flatpickr input with a "futuredate" class will require that the selected date be after today. - The Flatpickr input field will be wrapped in a container to facilitate better CSS styling. - Generic handling of paired date fields is enabled using ".flatpickrfrom" and ".flatpickrto" field classes. This mimics the same feature we have for jQueryUI datepickers using ".datepickerfrom" and ".datepickerto". This patch also removes an unused function which was repeated in three templates: validate1. To test, apply the patch and rebuild the staff interface CSS (https://wiki.koha-community.org/wiki/Working_with_SCSS_in_the_OPAC_and_staff_client). - Go to Circulation and check out to a patron. - Open the Restrictions tab and click "Add manual restriction." - In the "Expiration" field, test that the Flatpickr widget works correctly and limits to dates after today. - Enable the SpecifyDueDate preference if necessary. - Test the behavior of the SpecifyDueDate controls: Setting a date, clearing a date, session persistence. - Enable the SuspendHoldsIntranet system preference if necessary. - Check out to a patron with existing holds. - Open the Holds tab and click the "Suspend" button for one of the holds. - In the modal window which appears, check that the Flatpickr widget works correctly and limits to dates after today. - At the bottom of the table of holds, test that the "Suspend all holds" Flatpickr works correctly and limits to dates after today. - Perform this same test from the patron details page. - Enable the BatchCheckouts system preference if necessary. - Open a patron record and click "Batch check out" in the left-hand sidebar menu. - Test that the "Hard due date" Flatpickr works correctly as a date and time picker. - Go to Circulation -> Overdues. - Test that the date due filters in the sidebar work correctly and are linked, e.g. the "to" field cannot be before the "from" field. - Perform the same test here: Circulation -> Holds to pull; and here: Circulation -> Hold ratios. - Enable the HouseboundModule system preference if necessary. - Check out to or view details of a patron. - Click "Housebound" in the sidebar menu. - Save delivery day and frequency settings for that patron. - Click "Add a new delivery." - Test that the "Date" Flatpickr widget works correctly. - Go to Patrons -> A patron record -> Edit. - Test that Flatpickr widgets work on the following fields: - Date of birth - Registration date & Expiration date (linked). - Patron restrictions -> Add manual restriction -> Expiration. - View a bibliographic record and start the process of placing a hold. - After selecting a patron, test the "Hold starts on" and "Hold expires on" date fields. The fields should be linked and each should limit to future dates. - Confirm that the dates are saved correctly when you submit the hold. - Locate a bibliographic record with multiple holds and view the holds. - In the table of holds, test each date field: Date, expiration, and suspend-until. - Test that Flatpickr's static "formatDate" method is working correctly: - Locate a bibliographic record's item so that there is text in both the "Public note" and "Non-public note" field. - Check that item out to a patron. - After the page reloads the public and non-public notes should be shown under the checkout title highlighted in red. - Check for references to a "validate1" function. There should be none. Signed-off-by: Lucas Gass Signed-off-by: Martin Renvoize --- .../prog/css/src/_flatpickr.scss | 4 +++ .../prog/css/src/staff-global.scss | 7 +++- .../prog/en/includes/borrower_debarments.inc | 6 ++-- .../prog/en/includes/calendar.inc | 19 ++++++++++ .../prog/en/includes/holds_table.inc | 10 +++--- .../prog/en/modules/circ/circulation.tt | 18 +--------- .../circ/circulation_batch_checkouts.tt | 12 +++---- .../prog/en/modules/circ/offline.tt | 9 ----- .../prog/en/modules/circ/overdue.tt | 4 +-- .../prog/en/modules/circ/pendingreserves.tt | 4 +-- .../prog/en/modules/circ/reserveratios.tt | 4 +-- .../prog/en/modules/members/housebound.tt | 4 +-- .../prog/en/modules/members/memberentrygen.tt | 10 +++--- .../prog/en/modules/members/moremember.tt | 11 +----- .../prog/en/modules/reserve/request.tt | 36 ++++++++++++++----- koha-tmpl/intranet-tmpl/prog/js/calendar.js | 8 ----- koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 10 +++--- koha-tmpl/intranet-tmpl/prog/js/holds.js | 6 ++-- .../prog/js/pages/circulation.js | 32 +++++++---------- 19 files changed, 106 insertions(+), 108 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss b/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss index 2883873a6dd..19462121b3b 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss @@ -958,3 +958,7 @@ span.flatpickr-weekday { .flatpickr-day { border-radius: 0; } + +.flatpickr_wrapper { + white-space: nowrap; +} diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss index 9d8f5e8069c..7c22f355b88 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss @@ -58,6 +58,10 @@ a { &.clear_date { color: #C33; font-size: 130%; + + &:hover { + color: #FF9090; + } } &.close { @@ -219,7 +223,8 @@ aside { width: 100%; } - .hasDatepicker { + .hasDatepicker, + .flatpickr-input { margin-right: 3px; width: calc(100% - 20px); } diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/borrower_debarments.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/borrower_debarments.inc index aa53fce1678..b1aa6d1f61a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/borrower_debarments.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/borrower_debarments.inc @@ -60,8 +60,10 @@ Add manual restriction
  1. -
  2. - Clear date
  3. +
  4. + + +
Cancel
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc index 5a61a3d0584..bdb793ca671 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc @@ -31,7 +31,12 @@ }, onReady: function( selectedDates, dateStr, instance ){ /* When flatpickr instance is created, automatically append a "clear date" link */ + if( $(instance.input).hasClass("futuredate") ){ + instance.set("minDate", new Date().fp_incr(1)); + } $(instance.input) + /* Add a wrapper element so that we can prevent the clear button from wrapping */ + .wrap("") .after( $("") .attr("href","#") .addClass("clear_date") @@ -48,5 +53,19 @@ validate_date( selectedDates, instance ); }, }); + $(document).ready(function(){ + $(".flatpickr").flatpickr(); + var startPicker = $(".flatpickrfrom").flatpickr({ + onClose: function( selectedDates, dateText, instance) { + validate_date( selectedDates, instance ); + endPicker.set('minDate', selectedDates[0]); + } + }); + var endPicker = $(".flatpickrto").flatpickr({ + onClose: function( selectedDates, dateText, instance) { + validate_date( selectedDates, instance ); + }, + }); + }); [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc index 59f33cd2a0a..6250dd4c131 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc @@ -112,13 +112,14 @@ [% hold.notes | html | html_line_break %] [% IF Koha.Preference('AllowHoldDateInFuture') %] - + [% ELSE %] [% hold.date | $KohaDates %] [% END %] - - + + + [% IF ( hold.found ) %] [% IF ( hold.atdestination ) %] @@ -208,8 +209,7 @@ [% IF Koha.Preference('AutoResumeSuspendedHolds') %] - - Clear date + [% ELSE %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 6e7aa020def..b2fcc38d9af 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -636,7 +636,6 @@ [% ELSE %] [% END %] - [% END %] [% END %] @@ -884,7 +883,7 @@ [% IF Koha.Preference('AutoResumeSuspendedHolds') %] - + Specify date on which to resume [% INCLUDE 'date-format.inc' %]: [% END %] @@ -1013,21 +1012,6 @@ function toggle_onsite_checkout(){ if ( $("#onsite_checkout").prop('checked') ) { $("#duedatespec").val("[% todaysdate | $KohaDates with_hours => 1 %]") - [% IF !Koha.Preference('SpecifyDueDate') %] - $("#duedatespec").datetimepicker('destroy'); - [% END %] - } else { - $("#duedatespec").datetimepicker({ - onClose: function(dateText, inst) { - if (validate_date(dateText, inst) ) { - $("#barcode").focus(); - } - }, - hour: 23, - minute: 59 - }).on("change", function(e, value) { - if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} - }); } } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation_batch_checkouts.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation_batch_checkouts.tt index c28e6dd3e2a..41679237bca 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation_batch_checkouts.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation_batch_checkouts.tt @@ -359,14 +359,10 @@ })); [% IF Koha.Preference('SpecifyDueDate') %] - $("#duedatespec").datetimepicker({ - onClose: function(dateText, inst) { - validate_date(dateText, inst); - }, - hour: 23, - minute: 59 - }).on("change", function(e, value) { - if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} + $("#duedatespec").flatpickr({ + enableTime: true, + dateFormat: flatpickr_dateformat_string + " " + flatpickr_timeformat_string, + defaultDate: new Date().setHours(23, 59, 0, 0) /* Today a 11:59PM */ }); [% END %] }); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt index 270e2f60558..1350a9489b5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt @@ -456,15 +456,6 @@ [% END %] } - function validate1(date) { - var today = new Date(); - if ( date < today ) { - return true; - } else { - return false; - } - }; - function loadPatron(barcode) { $('#oldissues').hide(); $('#session-issues').hide(); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt index febd0d66c95..d1ecdca234e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt @@ -156,11 +156,11 @@
  • - +
  • - +
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt index fb90eeacdd9..d3e9c827644 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt @@ -271,12 +271,12 @@ - +
  • - +
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/reserveratios.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/reserveratios.tt index 9f88b39591a..67082a4b75d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/reserveratios.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/reserveratios.tt @@ -164,12 +164,12 @@
  • - +
  • - +
  • (inclusive) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt index 51488f2d596..634d24cdb75 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt @@ -217,11 +217,11 @@
  • [% IF ( visit ) %] - [% ELSE %] - [% END %] Required diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt index 49ab35f70f3..87bcf0852d2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt @@ -347,7 +347,7 @@ legend:hover { [% END %] Date of birth: - + [% IF ( mandatorydateofbirth ) %] Required [% END %] @@ -1055,7 +1055,7 @@ legend:hover { [% END %] Registration date: - + [% IF ( mandatorydateenrolled ) %] Required [% END %] @@ -1079,9 +1079,9 @@ legend:hover { Expiry date (leave blank for auto calc): [% UNLESS ( opadd ) %] - + [% ELSE %] - + [% END %] [% IF ( mandatorydateexpiry ) %] Required @@ -1373,7 +1373,7 @@ legend:hover {
  • - + Clear date
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt index 39024d6ffac..ed20b2a1b61 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -810,7 +810,7 @@ [% IF Koha.Preference('AutoResumeSuspendedHolds') %] - + Specify date on which to resume [% INCLUDE 'date-format.inc' %]: [% END %] @@ -952,15 +952,6 @@ } } } - - function validate1(date) { - var today = new Date(); - if ( date < today ) { - return true; - } else { - return false; - } - }; [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt index f54ac0d32a6..e238ff26160 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt @@ -492,17 +492,15 @@ [% IF ( reserve_in_future ) %]
  • - + - Clear date
  • [% END %]
  • - + - Clear date
  • [% UNLESS ( multi_hold ) %] @@ -1141,14 +1139,34 @@ [% END %] [% IF AutoResumeSuspendedHolds %] - $(".suspend_until_datepicker, .datepickerfrom, .datepickerto").datepicker("option", "minDate", 1); + $(".suspend_until_datepicker").flatpickr({ + minDate: new Date().fp_incr(1) /* Require that "until date" be in the future */ + }); [% END %] - $(".datepickerto").datepicker("option", "altField", ".datepickerto_hidden"); - $(".datepickerto").datepicker("option", "altFormat", "yy-mm-dd"); - $(".datepickerfrom").datepicker("option", "altField", ".datepickerfrom_hidden"); - $(".datepickerfrom").datepicker("option", "altFormat", "yy-mm-dd"); + var startPicker = $("#reserve_date").flatpickr({ + minDate: new Date().fp_incr(1), /* Require that "Hold starts on date" be in the future */ + onChange: function(selectedDates, dateStr, instance) { + altFormat = instance.formatDate(selectedDates[0], "Y-m-d"); + $(".datepickerfrom_hidden").val( altFormat ); /* Populate hidden field with ISO-formatted date */ + }, + onClose: function( selectedDates, dateText, instance) { + validate_date( selectedDates, instance ); + endPicker.set('minDate', selectedDates[0]); + } + }); + + var endPicker = $("#expiration_date").flatpickr({ + minDate: new Date().fp_incr(1), // Require that "Hold expires on date" be in the future + onChange: function(selectedDates, dateStr, instance) { + altFormat = instance.formatDate(selectedDates[0], "Y-m-d"); + $(".datepickerto_hidden").val( altFormat ); /* Populate hidden field with ISO-formatted date */ + }, + onClose: function( selectedDates, dateText, instance) { + validate_date( selectedDates, instance ); + }, + }); var my_table = $("#requestspecific").dataTable($.extend(true, {}, dataTablesDefaults, { 'bPaginate': false, diff --git a/koha-tmpl/intranet-tmpl/prog/js/calendar.js b/koha-tmpl/intranet-tmpl/prog/js/calendar.js index 1b1b31212ba..b37fd327dea 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/calendar.js +++ b/koha-tmpl/intranet-tmpl/prog/js/calendar.js @@ -186,14 +186,6 @@ $(document).ready(function () { yearRange: "c-100:c+10" }); - $("#dateofbirth").datepicker({ - yearRange: "c-100:c" - }); - - $(".futuredate").datepicker({ - minDate: 1, // require that hold suspended until date is after today - }); - $(".datepicker").datepicker({ onClose: function (dateText, inst) { validate_date(dateText, inst); diff --git a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js index 44a595173d0..1ecd66002f0 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js +++ b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js @@ -233,7 +233,7 @@ $(document).ready(function() { return false; }); - var ymd = $.datepicker.formatDate('yy-mm-dd', new Date()); + var ymd = flatpickr.formatDate(new Date(), "Y-m-d"); $('#issues-table').hide(); $('#issues-table-actions').hide(); @@ -349,7 +349,7 @@ $(document).ready(function() { if ( oObj.itemnotes ) { var span_class = "text-muted"; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){ span_class = "circ-hlt"; } title += " - " + oObj.itemnotes.escapeHtml() + ""; @@ -357,7 +357,7 @@ $(document).ready(function() { if ( oObj.itemnotes_nonpublic ) { var span_class = "text-danger"; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){ span_class = "circ-hlt"; } title += " - " + oObj.itemnotes_nonpublic.escapeHtml() + ""; @@ -740,7 +740,7 @@ $(document).ready(function() { if ( oObj.itemnotes ) { var span_class = ""; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){ span_class = "circ-hlt"; } title += " - " + oObj.itemnotes.escapeHtml() + "" @@ -748,7 +748,7 @@ $(document).ready(function() { if ( oObj.itemnotes_nonpublic ) { var span_class = ""; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){ span_class = "circ-hlt"; } title += " - " + oObj.itemnotes_nonpublic.escapeHtml() + "" diff --git a/koha-tmpl/intranet-tmpl/prog/js/holds.js b/koha-tmpl/intranet-tmpl/prog/js/holds.js index f068dbd80e1..13309533a95 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/holds.js +++ b/koha-tmpl/intranet-tmpl/prog/js/holds.js @@ -44,7 +44,7 @@ $(document).ready(function() { if ( oObj.itemnotes ) { var span_class = ""; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){ span_class = "circ-hlt"; } title += " - " + oObj.itemnotes.escapeHtml() + "" @@ -335,7 +335,9 @@ $(document).ready(function() { \ "); - $("#suspend-modal-until").datepicker({ minDate: 1 }); // Require that "until date" be in the future + $("#suspend-modal-until").flatpickr({ + minDate: new Date().fp_incr(1) // Require that "until date" be in the future + }); $("#suspend-modal-clear-date").on( "click", function() { $("#suspend-modal-until").val(""); } ); $("#suspend-modal-submit").on( "click", function( e ) { diff --git a/koha-tmpl/intranet-tmpl/prog/js/pages/circulation.js b/koha-tmpl/intranet-tmpl/prog/js/pages/circulation.js index d282e4b22a9..7a544ff2a4d 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/pages/circulation.js +++ b/koha-tmpl/intranet-tmpl/prog/js/pages/circulation.js @@ -1,3 +1,4 @@ +/* global flatpickr_dateformat_string flatpickr_timeformat_string */ $(document).ready(function() { $("#CheckAllExports").on("click",function(){ $(".export:visible").prop("checked", true); @@ -38,17 +39,19 @@ $(document).ready(function() { }).on("change", function(e) { if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} }); - $("#duedatespec").datetimepicker({ - onClose: function(dateText, inst) { - if ( validate_date(dateText, inst) ) { - $("#barcode").focus(); - } - }, - hour: 23, - minute: 59 - }).on("change", function(e, value) { - if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} + + $("#duedatespec").flatpickr({ + enableTime: true, + dateFormat: flatpickr_dateformat_string + " " + flatpickr_timeformat_string, + onClose: function() { + $("#barcode").focus(); + } + }); + + $(".clear_date").on("click", function(){ + $("#stickyduedate").prop( "checked", false ); }); + $("#export_submit").on("click",function(){ export_checkouts($("#issues-table-output-format").val()); return false; @@ -136,12 +139,3 @@ function export_checkouts(format) { document.getElementById("output_format").value = format; document.issues.submit(); } - -function validate1(date) { - var today = new Date(); - if ( date < today ) { - return true; - } else { - return false; - } -} -- 2.20.1