From 1a6639a1998884b35caf7c09618c707a77854120 Mon Sep 17 00:00:00 2001
From: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Date: Fri, 9 Feb 2024 16:59:45 +0000
Subject: [PATCH] Bug 6796: Take CalenderFirstDayOfWeek and TimeFormat into
 account

This patch adds accounting for the `CalendarFirstDayOfWeek` and
`TimeFormat` preferences in the libraries management pages.

We respect CalendarFirstDayOfWeek for both input and display, but we
only respect TimeFormat for input at this time. We need a new template
helper and js helper for formatting just time in the appropriate format,
currently we only have such formatters for full datetimes.
---
 admin/branches.pl                             |  59 ++++++----
 .../prog/en/includes/calendar.inc             |   7 ++
 .../prog/en/modules/admin/branches.tt         | 102 ++++++++++--------
 3 files changed, 103 insertions(+), 65 deletions(-)

diff --git a/admin/branches.pl b/admin/branches.pl
index 228838b7352..cc06c678249 100755
--- a/admin/branches.pl
+++ b/admin/branches.pl
@@ -102,35 +102,48 @@ if ( $op eq 'add_form' ) {
             Koha::Database->new->schema->txn_do(
                 sub {
                     $library->store->discard_changes;
+
                     # Deal with SMTP server
                     my $smtp_server_id = $input->param('smtp_server');
 
-                    if ( $smtp_server_id ) {
+                    if ($smtp_server_id) {
                         if ( $smtp_server_id eq '*' ) {
-                            $library->smtp_server({ smtp_server => undef });
-                        }
-                        else {
-                            my $smtp_server = Koha::SMTP::Servers->find( $smtp_server_id );
+                            $library->smtp_server( { smtp_server => undef } );
+                        } else {
+                            my $smtp_server = Koha::SMTP::Servers->find($smtp_server_id);
                             Koha::Exceptions::BadParameter->throw( parameter => 'smtp_server' )
                                 unless $smtp_server;
-                            $library->smtp_server({ smtp_server => $smtp_server });
+                            $library->smtp_server( { smtp_server => $smtp_server } );
                         }
                     }
 
+                    # Deal with opening hours
                     my @days        = $input->multi_param("day");
                     my @open_times  = $input->multi_param("open_time");
                     my @close_times = $input->multi_param("close_time");
 
+                    my $index = 0;
                     foreach my $day (@days) {
-                        if ( $open_times[$day] !~ /([0-9]{2}:[0-9]{2})/ ) {
-                            $open_times[$day] = undef;
+                        if ( $open_times[$index] !~ /([0-9]{2}:[0-9]{2})/ ) {
+                            $open_times[$index] = undef;
                         }
-                        if ( $close_times[$day] !~ /([0-9]{2}:[0-9]{2})/ ) {
-                            $close_times[$day] = undef;
+                        if ( $close_times[$index] !~ /([0-9]{2}:[0-9]{2})/ ) {
+                            $close_times[$index] = undef;
                         }
 
-                        my $openday = Koha::Library::Hours->find( { library_id => $branchcode, day => $day } )
-                            ->update( { open_time => $open_times[$day], close_time => $close_times[$day] } );
+                        my $openday = Koha::Library::Hours->find( { library_id => $branchcode, day => $day } );
+                        if ($openday) {
+                            $openday->update(
+                                { open_time => $open_times[$index], close_time => $close_times[$index] } );
+                        } else {
+                            $openday = Koha::Library::Hour->new(
+                                {
+                                    library_id => $branchcode, day => $day, open_time => $open_times[$index],
+                                    close_time => $close_times[$index]
+                                }
+                            )->store;
+                        }
+                        $index++;
                     }
 
                     push @messages, { type => 'message', code => 'success_on_update' };
@@ -162,33 +175,37 @@ if ( $op eq 'add_form' ) {
 
                     my $smtp_server_id = $input->param('smtp_server');
 
-                    if ( $smtp_server_id ) {
+                    # Deal with SMTP server
+                    if ($smtp_server_id) {
                         if ( $smtp_server_id ne '*' ) {
-                            my $smtp_server = Koha::SMTP::Servers->find( $smtp_server_id );
+                            my $smtp_server = Koha::SMTP::Servers->find($smtp_server_id);
                             Koha::Exceptions::BadParameter->throw( parameter => 'smtp_server' )
                                 unless $smtp_server;
-                            $library->smtp_server({ smtp_server => $smtp_server });
+                            $library->smtp_server( { smtp_server => $smtp_server } );
                         }
                     }
 
+                    # Deal with opening hours
                     my @days        = $input->multi_param("day");
                     my @open_times  = $input->multi_param("open_time");
                     my @close_times = $input->multi_param("close_time");
 
+                    my $index = 0;
                     foreach my $day (@days) {
-                        if ( $open_times[$day] !~ /([0-9]{2}:[0-9]{2})/ ) {
-                            $open_times[$day] = undef;
+                        if ( $open_times[$index] !~ /([0-9]{2}:[0-9]{2})/ ) {
+                            $open_times[$index] = undef;
                         }
-                        if ( $close_times[$day] !~ /([0-9]{2}:[0-9]{2})/ ) {
-                            $close_times[$day] = undef;
+                        if ( $close_times[$index] !~ /([0-9]{2}:[0-9]{2})/ ) {
+                            $close_times[$index] = undef;
                         }
 
                         my $openday = Koha::Library::Hour->new(
                             {
-                                library_id => $branchcode, day => $day, open_time => $open_times[$day],
-                                close_time => $close_times[$day]
+                                library_id => $branchcode, day => $day, open_time => $open_times[$index],
+                                close_time => $close_times[$index]
                             }
                         )->store;
+                        $index++;
                     }
 
                     push @messages, { type => 'message', code => 'success_on_insert' };
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc
index f0275520539..1e03e604fe2 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/calendar.inc
@@ -181,6 +181,13 @@
             options['dateFormat'] = "Y-m-d H:i";
             options['altFormat'] = flatpickr_dateformat_string + " " + flatpickr_timeformat_string;
         }
+        if( $(input).data("flatpickr-time-only") === true ) {
+            options['enableTime'] = true;
+            options['noCalendar'] = true;
+            options['dateFormat'] = "H:i";
+            options['altFormat'] = flatpickr_timeformat_string;
+            options['plugins'] = [];
+        }
 
         let fp = $(input).flatpickr(options);
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt
index 7da93b93234..9e91d957fa6 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt
@@ -300,43 +300,47 @@
                             </tr>
                         </thead>
                         <tbody>
-                            [% IF library.library_hours # Existing library %]
-                                [% daycount = 0 %]
-                                [% FOREACH hr IN library.library_hours %]
-                                <tr id="hours_[% daycount | html %]">
+                            [% SET CalendarFirstDayOfWeek = Koha.Preference("CalendarFirstDayOfWeek") %]
+                            [% IF library.library_hours.count > 0 # Existing hours %]
+                                [% SET library_hours = library.library_hours.as_list %]
+
+                                [% FOR i IN [0..6] %]
+                                [% SET d = ( CalendarFirstDayOfWeek + i ) % 7 %]
+                                [% SET hr = library_hours.$d %]
+                                <tr id="hours_[% d | html %]">
                                     <td>
-                                        [% PROCESS dayname day=daycount %]
-                                        <input type="hidden" value="[% daycount | html %]" name="day">
+                                        [% PROCESS dayname day=d %]
+                                        <input type="hidden" value="[% d | html %]" name="day">
                                     </td>
                                     <td>
-                                        [% IF hr.day == daycount && hr.open_time %]
-                                        <input type="time" value="[% hr.open_time | html %]" name="open_time">
+                                        [% IF hr.open_time %]
+                                        <input type="text" size="5" value="[% hr.open_time | html %]" name="open_time" class="flatpickr" data-flatpickr-time-only="true">
                                         [% ELSE %]
-                                        <input type="time" value="" name="open_time">
+                                        <input type="text" size="5" value="" name="open_time" class="flatpickr" data-flatpickr-time-only="true">
                                         [% END %]
                                     </td>
                                     <td>
-                                        [% IF hr.day == daycount && hr.close_time %]
-                                        <input type="time" value="[% hr.close_time | html %]" name="close_time">
+                                        [% IF hr.close_time %]
+                                        <input type="text" size="5" value="[% hr.close_time | html %]" name="close_time" class="flatpickr" data-flatpickr-time-only="true">
                                         [% ELSE %]
-                                        <input type="time" value="" name="close_time">
+                                        <input type="text" size="5" value="" name="close_time" class="flatpickr" data-flatpickr-time-only="true">
                                         [% END %]
                                     </td>
                                 </tr>
-                                [% daycount = daycount+1 %]
                                 [% END %]
-                            [% ELSE # New library %]
-                                [% FOREACH daycount IN [0..6] %]
-                                <tr id="hours_[% day | html %]">
+                            [% ELSE # New hours %]
+                                [% FOR i IN [0..6] %]
+                                [% SET d = ( CalendarFirstDayOfWeek + i ) % 7 %]
+                                <tr id="hours_[% d | html %]">
                                     <td>
-                                        [% PROCESS dayname day=daycount %]
-                                        <input type="hidden" value="[% daycount | html %]" name="day">
+                                        [% PROCESS dayname day=d %]
+                                        <input type="hidden" value="[% d | html %]" name="day">
                                     </td>
                                     <td>
-                                        <input type="time" value="" name="open_time">
+                                        <input type="text" size="5" name="open_time" class="noEnterSubmit flatpickr" data-flatpickr-time-only="true">
                                     </td>
                                     <td>
-                                        <input type="time" value="" name="close_time">
+                                        <input type="text" size="5" name="close_time" class="noEnerSubmit flatpickr" data-flatpickr-time-only="true">
                                     </td>
                                 </tr>
                                 [% END %]
@@ -371,19 +375,19 @@
 
 [% BLOCK dayname %]
     [% IF day == 0 %]
-    <span>Monday</span>
+    <span>Sunday</span>
     [% ELSIF day == 1 %]
-    <span>Tuesday</span>
+    <span>Monday</span>
     [% ELSIF day == 2 %]
-    <span>Wednesday</span>
+    <span>Tuesday</span>
     [% ELSIF day == 3 %]
-    <span>Thursday</span>
+    <span>Wednesday</span>
     [% ELSIF day == 4 %]
-    <span>Friday</span>
+    <span>Thursday</span>
     [% ELSIF day == 5 %]
-    <span>Saturday</span>
+    <span>Friday</span>
     [% ELSE %]
-    <span>Sunday</span>
+    <span>Saturday</span>
     [% END %]
 [% END %]
 
@@ -550,7 +554,8 @@
                     </li>
                     <li>
                         <span class="label">Opening hours: </span>
-                        [% IF library.library_hours # Existing library %]
+                        [% IF library.library_hours.count > 0 # Existing library %]
+                            [% SET library_hours = library.library_hours.as_list %]
                             <table id="library_hours_table">
                                 <thead>
                                     <tr>
@@ -560,11 +565,12 @@
                                     </tr>
                                 </thead>
                                 <tbody>
-                                    [% daycount = 0 %]
-                                    [% FOREACH hr IN library.library_hours %]
-                                    <tr id="hours_[% daycount | html %]">
+                                    [% FOR i IN [0..6] %]
+                                    [% SET d = ( CalendarFirstDayOfWeek + i) % 7 %]
+                                    [% SET hr = library_hours.$d %]
+                                    <tr id="hours_[% d | html %]">
                                         <td>
-                                            <span>[% PROCESS dayname day=daycount %]</span>
+                                            <span>[% PROCESS dayname day=d %]</span>
                                         </td>
                                         <td>
                                             <span>[% hr.open_time | html %]</span>
@@ -573,7 +579,6 @@
                                             <span>[% hr.close_time | html %]</span>
                                         </td>
                                     </tr>
-                                    [% daycount = daycount+1 %]
                                     [% END %]
                                 </tbody>
                             </table>
@@ -609,6 +614,7 @@
 
 [% MACRO jsinclude BLOCK %]
     [% Asset.js("js/admin-menu.js") | $raw %]
+    [% INCLUDE 'calendar.inc' %]
     [% INCLUDE 'datatables.inc' %]
     [% INCLUDE 'columns_settings.inc' %]
     [% Asset.js( "lib/codemirror/codemirror.min.js" ) | $raw %]
@@ -638,6 +644,7 @@
         var table_settings = [% TablesSettings.GetTableSettings( 'admin', 'libraries', 'libraries', 'json' ) | $raw %];
         var saved_table = localStorage.getItem("DataTables_libraries_/cgi-bin/koha/admin/branches.pl");
         var updated_settings = get_columns_saved_state(saved_table, table_settings);
+        var calendarFirstDayOfWeek = '[% Koha.Preference('CalendarFirstDayOfWeek') | html %]';
 
         $(document).ready(function() {
 
@@ -747,18 +754,25 @@
                     },
                     {
                         "data": function( row, type, val, meta ) {
-                            const daynames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'];
-                            var daycount = 0;
-                            var result = '<table id="library_hours_table"><thead><tr><th>Day</th><th>Open time</th><th>Close time</th></tr></thead><tbody>';
-                            while ( row.library_hours[daycount] ) {
-                                result += '<tr id="hours_'+daycount+'">';
-                                result += '<td>'+daynames[daycount]+'</td>';
-                                result += '<td><span>'+row.library_hours[daycount].open_time+'</span></td>';
-                                result += '<td><span>'+row.library_hours[daycount].close_time+'</span></td>';
-                                result += '</tr>';
-                                daycount++;
+                            let result = '';
+                            if ( row.library_hours.length > 0 ) {
+                                const daysOfWeek = [ _("Sunday"), _("Monday"), _("Tuesday"), _("Wednesday"), _("Thursday"), _("Friday"), _("Saturday") ];
+
+                                result = '<table id="library_hours_table"><thead><tr><th>Day</th><th>Open time</th><th>Close time</th></tr></thead><tbody>';
+                                let counter = 0;
+                                for (let i = calendarFirstDayOfWeek; counter < 7; i++) {
+                                    const day = i % 7; // Wrap around the day using modulo operator
+                                    result += '<tr id="hours_'+day+'">';
+                                    result += '<td>'+daysOfWeek[day]+'</td>';
+                                    result += '<td><span>'+row.library_hours[day].open_time+'</span></td>';
+                                    result += '<td><span>'+row.library_hours[day].close_time+'</span></td>';
+                                    result += '</tr>';
+                                    counter++;
+                                }
+                                result += '</tbody></table>';
+                            } else {
+                                result = _("Library hours not set");
                             }
-                            result += '</tbody></table>';
                             return result;
                         },
                         "searchable": false,
-- 
2.43.0