View | Details | Raw Unified | Return to bug 17015
Collapse All | Expand All

(-)a/Koha/DiscreteCalendar.pm (-22 / +47 lines)
Lines 1049-1070 Returns a string representing the next day the library is open, starting from C< Link Here
1049
=cut
1049
=cut
1050
1050
1051
sub next_open_day {
1051
sub next_open_day {
1052
    my ( $self, $date ) = @_;
1052
    my ( $self, $date, $dayweek ) = @_;
1053
    my $branchcode = $self->{branchcode};
1053
    my $branchcode = $self->{branchcode};
1054
    my $schema = Koha::Database->new->schema;
1054
    my $schema = Koha::Database->new->schema;
1055
    my $dtf = $schema->storage->datetime_parser;
1055
    my $dtf = $schema->storage->datetime_parser;
1056
    my $formatted_date = $dtf->format_datetime($date);
1056
    my $formatted_date = $dtf->format_datetime($date);
1057
1057
1058
    my $options = {
1059
        order_by => { -asc => 'date' },
1060
        rows     => 1,
1061
    };
1062
    $options->{where} = \['DAYOFWEEK(date) = DAYOFWEEK(?)', $formatted_date] if $dayweek;
1063
1058
    my $rs = $schema->resultset('DiscreteCalendar')->search(
1064
    my $rs = $schema->resultset('DiscreteCalendar')->search(
1059
        {
1065
        {
1060
            branchcode => $branchcode,
1066
            branchcode => $branchcode,
1061
            is_opened  => 1,
1067
            is_opened  => 1,
1068
            date => { '>' => \['DATE(?)', $formatted_date] },
1062
        },
1069
        },
1063
        {
1070
        $options
1064
            where    => \['date > date(?)', $formatted_date],
1065
            order_by => { -asc => 'date' },
1066
            rows     => 1
1067
        }
1068
    );
1071
    );
1069
1072
1070
    my $next = $rs->next();
1073
    my $next = $rs->next();
Lines 1084-1105 Returns a string representing the closest previous day the library was open, sta Link Here
1084
=cut
1087
=cut
1085
1088
1086
sub prev_open_day {
1089
sub prev_open_day {
1087
    my ( $self, $date ) = @_;
1090
    my ( $self, $date, $dayweek ) = @_;
1088
    my $branchcode = $self->{branchcode};
1091
    my $branchcode = $self->{branchcode};
1089
    my $schema = Koha::Database->new->schema;
1092
    my $schema = Koha::Database->new->schema;
1090
    my $dtf = $schema->storage->datetime_parser;
1093
    my $dtf = $schema->storage->datetime_parser;
1091
    my $formatted_date = $dtf->format_datetime($date);
1094
    my $formatted_date = $dtf->format_datetime($date);
1092
1095
1096
    my $options = {
1097
        order_by => { -desc => 'date' },
1098
        rows     => 1,
1099
    };
1100
    $options->{where} = \['DAYOFWEEK(date) = DAYOFWEEK(?)', $formatted_date] if $dayweek;
1101
1093
    my $rs = $schema->resultset('DiscreteCalendar')->search(
1102
    my $rs = $schema->resultset('DiscreteCalendar')->search(
1094
        {
1103
        {
1095
            branchcode => $branchcode,
1104
            branchcode => $branchcode,
1096
            is_opened  => 1,
1105
            is_opened  => 1,
1106
            date => { '<' => \['DATE(?)', $formatted_date] },
1097
        },
1107
        },
1098
        {
1108
        $options
1099
            where    => \['date < date(?)', $formatted_date],
1100
            order_by => { -desc => 'date' },
1101
            rows     => 1
1102
        }
1103
    );
1109
    );
1104
1110
1105
    my $prev = $rs->next();
1111
    my $prev = $rs->next();
Lines 1165-1175 sub hours_between { Link Here
1165
    my $hours_between = $schema->resultset('DiscreteCalendar')->search(
1171
    my $hours_between = $schema->resultset('DiscreteCalendar')->search(
1166
        {
1172
        {
1167
            branchcode => $branchcode,
1173
            branchcode => $branchcode,
1168
            is_opened  => 0
1174
            is_opened  => 0,
1175
            date => {
1176
                '>=' => $start_date,
1177
                '<' => $end_date,
1178
            },
1169
        },
1179
        },
1170
        {
1171
            where => {date => {-between => [$start_date, $end_date]}},
1172
        }
1173
    );
1180
    );
1174
1181
1175
    if ($skipped_days = $hours_between->count()) {
1182
    if ($skipped_days = $hours_between->count()) {
Lines 1351-1368 sub addDays { Link Here
1351
1358
1352
    } else { # Days or Datedue
1359
    } else { # Days or Datedue
1353
        # use straight days, then use calendar to push
1360
        # use straight days, then use calendar to push
1354
        # the date to the next open day if Datedue
1361
        # the date to the next open day as appropriate
1362
        # if Datedue or Dayweek
1355
        $base_date->add_duration($days_duration);
1363
        $base_date->add_duration($days_duration);
1356
1364
1357
        if ( $self->{days_mode} eq 'Datedue' ) {
1365
        if ( $self->{days_mode} eq 'Datedue' ||
1358
            # Datedue, then use the calendar to push
1366
            $self->{days_mode} eq 'Dayweek') {
1367
            # Datedue or Dayweek, then use the calendar to push
1359
            # the date to the next open day if holiday
1368
            # the date to the next open day if holiday
1360
            if (!$self->is_opened($base_date) ) {
1369
            if ( $self->is_holiday($base_date) ) {
1370
                my $days = $days_duration->in_units('days');
1371
1372
                my $dayweek = 0;
1373
                if (
1374
                    $self->{days_mode} eq 'Dayweek' &&
1375
                    $days % 7 == 0      # Is it a period based on weeks
1376
                ) {
1377
                    my $dow = $base_date->day_of_week;
1378
                    # Representation fix
1379
                    # DateTime object dow (1-7) where Monday is 1
1380
                    # in Koha::DiscreteCalendar 1 = Sunday, not 7.
1381
                    $dow = ( $dow == 7 ) ? 1 : $dow + 1;
1382
1383
                    my @weekly_holidays = $self->get_week_days_holidays();
1384
                    $dayweek = !(@weekly_holidays && grep $_->{weekday} == $dow, @weekly_holidays);
1385
                }
1361
1386
1362
                if ( $days_duration->is_negative() ) {
1387
                if ( $days_duration->is_negative() ) {
1363
                    $base_date = $self->prev_open_day($base_date);
1388
                    $base_date = $self->prev_open_day($base_date, $dayweek);
1364
                } else {
1389
                } else {
1365
                    $base_date = $self->next_open_day($base_date);
1390
                    $base_date = $self->next_open_day($base_date, $dayweek);
1366
                }
1391
                }
1367
            }
1392
            }
1368
        }
1393
        }
(-)a/koha-tmpl/intranet-tmpl/prog/css/src/calendar.scss (+13 lines)
Lines 177-179 fieldset.brief li.radio { Link Here
177
.dayContainer {
177
.dayContainer {
178
    gap: 3px;
178
    gap: 3px;
179
}
179
}
180
181
.calendar {
182
    display: flex;
183
    align-items: start;
184
    gap: 10px;
185
    flex-wrap: wrap;
186
}
187
188
#newHoliday {
189
    flex-grow: 1;
190
    margin-top: 2px;
191
    border-radius: 0;
192
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/discrete_calendar.tt (-319 / +327 lines)
Lines 9-32 Link Here
9
</head>
9
</head>
10
10
11
<body id="tools_holidays" class="tools">
11
<body id="tools_holidays" class="tools">
12
[% INCLUDE 'header.inc' %]
12
[% WRAPPER 'header.inc' %]
13
[% INCLUDE 'cat-search.inc' %]
13
    [% INCLUDE 'cat-search.inc' %]
14
14
[% END %]
15
<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
15
16
    <ol>
16
[% WRAPPER 'sub-header.inc' %]
17
        <li>
17
    [% WRAPPER breadcrumbs %]
18
            <a href="/cgi-bin/koha/mainpage.pl">Home</a>
18
        [% WRAPPER breadcrumb_item %]
19
        </li>
20
        <li>
21
            <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
19
            <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a>
22
        </li>
20
        [% END %]
23
        <li>
21
        [% WRAPPER breadcrumb_item bc_active= 1 %]
24
            <a href="#" aria-current="page">
22
            <span>[% Branches.GetName( branch ) | html %] calendar</span>
25
                [% Branches.GetName( branch ) | html %] calendar
23
        [% END %]
26
            </a>
24
    [% END #/ WRAPPER breadcrumbs %]
27
        </li>
25
[% END #/ WRAPPER sub-header.inc %]
28
    </ol>
29
</nav>
30
26
31
<div id="main" class="main container-fluid">
27
<div id="main" class="main container-fluid">
32
    <div class="row">
28
    <div class="row">
Lines 59-368 Link Here
59
                <h1>[% Branches.GetName( branch ) | html %] calendar</h1>
55
                <h1>[% Branches.GetName( branch ) | html %] calendar</h1>
60
56
61
                <div class="row">
57
                <div class="row">
62
                    <div class="col-sm-8">
58
                    <div class="col-sm-6">
63
                        <label for="branch">Define the holidays for:</label>
59
                        <div class="page-section">
64
                        <form id="copyCalendar-form" method="post">
60
                            <label for="branch">Define the holidays for:</label>
65
                            <select id="branch" name="branch">
61
                            <form id="copyCalendar-form" method="post">
66
                                [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %]
62
                                <select id="branch" name="branch">
67
                            </select>
63
                                    [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %]
68
                            Copy calendar to
64
                                </select>
69
                            <select id='newBranch' name ='newBranch'>
65
                                Copy calendar to
70
                                <option value=""></option>
66
                                <select id='newBranch' name ='newBranch'>
71
                                [% FOREACH l IN Branches.all() %]
67
                                    <option value=""></option>
72
                                    [% UNLESS branch == l.branchcode %]
68
                                    [% FOREACH l IN Branches.all() %]
73
                                    <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option>
69
                                        [% UNLESS branch == l.branchcode %]
70
                                        <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option>
71
                                        [% END %]
74
                                    [% END %]
72
                                    [% END %]
75
                                [% END %]
73
                                </select>
76
                            </select>
74
                                <input type="hidden" name="action" value="copyBranch" />
77
                            <input type="hidden" name="action" value="copyBranch" />
75
                                <input type="submit" value="Clone">
78
                            <input type="submit" value="Clone">
79
                        </form>
80
81
                        <h3>Calendar information</h3>
82
83
                        <span id="calendar-anchor"></span>
84
85
                        <!-- ***************************** Panel to deal with new holidays ********************** -->
86
                        <div class="panel newHoliday" id="newHoliday">
87
                            <form id="newHoliday-form" method="post">
88
                                <fieldset class="brief">
89
                                    <h3>Edit date details</h3>
90
                                    <span id="holtype"></span>
91
                                    <ol>
92
                                        <li>
93
                                            <strong>Library:</strong>
94
                                            <span id="newBranchNameOutput"></span>
95
                                            <input type="hidden" id="branch" name="branch" value="[% branch %]" />
96
                                        </li>
97
                                        <li>
98
                                            <strong>From date:</strong>
99
                                            <span id="newDaynameOutput"></span>,
100
101
                                            [% IF ( dateformat == "us" ) %]<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>
102
                                            [% ELSIF ( dateformat == "metric" ) %]<span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>
103
                                            [% ELSIF ( dateformat == "dmydot" ) %]<span id="newDayOutput"></span>.<span id="newMonthOutput"></span>.<span id="newYearOutput"></span>
104
                                            [% ELSE %]<span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>[% END %]
105
106
                                            <input type="hidden" id="newDayname" name="showDayname" />
107
                                            <input type="hidden" id="Day" name="Day" />
108
                                            <input type="hidden" id="Month" name="Month" />
109
                                            <input type="hidden" id="Year" name="Year" />
110
                                        </li>
111
                                        <li class="dateinsert">
112
                                            <strong>To date:</strong>
113
                                            <input type="text" id="to_date_flatpickr" size="20" />
114
                                        </li>
115
                                        <li>
116
                                            <label for="title">Title: </label>
117
                                            <input type="text" name="Title" id="title" size="35" />
118
                                        </li>
119
                                        <li>
120
                                            <label for="description">Description: </label>
121
                                            <textarea id="description" name="description" rows="2" cols="40"></textarea>
122
                                        </li>
123
                                        <li id="holidayType">
124
                                            <label for="holidayType">Date type</label>
125
                                            <select name ='holidayType'>
126
                                                <option value="empty"></option>
127
                                                <option value="none">Working day</option>
128
                                                <option value="E">Unique holiday</option>
129
                                                <option value="W">Weekly holiday</option>
130
                                                <option value="R">Repeatable holiday</option>
131
                                                <option value="F">Floating holiday</option>
132
                                                <option value="N" disabled>Need validation</option>
133
                                            </select>
134
                                            <a href="#" class="helptext">[?]</a>
135
                                            <div class="hint">
136
                                                <ol>
137
                                                    <li><strong>Working day:</strong> the library is open on that day.</li>
138
                                                    <li><strong>Unique holiday:</strong> make a single holiday. For example, selecting August 1, 2012 will make it a holiday, but will not affect August 1 in other years.</li>
139
                                                    <li><strong>Weekly holiday:</strong> make this weekday a holiday, every week. For example, if your library is closed on Saturdays, use this option to make every Saturday a holiday.</li>
140
                                                    <li><strong>Repeatable holiday:</strong> this will take this day and month as a reference to make it a holiday. Through this option, you can repeat this rule for every year. For example, selecting August 1 will make August 1 a holiday every year.</li>
141
                                                    <li><strong>Floating holiday:</strong> this will take this day and month as a reference to make it a floating holiday. Through this option, you can add a holiday that repeats every year but not necessarily on the exact same day. On subsequent years the date will need validation.</li>
142
                                                    <li><strong>Need validation:</strong> this holiday has been added automatically, but needs to be validated.</li>
143
                                                </ol>
144
                                            </div>
145
                                        </li>
146
                                        <li id="days_of_week">
147
                                            <label for="day_of_week">Week day</label>
148
                                            <select name ='day_of_week'>
149
                                                <option value="everyday">Everyday</option>
150
                                                <option value="1">Sundays</option>
151
                                                <option value="2">Mondays</option>
152
                                                <option value="3">Tuesdays</option>
153
                                                <option value="4">Wednesdays</option>
154
                                                <option value="5">Thursdays</option>
155
                                                <option value="6">Fridays</option>
156
                                                <option value="7">Saturdays</option>
157
                                            </select>
158
                                        </li>
159
                                        <li class="radio" id="deleteType">
160
                                            <input type="checkbox" name="deleteType" id="deleteType_checkbox" value="1" ><label for="deleteType_checkbox"> Delete this type</label>
161
                                            <a href="#" class="helptext">[?]</a>
162
                                            <div class="hint">Remove all repeated or weekly holidays of the selected date or week day <br> if working day is selected.</div>
163
                                        </li>
164
                                        <li>
165
                                            <label for="openHour">Open hours: </label><input type="text" name="openHour" id='openHour' />
166
                                        </li>
167
                                        <li>
168
                                            <label for="closeHour">Close hours: </label><input type="text" name="closeHour" id='closeHour' />
169
                                        </li>
170
                                        <li class="radio">
171
                                            <input type="radio" name="action" id="EditRadioButton" value="edit" checked/>
172
                                            <label for="EditRadioButton">Edit selected dates</label>
173
                                        </li>
174
                                        <li class="radio">
175
                                            <input type="radio" name="action" id="CopyRadioButton" value="copyDates" />
176
                                            <label for="CopyRadioButton">Copy to different dates</label>
177
                                        </li>
178
                                        <li class="CopyDatePanel">
179
                                            <label>From:</label>
180
                                            <input type="text" id="copyto_from_flatpickr" size="20"/>
181
                                            <label>To:</label>
182
                                            <input type="text" id="copyto_to_flatpickr" size="20"/>
183
                                        </li>
184
                                        <li class="checkbox">
185
                                            <input type="checkbox" name="all_branches" id="all_branches" />
186
                                            <label for="all_branches">Copy to all libraries</label>.
187
                                            <a href="#" class="helptext">[?]</a>
188
                                            <div class="hint">If checked, this holiday will be copied to all libraries.</div>
189
                                        </li>
190
                                    </ol>
191
192
                                    <!-- These yyyy-mm-dd -->
193
                                    <input type="hidden" name="from_date" id='from_date'>
194
                                    <input type="hidden" name="to_date" id='to_date'>
195
                                    <input type="hidden" name="copyto_from" id='copyto_from'>
196
                                    <input type="hidden" name="copyto_to" id='copyto_to'>
197
                                    <input type="hidden" name="daysnumber" id='daysnumber'>
198
                                    <input type="hidden" name="local_today" id='local_today'>
199
200
                                    <fieldset class="action">
201
                                        <input type="submit" name="submit" value="Save" />
202
                                        <a href="#" class="cancel hidePanel newHoliday">Cancel</a>
203
                                    </fieldset>
204
                                </fieldset>
205
                            </form>
76
                            </form>
206
                        </div>
77
207
                    </div>
78
                            <h3>Calendar information</h3>
208
79
209
                    <div class="col-sm-4">
80
                            <div class="calendar">
210
                        <div class="help">
81
                                <span id="calendar-anchor"></span>
211
                            <h4>Hints</h4>
82
212
                            <ul>
83
                                <!-- ***************************** Panel to deal with new holidays ********************** -->
213
                                <li>Search in the calendar the day you want to set as holiday.</li>
84
                                <div class="panel newHoliday" id="newHoliday">
214
                                <li>Click the date to add or edit a holiday.</li>
85
                                    <form id="newHoliday-form" method="post">
215
                                <li>Enter a title and description for the holiday.</li>
86
                                        <fieldset class="brief">
216
                                <li>Specify how the holiday should repeat.</li>
87
                                            <h3>Edit date details</h3>
217
                                <li>Click Save to finish.</li>
88
                                            <span id="holtype"></span>
218
                                <li>PS:
89
                                            <ol>
219
                                    <ul>
90
                                                <li>
220
                                        <li>Past dates cannot be changed</li>
91
                                                    <strong>Library:</strong>
221
                                        <li>Weekly holidays change open/close hours for all the days affected unless inputs are empty</li>
92
                                                    <span id="newBranchNameOutput"></span>
222
                                    </ul>
93
                                                    <input type="hidden" id="branch" name="branch" value="[% branch %]" />
223
                                </li>
94
                                                </li>
224
                            </ul>
95
                                                <li>
225
                            <h4>Key</h4>
96
                                                    <strong>From date:</strong>
226
                            <p>
97
                                                    <span id="newDaynameOutput"></span>,
227
                                <span class="key normalday">Working day</span>
98
228
                                <span class="key holiday">Unique holiday</span>
99
                                                    [% IF ( dateformat == "us" ) %]
229
                                <span class="key repeatableweekly">Holiday repeating weekly</span>
100
                                                        <span id="newMonthOutput"></span>/<span id="newDayOutput"></span>/<span id="newYearOutput"></span>
230
                                <span class="key repeatableyearly">Holiday repeating yearly</span>
101
                                                    [% ELSIF ( dateformat == "metric" ) %]
231
                                <span class="key float">Floating holiday</span>
102
                                                        <span id="newDayOutput"></span>/<span id="newMonthOutput"></span>/<span id="newYearOutput"></span>
232
                                <span class="key exception">Need validation</span>
103
                                                    [% ELSIF ( dateformat == "dmydot" ) %]
233
                            </p>
104
                                                        <span id="newDayOutput"></span>.<span id="newMonthOutput"></span>.<span id="newYearOutput"></span>
234
                        </div>
105
                                                    [% ELSE %]
235
106
                                                        <span id="newYearOutput"></span>/<span id="newMonthOutput"></span>/<span id="newDayOutput"></span>
236
                        <div id="holiday-list">
107
                                                    [% END %]
237
                            [% IF ( NEED_VALIDATION_HOLIDAYS ) %]
108
238
                            <h3>Need validation holidays</h3>
109
                                                    <input type="hidden" id="newDayname" name="showDayname" />
239
                            <table id="holidaysvalidation" class="dataTable no-footer">
110
                                                    <input type="hidden" id="Day" name="Day" />
240
                                <thead>
111
                                                    <input type="hidden" id="Month" name="Month" />
241
                                    <tr>
112
                                                    <input type="hidden" id="Year" name="Year" />
242
                                        <th class="validation">Date</th>
113
                                                </li>
243
                                        <th class="validation">Title</th>
114
                                                <li class="dateinsert">
244
                                        <th class="validation">Description</th>
115
                                                    <strong>To date:</strong>
245
                                    </tr>
116
                                                    <input type="text" id="to_date_flatpickr" size="20" />
246
                                </thead>
117
                                                </li>
247
                                <tbody>
118
                                                <li>
248
                                    [% FOREACH need_validation_holiday IN NEED_VALIDATION_HOLIDAYS %]
119
                                                    <label for="title">Title: </label>
249
                                    <tr>
120
                                                    <input type="text" name="Title" id="title" size="35" />
250
                                        <td><a href="#main" onclick="go_to_date('[% need_validation_holiday.date | html %]')"><span title="[% need_validation_holiday.DATE_SORT | html %]">[% need_validation_holiday.outputdate | html %]</span></a></td>
121
                                                </li>
251
                                        <td>[% need_validation_holiday.note | html %]</td>
122
                                                <li>
252
                                        <td>[% need_validation_holiday.description.replace('\\\r\\\n', '<br />') | html %]</td>
123
                                                    <label for="description">Description: </label>
253
                                    </tr>
124
                                                    <textarea id="description" name="description" rows="2" cols="40"></textarea>
254
                                    [% END %]
125
                                                </li>
255
                                </tbody>
126
                                                <li id="holidayType">
256
                            </table>
127
                                                    <label for="holidayType">Date type</label>
257
                            [% END %]
128
                                                    <select name ='holidayType'>
258
129
                                                        <option value="empty"></option>
259
                            [% IF ( WEEKLY_HOLIDAYS ) %]
130
                                                        <option value="none">Working day</option>
260
                            <h3>Weekly - Repeatable holidays</h3>
131
                                                        <option value="E">Unique holiday</option>
261
                            <table id="holidayweeklyrepeatable" class="dataTable no-footer">
132
                                                        <option value="W">Weekly holiday</option>
262
                                <thead>
133
                                                        <option value="R">Repeatable holiday</option>
263
                                    <tr>
134
                                                        <option value="F">Floating holiday</option>
264
                                        <th class="repeatableweekly">Day of week</th>
135
                                                        <option value="N" disabled>Need validation</option>
265
                                        <th class="repeatableweekly">Title</th>
136
                                                    </select>
266
                                        <th class="repeatableweekly">Description</th>
137
                                                    <a href="#" class="helptext">[?]</a>
267
                                    </tr>
138
                                                    <div class="hint">
268
                                </thead>
139
                                                        <ol>
269
                                <tbody>
140
                                                            <li><strong>Working day:</strong> the library is open on that day.</li>
270
                                    [% FOREACH WEEK_DAYS_LOO IN WEEKLY_HOLIDAYS %]
141
                                                            <li><strong>Unique holiday:</strong> make a single holiday. For example, selecting August 1, 2012 will make it a holiday, but will not affect August 1 in other years.</li>
271
                                    <tr>
142
                                                            <li><strong>Weekly holiday:</strong> make this weekday a holiday, every week. For example, if your library is closed on Saturdays, use this option to make every Saturday a holiday.</li>
272
                                        <td>[% WEEK_DAYS_LOO.weekday | html %]</td>
143
                                                            <li><strong>Repeatable holiday:</strong> this will take this day and month as a reference to make it a holiday. Through this option, you can repeat this rule for every year. For example, selecting August 1 will make August 1 a holiday every year.</li>
273
                                        <td>[% WEEK_DAYS_LOO.note | html %]</td>
144
                                                            <li><strong>Floating holiday:</strong> this will take this day and month as a reference to make it a floating holiday. Through this option, you can add a holiday that repeats every year but not necessarily on the exact same day. On subsequent years the date will need validation.</li>
274
                                        <td>[% WEEK_DAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
145
                                                            <li><strong>Need validation:</strong> this holiday has been added automatically, but needs to be validated.</li>
275
                                    </tr>
146
                                                        </ol>
276
                                    [% END %]
147
                                                    </div>
277
                                </tbody>
148
                                                </li>
278
                            </table>
149
                                                <li id="days_of_week">
279
                            [% END %]
150
                                                    <label for="day_of_week">Week day</label>
280
151
                                                    <select name ='day_of_week'>
281
                            [% IF ( REPEATABLE_HOLIDAYS ) %]
152
                                                        <option value="everyday">Everyday</option>
282
                            <h3>Yearly - Repeatable holidays</h3>
153
                                                        <option value="1">Sundays</option>
283
                            <table id="holidaysyearlyrepeatable" class="dataTable no-footer">
154
                                                        <option value="2">Mondays</option>
284
                                <thead>
155
                                                        <option value="3">Tuesdays</option>
285
                                    <tr>
156
                                                        <option value="4">Wednesdays</option>
286
                                        [% IF ( dateformat == "metric" ) %]
157
                                                        <option value="5">Thursdays</option>
287
                                        <th class="repeatableyearly">Day/month</th>
158
                                                        <option value="6">Fridays</option>
288
                                        [% ELSE %]
159
                                                        <option value="7">Saturdays</option>
289
                                        <th class="repeatableyearly">Month/day</th>
160
                                                    </select>
161
                                                </li>
162
                                                <li class="radio" id="deleteType">
163
                                                    <input type="checkbox" name="deleteType" id="deleteType_checkbox" value="1" ><label for="deleteType_checkbox"> Delete this type</label>
164
                                                    <a href="#" class="helptext">[?]</a>
165
                                                    <div class="hint">Remove all repeated or weekly holidays of the selected date or week day <br> if working day is selected.</div>
166
                                                </li>
167
                                                <li>
168
                                                    <label for="openHour">Open hours: </label><input type="text" name="openHour" id='openHour' />
169
                                                </li>
170
                                                <li>
171
                                                    <label for="closeHour">Close hours: </label><input type="text" name="closeHour" id='closeHour' />
172
                                                </li>
173
                                                <li class="radio">
174
                                                    <input type="radio" name="action" id="EditRadioButton" value="edit" checked/>
175
                                                    <label for="EditRadioButton">Edit selected dates</label>
176
                                                </li>
177
                                                <li class="radio">
178
                                                    <input type="radio" name="action" id="CopyRadioButton" value="copyDates" />
179
                                                    <label for="CopyRadioButton">Copy to different dates</label>
180
                                                </li>
181
                                                <li class="CopyDatePanel">
182
                                                    <label>From:</label>
183
                                                    <input type="text" id="copyto_from_flatpickr" size="20"/>
184
                                                    <label>To:</label>
185
                                                    <input type="text" id="copyto_to_flatpickr" size="20"/>
186
                                                </li>
187
                                                <li class="checkbox">
188
                                                    <input type="checkbox" name="all_branches" id="all_branches" />
189
                                                    <label for="all_branches">Copy to all libraries</label>.
190
                                                    <a href="#" class="helptext">[?]</a>
191
                                                    <div class="hint">If checked, this holiday will be copied to all libraries.</div>
192
                                                </li>
193
                                            </ol>
194
195
                                            <!-- These yyyy-mm-dd -->
196
                                            <input type="hidden" name="from_date" id='from_date'>
197
                                            <input type="hidden" name="to_date" id='to_date'>
198
                                            <input type="hidden" name="copyto_from" id='copyto_from'>
199
                                            <input type="hidden" name="copyto_to" id='copyto_to'>
200
                                            <input type="hidden" name="daysnumber" id='daysnumber'>
201
                                            <input type="hidden" name="local_today" id='local_today'>
202
203
                                            <fieldset class="action">
204
                                                <input type="submit" name="submit" value="Save" />
205
                                                <a href="#" class="cancel hidePanel newHoliday">Cancel</a>
206
                                            </fieldset>
207
                                        </fieldset>
208
                                    </form>
209
                                </div>
210
                            </div>
211
                        </div> <!-- /.page-section -->
212
                    </div> <!-- /.col-sm-6 -->
213
214
                    <div class="col-sm-6">
215
                        <div class="page-section">
216
                            <div class="help">
217
                                <h4>Hints</h4>
218
                                <ul>
219
                                    <li>Search in the calendar the day you want to set as holiday.</li>
220
                                    <li>Click the date to add or edit a holiday.</li>
221
                                    <li>Enter a title and description for the holiday.</li>
222
                                    <li>Specify how the holiday should repeat.</li>
223
                                    <li>Click Save to finish.</li>
224
                                    <li>PS:
225
                                        <ul>
226
                                            <li>Past dates cannot be changed</li>
227
                                            <li>Weekly holidays change open/close hours for all the days affected unless inputs are empty</li>
228
                                        </ul>
229
                                    </li>
230
                                </ul>
231
                                <h4>Key</h4>
232
                                <p>
233
                                    <span class="key normalday">Working day</span>
234
                                    <span class="key holiday">Unique holiday</span>
235
                                    <span class="key repeatableweekly">Holiday repeating weekly</span>
236
                                    <span class="key repeatableyearly">Holiday repeating yearly</span>
237
                                    <span class="key float">Floating holiday</span>
238
                                    <span class="key exception">Need validation</span>
239
                                </p>
240
                            </div> <!-- /#help -->
241
242
                            <div id="holiday-list">
243
                                [% IF ( NEED_VALIDATION_HOLIDAYS ) %]
244
                                <h3>Need validation holidays</h3>
245
                                <table id="holidaysvalidation" class="dataTable no-footer">
246
                                    <thead>
247
                                        <tr>
248
                                            <th class="validation">Date</th>
249
                                            <th class="validation">Title</th>
250
                                            <th class="validation">Description</th>
251
                                        </tr>
252
                                    </thead>
253
                                    <tbody>
254
                                        [% FOREACH need_validation_holiday IN NEED_VALIDATION_HOLIDAYS %]
255
                                        <tr>
256
                                            <td><a href="#main" onclick="go_to_date('[% need_validation_holiday.date | html %]')"><span title="[% need_validation_holiday.DATE_SORT | html %]">[% need_validation_holiday.outputdate | html %]</span></a></td>
257
                                            <td>[% need_validation_holiday.note | html %]</td>
258
                                            <td>[% need_validation_holiday.description.replace('\\\r\\\n', '<br />') | html %]</td>
259
                                        </tr>
290
                                        [% END %]
260
                                        [% END %]
291
                                        <th class="repeatableyearly">Title</th>
261
                                    </tbody>
292
                                        <th class="repeatableyearly">Description</th>
262
                                </table> <!-- /#holidayexceptions -->
293
                                    </tr>
263
                                [% END # /IF ( EXCEPTION_HOLIDAYS_LOOP ) %]
294
                                </thead>
264
295
                                <tbody>
265
                                [% IF ( WEEKLY_HOLIDAYS ) %]
296
                                    [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN REPEATABLE_HOLIDAYS %]
266
                                <h3>Weekly - Repeatable holidays</h3>
297
                                    <tr>
267
                                <table id="holidayweeklyrepeatable" class="dataTable no-footer">
298
                                        [% IF ( dateformat == "metric" ) %]
268
                                    <thead>
299
                                        <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT | html %]">[% DAY_MONTH_HOLIDAYS_LOO.day | html %]/[% DAY_MONTH_HOLIDAYS_LOO.month | html %]</span></td>
269
                                        <tr>
300
                                        [% ELSE %]
270
                                            <th class="repeatableweekly">Day of week</th>
301
                                        <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT | html %]">[% DAY_MONTH_HOLIDAYS_LOO.month | html %]/[% DAY_MONTH_HOLIDAYS_LOO.day | html %]</span></td>
271
                                            <th class="repeatableweekly">Title</th>
272
                                            <th class="repeatableweekly">Description</th>
273
                                        </tr>
274
                                    </thead>
275
                                    <tbody>
276
                                        [% FOREACH WEEK_DAYS_LOO IN WEEKLY_HOLIDAYS %]
277
                                        <tr>
278
                                            <td>[% WEEK_DAYS_LOO.weekday | html %]</td>
279
                                            <td>[% WEEK_DAYS_LOO.note | html %]</td>
280
                                            <td>[% WEEK_DAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
281
                                        </tr>
302
                                        [% END %]
282
                                        [% END %]
303
                                        <td>[% DAY_MONTH_HOLIDAYS_LOO.note | html %]</td>
283
                                    </tbody>
304
                                        <td>[% DAY_MONTH_HOLIDAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
284
                                </table> <!-- /#holidayweeklyrepeatable -->
305
                                    </tr>
285
                                [% END # / IF ( WEEKLY_HOLIDAYS ) %]
306
                                    [% END %]
286
307
                                </tbody>
287
                                [% IF ( REPEATABLE_HOLIDAYS ) %]
308
                            </table>
288
                                <h3>Yearly - Repeatable holidays</h3>
309
                            [% END %]
289
                                <table id="holidaysyearlyrepeatable" class="dataTable no-footer">
310
290
                                    <thead>
311
                            [% IF ( UNIQUE_HOLIDAYS ) %]
291
                                        <tr>
312
                            <h3>Unique holidays</h3>
292
                                            [% IF ( dateformat == "metric" ) %]
313
                            <label class="controls">
293
                                            <th class="repeatableyearly">Day/month</th>
314
                                <input type="checkbox" name="show_past" id="show_past_holidaysunique" class="show_past" />
294
                                            [% ELSE %]
315
                                Show past entries
295
                                            <th class="repeatableyearly">Month/day</th>
316
                            </label>
296
                                            [% END %]
317
                            <table id="holidaysunique" class="dataTable no-footer">
297
                                            <th class="repeatableyearly">Title</th>
318
                                <thead>
298
                                            <th class="repeatableyearly">Description</th>
319
                                    <tr>
299
                                        </tr>
320
                                        <th class="holiday">Date</th>
300
                                    </thead>
321
                                        <th class="holiday">Title</th>
301
                                    <tbody>
322
                                        <th class="holiday">Description</th>
302
                                        [% FOREACH DAY_MONTH_HOLIDAYS_LOO IN REPEATABLE_HOLIDAYS %]
323
                                    </tr>
303
                                        <tr>
324
                                </thead>
304
                                            [% IF ( dateformat == "metric" ) %]
325
                                <tbody>
305
                                            <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT | html %]">[% DAY_MONTH_HOLIDAYS_LOO.day | html %]/[% DAY_MONTH_HOLIDAYS_LOO.month | html %]</span></td>
326
                                    [% FOREACH HOLIDAYS_LOO IN UNIQUE_HOLIDAYS %]
306
                                            [% ELSE %]
327
                                    <tr data-date="[% HOLIDAYS_LOO.date | html %]">
307
                                            <td><span title="[% DAY_MONTH_HOLIDAYS_LOO.DATE_SORT | html %]">[% DAY_MONTH_HOLIDAYS_LOO.month | html %]/[% DAY_MONTH_HOLIDAYS_LOO.day | html %]</span></td>
328
                                        <td><a href="#main" onclick="go_to_date('[% HOLIDAYS_LOO.date | html %]')"><span title="[% HOLIDAYS_LOO.DATE_SORT | html %]">[% HOLIDAYS_LOO.outputdate | html %]</span></a></td>
308
                                            [% END %]
329
                                        <td>[% HOLIDAYS_LOO.note | html %]</td>
309
                                            <td>[% DAY_MONTH_HOLIDAYS_LOO.note | html %]</td>
330
                                        <td>[% HOLIDAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
310
                                            <td>[% DAY_MONTH_HOLIDAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
331
                                    </tr>
311
                                        </tr>
332
                                    [% END %]
312
                                        [% END %]
333
                                </tbody>
313
                                    </tbody>
334
                            </table>
314
                                </table> <!-- /#holidaysyearlyrepeatable -->
335
                            [% END %]
315
                                [% END # /IF ( REPEATABLE_HOLIDAYS ) %]
336
316
337
                            [% IF ( FLOAT_HOLIDAYS ) %]
317
                                [% IF ( UNIQUE_HOLIDAYS ) %]
338
                            <h3>Floating holidays</h3>
318
                                <h3>Unique holidays</h3>
339
                            <label class="controls">
319
                                <label class="controls">
340
                                <input type="checkbox" name="show_past" id="show_past_holidaysfloat" class="show_past" />
320
                                    <input type="checkbox" name="show_past" id="show_past_holidaysunique" class="show_past" />
341
                                Show past entries
321
                                    Show past entries
342
                            </label>
322
                                </label>
343
                            <table id="holidaysfloat" class="dataTable no-footer">
323
                                <table id="holidaysunique" class="dataTable no-footer">
344
                                <thead>
324
                                    <thead>
345
                                    <tr>
325
                                        <tr>
346
                                        <th class="float">Date</th>
326
                                            <th class="holiday">Date</th>
347
                                        <th class="float">Title</th>
327
                                            <th class="holiday">Title</th>
348
                                        <th class="float">Description</th>
328
                                            <th class="holiday">Description</th>
349
                                    </tr>
329
                                        </tr>
350
                                </thead>
330
                                    </thead>
351
                                <tbody>
331
                                    <tbody>
352
                                    [% FOREACH float_holiday IN FLOAT_HOLIDAYS %]
332
                                        [% FOREACH HOLIDAYS_LOO IN UNIQUE_HOLIDAYS %]
353
                                    <tr data-date="[% float_holiday.date | html %]">
333
                                        <tr data-date="[% HOLIDAYS_LOO.date | html %]">
354
                                        <td><a href="#main" onclick="go_to_date('[% float_holiday.date | html %]')"><span title="[% float_holiday.DATE_SORT | html %]">[% float_holiday.outputdate | html %]</span></a></td>
334
                                            <td><a href="#main" onclick="go_to_date('[% HOLIDAYS_LOO.date | html %]')"><span title="[% HOLIDAYS_LOO.DATE_SORT | html %]">[% HOLIDAYS_LOO.outputdate | html %]</span></a></td>
355
                                        <td>[% float_holiday.note | html %]</td>
335
                                            <td>[% HOLIDAYS_LOO.note | html %]</td>
356
                                        <td>[% float_holiday.description.replace('\\\r\\\n', '<br />') | html %]</td>
336
                                            <td>[% HOLIDAYS_LOO.description.replace('\\\r\\\n', '<br />') | html %]</td>
357
                                    </tr>
337
                                        </tr>
358
                                    [% END %]
338
                                        [% END %]
359
                                </tbody>
339
                                    </tbody>
360
                            </table>
340
                                </table> <!-- /#holidaysunique -->
361
                            [% END %]
341
                                [% END # /IF ( UNIQUE_HOLIDAYS ) %]
362
                        </div>
342
363
                    </div>
343
                                [% IF ( FLOAT_HOLIDAYS ) %]
364
                </div>
344
                                <h3>Floating holidays</h3>
365
345
                                <label class="controls">
346
                                    <input type="checkbox" name="show_past" id="show_past_holidaysfloat" class="show_past" />
347
                                    Show past entries
348
                                </label>
349
                                <table id="holidaysfloat" class="dataTable no-footer">
350
                                    <thead>
351
                                        <tr>
352
                                            <th class="float">Date</th>
353
                                            <th class="float">Title</th>
354
                                            <th class="float">Description</th>
355
                                        </tr>
356
                                    </thead>
357
                                    <tbody>
358
                                        [% FOREACH float_holiday IN FLOAT_HOLIDAYS %]
359
                                        <tr data-date="[% float_holiday.date | html %]">
360
                                            <td><a href="#main" onclick="go_to_date('[% float_holiday.date | html %]')"><span title="[% float_holiday.DATE_SORT | html %]">[% float_holiday.outputdate | html %]</span></a></td>
361
                                            <td>[% float_holiday.note | html %]</td>
362
                                            <td>[% float_holiday.description.replace('\\\r\\\n', '<br />') | html %]</td>
363
                                        </tr>
364
                                        [% END %]
365
                                    </tbody>
366
                                </table> <!-- /#holidaysfloat -->
367
                                [% END # /IF ( FLOAT_HOLIDAYS ) %]
368
                            </div> <!-- /#holiday-list -->
369
                        </div> <!-- /.page-section -->
370
                    </div> <!-- /.col-sm-6 -->
371
                </div> <!-- /.row -->
366
            </main>
372
            </main>
367
        </div> <!-- /.col-sm-10.col-sm-push-2 -->
373
        </div> <!-- /.col-sm-10.col-sm-push-2 -->
368
374
Lines 460-465 Link Here
460
                $(".CopyDatePanel").toggle(value);
466
                $(".CopyDatePanel").toggle(value);
461
            }
467
            }
462
            $("#title").prop('disabled', value);
468
            $("#title").prop('disabled', value);
469
            $("#description").prop('disabled', value);
463
            $("#holidayType select").prop('disabled', value);
470
            $("#holidayType select").prop('disabled', value);
464
            $("#openHour").prop('disabled', value);
471
            $("#openHour").prop('disabled', value);
465
            $("#closeHour").prop('disabled', value);
472
            $("#closeHour").prop('disabled', value);
Lines 681-687 Link Here
681
            });
688
            });
682
689
683
            $("a.helptext").click(function () {
690
            $("a.helptext").click(function () {
684
                $(this).parent().find(".hint").toggle();
691
                $(this).parent().find(".hint")
692
                    .css("max-width", ($(this).closest("#newHoliday").width() - 20)+"px")
693
                    .toggle();
685
                return false;
694
                return false;
686
            });
695
            });
687
696
Lines 796-800 Link Here
796
    </script>
805
    </script>
797
[% END %]
806
[% END %]
798
807
799
<!-- the main div is closed in intranet-bottom.inc -->
800
[% INCLUDE 'intranet-bottom.inc' %]
808
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/tools/discrete_calendar.pl (-21 / +12 lines)
Lines 20-27 use Modern::Perl; Link Here
20
20
21
use CGI qw ( -utf8 );
21
use CGI qw ( -utf8 );
22
22
23
use C4::Auth qw ( get_template_and_user );
23
use C4::Auth qw( get_template_and_user );
24
use C4::Output qw ( output_html_with_http_headers );
24
use C4::Output qw( output_html_with_http_headers );
25
25
26
use Koha::DateUtils qw ( dt_from_string output_pref );
26
use Koha::DateUtils qw ( dt_from_string output_pref );
27
use Koha::DiscreteCalendar;
27
use Koha::DiscreteCalendar;
Lines 35-41 my ($template, $loggedinuser, $cookie) = get_template_and_user( Link Here
35
        type => "intranet",
35
        type => "intranet",
36
        query => $input,
36
        query => $input,
37
        flagsrequired => {tools => 'edit_calendar'},
37
        flagsrequired => {tools => 'edit_calendar'},
38
        debug => 1,
39
    }
38
    }
40
);
39
);
41
40
Lines 56-66 my $action = $input->param('action') || ''; Link Here
56
55
57
# calendardate - date passed in url for human readability (syspref)
56
# calendardate - date passed in url for human readability (syspref)
58
# if the url has an invalid date default to 'now.'
57
# if the url has an invalid date default to 'now.'
59
my $calendarinput_dt = eval { dt_from_string( scalar $input->param('calendardate')); } || dt_from_string;
58
# FIXME There is something to improve in the date handling here
59
my $calendarinput_dt = eval { dt_from_string( scalar $input->param('calendardate') ); } || dt_from_string;
60
my $calendardate = output_pref( { dt => $calendarinput_dt, dateonly => 1 } );
60
my $calendardate = output_pref( { dt => $calendarinput_dt, dateonly => 1 } );
61
61
62
if ($action eq 'copyBranch') {
62
if ($action eq 'copyBranch') {
63
    $calendar->copy_to_branch(scalar $input->param('newBranch'));
63
    my $new_branch = scalar $input->param('newBranch');
64
    $calendar->copy_to_branch($new_branch) if $new_branch;
64
} elsif($action eq 'copyDates') {
65
} elsif($action eq 'copyDates') {
65
    my $from_startDate = $input->param('from_date') ||'';
66
    my $from_startDate = $input->param('from_date') ||'';
66
    my $from_endDate = $input->param('to_date') || '';
67
    my $from_endDate = $input->param('to_date') || '';
Lines 139-171 if ( C4::Context->only_my_library ) { Link Here
139
140
140
# Get all the holidays
141
# Get all the holidays
141
142
142
#discrete_calendar weekly holidays
143
my @week_days = $calendar->get_week_days_holidays();
143
my @week_days = $calendar->get_week_days_holidays();
144
145
#discrete_calendar repeatable holidays
146
my @repeatable_holidays = $calendar->get_repeatable_holidays();
144
my @repeatable_holidays = $calendar->get_repeatable_holidays();
145
my @unique_holidays = $calendar->get_unique_holidays(0);
146
my @float_holidays = $calendar->get_float_holidays(0);
147
my @need_validation_holidays = $calendar->get_need_validation_holidays();
147
148
148
#discrete_calendar unique holidays
149
#Calendar minimum & maximum dates
149
my @unique_holidays =$calendar->get_unique_holidays(0);
150
#discrete_calendar floating holidays
151
my @float_holidays =$calendar->get_float_holidays(0);
152
#discrete_caledar need validation holidays
153
my @need_validation_holidays =$calendar->get_need_validation_holidays();
154
155
#Calendar maximum date
156
my $minDate = $calendar->get_min_date();
150
my $minDate = $calendar->get_min_date();
157
158
#Calendar minimum date
159
my $maxDate = $calendar->get_max_date();
151
my $maxDate = $calendar->get_max_date();
160
152
161
my @datesInfos = $calendar->get_dates_info();
153
my @datesInfos = $calendar->get_dates_info();
162
154
163
$template->param(
155
$template->param(
156
    WEEKLY_HOLIDAYS          => \@week_days,
157
    REPEATABLE_HOLIDAYS      => \@repeatable_holidays,
164
    UNIQUE_HOLIDAYS          => \@unique_holidays,
158
    UNIQUE_HOLIDAYS          => \@unique_holidays,
165
    FLOAT_HOLIDAYS           => \@float_holidays,
159
    FLOAT_HOLIDAYS           => \@float_holidays,
166
    NEED_VALIDATION_HOLIDAYS => \@need_validation_holidays,
160
    NEED_VALIDATION_HOLIDAYS => \@need_validation_holidays,
167
    REPEATABLE_HOLIDAYS      => \@repeatable_holidays,
168
    WEEKLY_HOLIDAYS          => \@week_days,
169
    calendardate             => $calendardate,
161
    calendardate             => $calendardate,
170
    keydate                  => $keydate,
162
    keydate                  => $keydate,
171
    branch                   => $branch,
163
    branch                   => $branch,
172
- 

Return to bug 17015