Move holidays to its own file, show holidays in all date selection calendars

This commit is contained in:
nathan 2022-04-29 11:35:04 -06:00
parent de2dade286
commit b44f4ea30d
4 changed files with 115 additions and 72 deletions

View File

@ -16,6 +16,10 @@ import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
import {dateStyles} from "./DateStyles"; import {dateStyles} from "./DateStyles";
import {LitFlatpickr} from "lit-flatpickr"; import {LitFlatpickr} from "lit-flatpickr";
import "flatpickr/dist/plugins/scrollPlugin.js"; import "flatpickr/dist/plugins/scrollPlugin.js";
import {holidays} from "./Holidays";
// Request this year's holidays now
holidays(new Date().getFullYear());
// list of existing localizations from node_modules/flatpicker/dist/l10n directory: // list of existing localizations from node_modules/flatpicker/dist/l10n directory:
const l10n = [ const l10n = [
@ -333,6 +337,8 @@ export class Et2Date extends Et2InputWidget(FormControlMixin(ValidateMixin(LitFl
constructor() constructor()
{ {
super(); super();
this._onDayCreate = this._onDayCreate.bind(this);
} }
@ -386,6 +392,8 @@ export class Et2Date extends Et2InputWidget(FormControlMixin(ValidateMixin(LitFl
options.dateFormat = "Y-m-dT00:00:00\\Z"; options.dateFormat = "Y-m-dT00:00:00\\Z";
options.weekNumbers = true; options.weekNumbers = true;
options.onDayCreate = this._onDayCreate;
this._localize(options); this._localize(options);
if(this.inline) if(this.inline)
@ -490,6 +498,63 @@ export class Et2Date extends Et2InputWidget(FormControlMixin(ValidateMixin(LitFl
this.modelValue = this.getValue(); this.modelValue = this.getValue();
} }
/**
* Customise date rendering
*
* @see https://flatpickr.js.org/events/
*
* @param {Date} dates Currently selected date(s)
* @param dStr a string representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option.
* @param inst flatpickr instance
* @param dayElement
* @protected
*/
protected _onDayCreate(dates : Date[], dStr : string, inst, dayElement : HTMLElement)
{
//@ts-ignore flatpickr adds dateObj to days
let date = new Date(dayElement.dateObj);
let f_date = new Date(date.valueOf() - date.getTimezoneOffset() * 60 * 1000);
if(!f_date)
{
return;
}
let set_holiday = function(holidays, element)
{
let day_holidays = holidays[formatDate(f_date, {dateFormat: "Ymd"})]
let tooltip = '';
if(typeof day_holidays !== 'undefined' && day_holidays.length)
{
for(var i = 0; i < day_holidays.length; i++)
{
if(typeof day_holidays[i]['birthyear'] !== 'undefined')
{
element.classList.add('calBirthday');
}
else
{
element.classList.add('calHoliday');
}
tooltip += day_holidays[i]['name'] + "\n";
}
}
if(tooltip)
{
this.egw().tooltipBind(element, tooltip);
}
}.bind(this);
let holiday_list = holidays(f_date.getFullYear());
if(holiday_list instanceof Promise)
{
holiday_list.then((h) => {set_holiday(h, dayElement);});
}
else
{
set_holiday(holiday_list, dayElement);
}
}
/** /**
* Set the minimum allowed date * Set the minimum allowed date
* @param {string | Date} min * @param {string | Date} min

View File

@ -0,0 +1,40 @@
/**
* Static holiday cache
* access through holidays(year)
*/
let _holiday_cache = {};
/**
* Get a list of holidays for the given year
*
* Returns either a list of holidays indexed by date, in Ymd format:
* {20001225: {day: 14, month: 2, occurence: 2021, name: "Valentinstag"}}
* or a promise that resolves with the list.
*
* No need to cache the results, we do it here.
*
* @param year
* @returns Promise | Object
*/
export function holidays(year) : Promise<Object> | {}
{
// No country selected causes error, so skip if it's missing
if(!egw.preference('country', 'common'))
{
return {};
}
if(typeof _holiday_cache[year] === 'undefined')
{
// Fetch with json instead of jsonq because there may be more than
// one widget listening for the response by the time it gets back,
// and we can't do that when it's queued.
_holiday_cache[year] = window.fetch(
egw.link('/calendar/holidays.php', {year: year})
).then((response) =>
{
return _holiday_cache[year] = response.json();
});
}
return _holiday_cache[year];
}

View File

@ -4017,6 +4017,15 @@ body .flatpickr-calendar {
display: none; display: none;
} }
.flatpickr-calendar.open {
z-index: 1000;
}
/** Holidays & birthdays **/
div.flatpickr-calendar .calHoliday, div.flatpickr-calendar .calBirthday {
background-color: rgba(103, 159, 210, 0.5);
}
/** Sizing for inline flatpickr, used in calendar sidebox **/ /** Sizing for inline flatpickr, used in calendar sidebox **/
div.flatpickr-calendar.inline { div.flatpickr-calendar.inline {
--dayWidth: calc((width - 80) / 7); --dayWidth: calc((width - 80) / 7);

View File

@ -1,6 +1,5 @@
import {Et2Date, formatDate, parseDate} from "../../api/js/etemplate/Et2Date/Et2Date"; import {Et2Date, parseDate} from "../../api/js/etemplate/Et2Date/Et2Date";
import {css} from "@lion/core"; import {css} from "@lion/core";
import {et2_calendar_view} from "./et2_widget_view";
import {CalendarApp} from "./app"; import {CalendarApp} from "./app";
export class SidemenuDate extends Et2Date export class SidemenuDate extends Et2Date
@ -36,8 +35,6 @@ export class SidemenuDate extends Et2Date
]; ];
} }
static _holidays : Object = null;
constructor() constructor()
{ {
super(); super();
@ -54,30 +51,6 @@ export class SidemenuDate extends Et2Date
this.removeEventListener("change", this._oldChange); this.removeEventListener("change", this._oldChange);
this.addEventListener("change", this._handleChange); this.addEventListener("change", this._handleChange);
if(null == SidemenuDate._holidays)
{
let holidays_or_promise = et2_calendar_view.get_holidays((new Date).getFullYear());
if(holidays_or_promise instanceof Promise)
{
holidays_or_promise.then(holidays =>
{
SidemenuDate._holidays = holidays;
if(this._instance)
{
// Already drawn without holidays so redraw
this._instance.redraw();
}
else
{
this.requestUpdate();
}
})
}
else
{
SidemenuDate._holidays = holidays_or_promise;
}
}
} }
disconnectedCallback() disconnectedCallback()
@ -140,7 +113,6 @@ export class SidemenuDate extends Et2Date
options.dateFormat = "Y-m-dT00:00:00\\Z"; options.dateFormat = "Y-m-dT00:00:00\\Z";
options.shorthandCurrentMonth = true; options.shorthandCurrentMonth = true;
options.onDayCreate = this._onDayCreate;
options.onMonthChange = this._updateGoButton; options.onMonthChange = this._updateGoButton;
options.nextArrow = ""; options.nextArrow = "";
@ -161,49 +133,6 @@ export class SidemenuDate extends Et2Date
} }
} }
/**
* Customise date rendering
*
* @see https://flatpickr.js.org/events/
*
* @param {Date} dates Currently selected date(s)
* @param dStr a string representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option.
* @param inst flatpickr instance
* @param dayElement
* @protected
*/
protected _onDayCreate(dates : Date[], dStr : string, inst, dayElement : HTMLElement)
{
//@ts-ignore flatpickr adds dateObj to days
let date = new Date(dayElement.dateObj);
let f_date = new Date(date.valueOf() - date.getTimezoneOffset() * 60 * 1000);
if(!f_date || SidemenuDate._holidays === null)
{
return;
}
let day_holidays = SidemenuDate._holidays[formatDate(f_date, {dateFormat: "Ymd"})]
var tooltip = '';
if(typeof day_holidays !== 'undefined' && day_holidays.length)
{
for(var i = 0; i < day_holidays.length; i++)
{
if(typeof day_holidays[i]['birthyear'] !== 'undefined')
{
dayElement.classList.add('calendar_calBirthday');
}
else
{
dayElement.classList.add('calendar_calHoliday');
}
tooltip += day_holidays[i]['name'] + "\n";
}
}
if(tooltip)
{
this.egw().tooltipBind(dayElement, tooltip);
}
}
/** /**
* Handler for change events. Re-bound to be able to cancel month changes, since it's an input and emits them * Handler for change events. Re-bound to be able to cancel month changes, since it's an input and emits them