@@ -, +, @@ - Go to Tools -> Calendar. - Confirm that entering holidays works correctly for all types: Single, weekly, yearly, ranges, repeated ranges. - Confirm that holidays are deleted as expected. - Confirm that the colors of each type of holiday is correct. --- .../intranet-tmpl/prog/css/src/_flatpickr.scss | 3 +- .../css/src/{_vars.scss => _flatpickr_vars.scss} | 4 +- koha-tmpl/intranet-tmpl/prog/css/src/calendar.scss | 149 +++++++++++++++++++++ .../prog/en/modules/tools/holidays.tt | 139 +++++++++---------- 4 files changed, 223 insertions(+), 72 deletions(-) rename koha-tmpl/intranet-tmpl/prog/css/src/{_vars.scss => _flatpickr_vars.scss} (94%) create mode 100644 koha-tmpl/intranet-tmpl/prog/css/src/calendar.scss --- a/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss +++ a/koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss @@ -1,4 +1,4 @@ -@import "vars"; +@import "flatpickr_vars"; @-webkit-keyframes fpFadeInDown { from { @@ -69,6 +69,7 @@ direction: ltr; display: none; font-size: 14px; + gap: 2px; line-height: 24px; opacity: 0; padding: 0; --- a/koha-tmpl/intranet-tmpl/prog/css/src/_vars.scss +++ a/koha-tmpl/intranet-tmpl/prog/css/src/_vars.scss @@ -2,9 +2,9 @@ $bezier: cubic-bezier(0.23, 1, 0.32, 1); $slideTime: 400ms; -$daySize: 39px; +$daySize: 39px !default; $padding: $daySize / 16; -$dayMargin: 2px; +$dayMargin: 2px !default; $daysWidth: $daySize * 7 + $dayMargin * 14 + $padding * 2 + 2; $calendarWidth: $daysWidth; --- a/koha-tmpl/intranet-tmpl/prog/css/src/calendar.scss +++ a/koha-tmpl/intranet-tmpl/prog/css/src/calendar.scss @@ -0,0 +1,149 @@ +$daySize: 45px; +$exception_bg: #B3D4FF; +$holiday_bg: #FFAEAE; +$repeatableweekly_bg: #FFFF99; +$repeatableyearly_bg: #FFCC66; +$selected: #B9DB88; + +@import "flatpickr"; + +.controls { + display: block; + padding: 3px 0; +} + +.key { + line-height: 230%; + padding: 3px; + white-space: nowrap; + + &.exception { + background-color: $exception_bg; + } + + &.holiday { + background-color: $holiday_bg; + } + + &.repeatableweekly { + background-color: $repeatableweekly_bg; + } + + &.repeatableyearly { + background-color: $repeatableyearly_bg; + } +} + +.flatpickr-day { + &.selected { + background-color: $selected; + border: 0; + } + + &.exception { + background-color: $exception_bg; + + &.selected { + border: 3px solid $selected; + } + } + + &.holiday { + background-color: $holiday_bg; + + &.selected { + border: 3px solid $selected; + } + } + + &.repeatableweekly { + background-color: $repeatableweekly_bg; + + &.selected { + border: 3px solid $selected; + } + } + + &.repeatableyearly { + background-color: $repeatableyearly_bg; + + &.selected { + border: 3px solid $selected; + } + } +} + +#holidayexceptions th.exception { + background-color: $exception_bg; +} + +#holidaysunique th.holiday { + background-color: $holiday_bg; + + &.selected { + border: 2px solid #fff4c6; + } +} + +#holidayweeklyrepeatable th.repeatableweekly { + background-color: $repeatableweekly_bg; +} + +#holidaysyearlyrepeatable th.repeatableyearly { + background-color: $repeatableyearly_bg; +} + +.panel { + border: 1px solid #B9D8D9; + border-radius: 4px; + box-shadow: none; + padding: 0; + display: none; + margin: 1em 0; + z-index: 1; +} + +fieldset.brief { + border: 0; + border-radius: 4px; + margin: 0; +} + +#showHoliday { + margin: .5em 0; +} + +fieldset.brief ol { + font-size: 100%; +} + +fieldset.brief li, +fieldset.brief li.radio { + padding: 0.2em 0; +} + +#holidayweeklyrepeatable, +#holidaysyearlyrepeatable, +#holidaysunique, +#holidayexceptions { + font-size: 90%; + margin-bottom: 1em; +} + +#calendar-container { + margin: 1em 0; +} + +#calendar-anchor { + display: none; +} + +.flatpickr-calendar { + border-radius: 0; + border: 1px solid #B9D8D9; + box-shadow: none; +} + +.dayContainer { + gap: 3px; +} --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt @@ -41,11 +41,6 @@ [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] - - - - -
@@ -76,7 +71,7 @@
  • To date: - +
  • @@ -141,7 +136,7 @@
  • - +
    @@ -174,7 +169,7 @@
  • To date: - +
  • @@ -228,15 +223,10 @@
  • - - - - - - - -

    Calendar information

    -
    +
    +

    Calendar information

    + +
    @@ -497,35 +487,48 @@ location.href='/cgi-bin/koha/tools/holidays.pl?branch=' + branch + '&calendardate=' + "[% calendardate | html %]"; } - function Help() { - newin=window.open("/cgi-bin/koha/help.pl","KohaHelp",'width=600,height=600,toolbar=false,scrollbars=yes'); - } - - /* This function gives css clases to each kind of day */ - function dateStatusHandler(date) { - date = new Date(date); - var day = date.getDate(); - var month = date.getMonth() + 1; - var year = date.getFullYear(); - var weekDay = date.getDay(); + /** + * Build settings to be passed to the formatDay function for each day in the calendar + * @param {object} dayElem - HTML node passed from Flatpickr + * @return {void} + */ + function dateStatusHandler( dayElem ) { + var day = dayElem.dateObj.getDate(); + var month = dayElem.dateObj.getMonth() + 1; + var year = dayElem.dateObj.getFullYear(); + var weekDay = dayElem.dateObj.getDay(); var dayMonth = month + '/' + day; var dateString = year + '/' + month + '/' + day; if (exception_holidays[dateString] != null) { - return [true, "exception", _("Exception: %s").format(exception_holidays[dateString].title)]; + formatDay( [ "exception", _("Exception: %s").format(exception_holidays[dateString].title)], dayElem ); } else if ( week_days[weekDay] != null ){ - return [true, "repeatableweekly", _("Weekly holiday: %s").format(week_days[weekDay].title)]; + formatDay( [ "repeatableweekly", _("Weekly holiday: %s").format(week_days[weekDay].title)], dayElem ); } else if ( day_month_holidays[dayMonth] != null ) { - return [true, "repeatableyearly", _("Yearly holiday: %s").format(day_month_holidays[dayMonth].title)]; + formatDay( [ "repeatableyearly", _("Yearly holiday: %s").format(day_month_holidays[dayMonth].title)], dayElem ); } else if (holidays[dateString] != null) { - return [true, "holiday", _("Single holiday: %s").format(holidays[dateString].title)]; + formatDay( [ "holiday", _("Single holiday: %s").format(holidays[dateString].title)], dayElem ); } else { - return [true, "normalday", _("Normal day")]; + formatDay( [ "normalday", _("Normal day")], dayElem ); } } - /* This function is in charge of showing the correct panel considering the kind of holiday */ - function dateChanged(calendar) { - calendar = new Date(calendar); + /** + * Adds style and title attribute to a day on the calendar + * @param {object} settings - span class attribute ([0]) and title attribute ([1]) + * @param {node} dayElem - HTML node passed from Flatpickr + * @return {void} + */ + function formatDay( settings, dayElem ){ + $(dayElem).attr("title", settings[1]).addClass( settings[0]); + } + + /** + * Triggers an action based on a click on a calendar day: If a holiday exists on + * that day it loads an edit form. If there is no existing holiday one can be created + * @param {object} calendar - a Date object corresponding to the clicked day + * @return {void} + */ + function dateChanged( calendar ) { var day = calendar.getDate(); var month = calendar.getMonth() + 1; var year = calendar.getFullYear(); @@ -579,7 +582,7 @@ "sDom": 't', "bPaginate": false })); - var tables = $("#holidayexceptions,#holidaysyearlyrepeatable,#holidaysunique").DataTable($.extend(true, {}, dataTablesDefaults, { + var tables = $("#holidayexceptions, #holidaysyearlyrepeatable, #holidaysunique").DataTable($.extend(true, {}, dataTablesDefaults, { "sDom": 't', "bPaginate": false, "createdRow": function( row, data, dataIndex ) { @@ -597,46 +600,44 @@ $("a.helptext").click(function(){ $(this).parent().find(".hint").toggle(); return false; }); - $("#dateofrange").datepicker({ - beforeShow: function() { - var startdate = $("#jcalendar-container").datepicker("getDate"); - if (startdate !== null) { - var sd = new Date(startdate); - var ed = new Date($(this).datepicker("getDate")); - if (ed < sd) { - $(this).datepicker("setDate", startdate); - $(this).datepicker("option", "defaultDate", startdate); - } - } - } - }); - $("#datecancelrange").datepicker(); + + var dateofrange = $("#dateofrange").flatpickr(); + + var datecancelrange = $("#datecancelrange").flatpickr(); + $("#dateofrange").each(function () { this.value = "" }); $("#datecancelrange").each(function () { this.value = "" }); - $("#jcalendar-container").datepicker({ - beforeShowDay: function(thedate) { - var day = thedate.getDate(); - var month = thedate.getMonth() + 1; - var year = thedate.getFullYear(); - var dateString = year + '/' + month + '/' + day; - return dateStatusHandler(dateString); + + var maincalendar = $("#calendar-anchor").flatpickr({ + inline: true, + onReady: function(){ + return; + }, + onDayCreate: function( dObj, dStr, fp, dayElem ){ + /* for each day on the calendar, get the + correct status information for the date */ + dateStatusHandler( dayElem ); }, - onSelect: function(dateText, inst) { - dateChanged($(this).datepicker("getDate")); - var enddate = $("#dateofrange").datepicker("getDate"); - $("#dateofrange").datepicker("option", "defaultDate", $(this).datepicker("getDate")); - $("#dateofrange").datepicker( "option", "minDate", $(this).datepicker("getDate")); //ensure end date can't be before start date - if (enddate !== null) { - var ed = new Date(enddate); - var sd = new Date($(this).datepicker("getDate")); - if (ed < sd) { - $("#dateofrange").datepicker("setDate", $(this).datepicker("getDate")); - $("#dateofrange").datepicker("option", "defaultDate", enddate); + onChange: function( selectedDates, dateStr, instance ){ + var fromdate = selectedDates[0]; + var enddate = dateofrange.selectedDates[0]; + + dateChanged( fromdate ); + + dateofrange.set( 'defaultDate', fromdate ); + dateofrange.set( 'minDate', fromdate ); + + if ( enddate != undefined ) { + if ( enddate < fromdate ) { + dateofrange.set("defaultDate", fromdate); + dateofrange.setDate(fromdate); } } + }, defaultDate: new Date("[% keydate | html %]") }); + $(".hidePanel").on("click",function(){ if( $(this).hasClass("showHoliday") ){ hidePanel("showHoliday"); --