Lp 1723651: Use HTML5 Date Input Element For Holds in the OPAC
authorJason Stephenson <jason@sigio.com>
Mon, 13 Nov 2017 00:30:17 +0000 (19:30 -0500)
committerJason Stephenson <jason@sigio.com>
Sat, 20 Jan 2018 16:08:48 +0000 (11:08 -0500)
We switch from using HTML text input elements to using the new HTML5
date input element in holds forms for the thaw and expire dates.  This
gives us the advantage of accepting dates in the user's native format
and presenting the backend with a date in ISO format.  We can also set
a minimum date for expiration and thaw, which we do with a new TT2
macro, get_tomorrow_date.  This allows us to avoid date validation to
check for dates in he past entered.

We add a check in opac/parts/place_hold.tt2 for the XUL staff client
and allow it to accept dates in the MM/DD/YYYY format because
XULRunner doesn't support the HTML5 date input element.

The expire and thaw date elements still accept dates in the MM/DD/YYYY
format as well as the YYYY-MM-DD format in the event that they degrade
to a text input.  This is, unfortunately, only half-documented for the
XUL staff client user, since we can't really tell from the server if
the user's browser supports the HTML5 date input.

Signed-off-by: Jason Stephenson <jason@sigio.com>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
Open-ILS/src/templates/opac/myopac/holds/edit.tt2
Open-ILS/src/templates/opac/parts/misc_util.tt2
Open-ILS/src/templates/opac/parts/place_hold.tt2

index 8295e12..8687960 100644 (file)
@@ -913,11 +913,15 @@ sub handle_hold_update {
             $val->{"pickup_lib"} = $self->cgi->param("pickup_lib");
 
             for my $field (qw/expire_time thaw_date/) {
-                # XXX TODO make this support other date formats, not just
-                # MM/DD/YYYY.
-                next unless $self->cgi->param($field) =~
-                    m:^(\d{2})/(\d{2})/(\d{4})$:;
-                $val->{$field} = "$3-$1-$2";
+                my $param_value = $self->cgi->param($field);
+                # Check for US date format grandfathered in for XUL.
+                if ($param_value =~ m:^(\d{2})/(\d{2})/(\d{4})$:) {
+                    $val->{$field} = "$3-$1-$2";
+                } elsif ($param_value =~ m:^\d{4}-\d{2}-\d{2}$:) {
+                    # It looks like an ISO date from HTML5 date input.
+                    $val->{$field} = $param_value;
+                }
+                # Otherwise, we drop it on the floor.
             }
 
             $val->{holdable_formats} = # no-op for non-MR holds
@@ -1037,10 +1041,11 @@ sub load_place_hold {
     }
     if ($cgi->param('hold_suspend')) {
         $ctx->{frozen} = 1;
-        # TODO: Make this support other date formats, not just mm/dd/yyyy.
-        # We should use a date input type on the forms once it is supported by Firefox.
-        # I didn't do that now because it is not available in a general release.
-        if ($cgi->param('thaw_date') =~ m:^(\d{2})/(\d{2})/(\d{4})$:){
+        # We now use a HTML5 date input, but we're leaving this check in place
+        # just in case.
+        if ($cgi->param('thaw_date') =~ m:^\d{4}-\d{2}-\d{2}$:) {
+            $ctx->{thaw_date} = $cgi->param('thaw_date');
+        } elsif ($cgi->param('thaw_date') =~ m:^(\d{2})/(\d{2})/(\d{4})$:){
             eval {
                 my $dt = DateTime::Format::ISO8601->parse_datetime("$3-$1-$2");
                 $ctx->{thaw_date} = $dt->ymd;
@@ -1048,6 +1053,8 @@ sub load_place_hold {
             if ($@) {
                 $logger->warn("ignoring invalid thaw_date when placing hold request");
             }
+        } else {
+            $logger->warn("ignoring invalid thaw_date when placing hold request");
         }
     }
 
index 6b567a6..61fb6e5 100644 (file)
     hold.human_status = PROCESS get_hold_status hold=hold;
 
     # Do this up front to avoid verbosity later
-    expire_time = ahr.expire_time ? date.format(ctx.parse_datetime(ahr.expire_time), DATE_FORMAT) : '';
-    thaw_date = ahr.thaw_date ? date.format(ctx.parse_datetime(ahr.thaw_date), DATE_FORMAT) : '';
+    # The HTML5 date element needs an ISO string for the value.
+    expire_time = ahr.expire_time ? date.format(ctx.parse_datetime(ahr.expire_time), '%Y-%m-%d') : '';
+    # The HTML5 date element needs an ISO string for the value.
+    thaw_date = ahr.thaw_date ? date.format(ctx.parse_datetime(ahr.thaw_date), '%Y-%m-%d') : '';
 %]
 <h3 class="sr-only">[% l('Edit Hold') %]</h3>
 <div class="pad-bottom-five">
                             [% l('Cancel unless filled by') %]
                         </th>
                         <td>
-                            <input type="text" name="expire_time"
-                                value="[% expire_time | html %]" />
-                        </td>
-                        <td class="fmt-note">
-                            <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
-                            <!-- XXX TODO pick out a minimal, simple, reliable
-                            calendar widget that's not part of some giant,
-                            bloated framework and doesn't do anything at onload.
-                            -->
+                            <input type="date" name="expire_time"
+                                value="[% expire_time | html %]"
+                                min="[% get_tomorrow_date | html; %]" />
                         </td>
                     </tr>
                     <tr>
                             [% l('If suspended, activate on') %]
                         </th>
                         <td>
-                            <input type="text" name="thaw_date"
-                                value="[% thaw_date | html %]" />
-                        </td>
-                        <td class="fmt-note">
-                            <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
+                            <input type="date" name="thaw_date"
+                                value="[% thaw_date | html %]"
+                                min="[% get_tomorrow_date | html; %]" />
                         </td>
                     </tr>
                     [% END %]
-                     
+
                     <tr><td colspan='4'>
                     [% IF hold.metarecord_filters.formats.size OR
                         (hold.metarecord_filters.langs.size.defined && hold.metarecord_filters.langs.size > 1);
index 97cbd1e..0a1b3cb 100644 (file)
                     || CGI.param(loc_name) || CGI.param('loc') || ctx.search_ou;
     END;
 
+    # Get an ISO date string for tomorrow's date for use in hold
+    # suspension date elements.
+    MACRO get_tomorrow_date BLOCK;
+        manip = date.manip;
+        manip.UnixDate('Noon Tomorrow', '%Y-%m-%d');
+    END;
 -%]
index 76d8d9e..b903fe6 100644 (file)
@@ -249,8 +249,11 @@ function toggleActivationDate() {
             </blockquote>
             <blockquote id="toggled-block-suspend">
                 <label for="thaw_date">[% l('Activate on') %]</label>
-                <input type="text" id="thaw_date" name="thaw_date" />
+                <input type="date" id="thaw_date" name="thaw_date"
+                       min="[% get_tomorrow_date | html; %]" />
+                [% IF ctx.proto == 'oils' %]
                 <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
+                [% END %]
             </blockquote>
         </p>
         <input id="place_hold_submit" type="submit" name="submit"