From e86fa9d24acc42038a0fc1a54a3b3fada31d3df1 Mon Sep 17 00:00:00 2001 From: Johan Alvinger Date: Mon, 23 Nov 2020 21:48:34 +0100 Subject: [PATCH] Revised handling of timeFormat "absolute" and "relative". Added new option "coloredEvents" which contain an array with keyword and color for coloring events matching keyword --- modules/default/calendar/calendar.js | 165 ++++++++++++++------------- 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 784e1b9a..0063b5c8 100755 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -38,6 +38,7 @@ Module.register("calendar", { hideOngoing: false, colored: false, coloredSymbolOnly: false, + coloredEvents: [], // Array of Keyword/Color where Keyword is a regexp and color the color code to use when regexp matches tableClass: "small", calendars: [ { @@ -155,6 +156,12 @@ Module.register("calendar", { // Override dom generator. getDom: function () { + // Define second, minute, hour, and day constants + const oneSecond = 1000; // 1,000 milliseconds + const oneMinute = oneSecond * 60; + const oneHour = oneMinute * 60; + const oneDay = oneHour * 24; + var events = this.createEventList(); var wrapper = document.createElement("table"); wrapper.className = this.config.tableClass; @@ -250,6 +257,17 @@ Module.register("calendar", { } } + if (this.config.coloredEvents.length > 0) { + for (var ev in this.config.coloredEvents) { + var needle = new RegExp(this.config.coloredEvents[ev].keyword, "gi"); + if (needle.test(event.title)) { + eventWrapper.style.cssText = "color:" + this.config.coloredEvents[ev].color; + titleWrapper.style.cssText = "color:" + this.config.coloredEvents[ev].color; + break; + } + } + } + titleWrapper.innerHTML = this.titleTransform(event.title, this.config.titleReplace, this.config.wrapEvents, this.config.maxTitleLength, this.config.maxTitleLines) + repeatingCountTitle; var titleClass = this.titleClassForUrl(event.url); @@ -282,82 +300,56 @@ Module.register("calendar", { eventWrapper.appendChild(titleWrapper); var now = new Date(); - // Define second, minute, hour, and day variables - var oneSecond = 1000; // 1,000 milliseconds - var oneMinute = oneSecond * 60; - var oneHour = oneMinute * 60; - var oneDay = oneHour * 24; - if (event.fullDayEvent) { - //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day - event.endDate -= oneSecond; - if (event.today) { - timeWrapper.innerHTML = this.capFirst(this.translate("TODAY")); - } else if (event.startDate - now < oneDay && event.startDate - now > 0) { - timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW")); - } else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) { - if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { - timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); - } else { + + if (this.config.timeFormat === "absolute") { + // Use dateFormat + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); + // Add end time if showEnd + if (this.config.showEnd) { + timeWrapper.innerHTML += "-"; + timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); + } + // For full day events we use the fullDayEventDateFormat + if (event.fullDayEvent) { + //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day + event.endDate -= oneSecond; + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat)); + } + if (this.config.getRelative > 0 && event.startDate >= now) { + // Ongoing and getRelative is set + timeWrapper.innerHTML = this.capFirst( + this.translate("RUNNING", { + fallback: this.translate("RUNNING") + " {timeUntilEnd}", + timeUntilEnd: moment(event.endDate, "x").fromNow(true) + }) + ); + } else if (this.config.urgency > 0 && event.startDate - now < this.config.urgency * oneDay) { + // Within urgency days + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); + } + if (event.fullDayEvent && this.config.nextDaysRelative) { + // Full days events within the next two days + if (event.today) { + timeWrapper.innerHTML = this.capFirst(this.translate("TODAY")); + } else if (event.startDate - now < oneDay && event.startDate - now > 0) { + timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW")); + } else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) { + if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { + timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); + } + } + } + } else { + // Show relative times + if (event.startDate >= now) { + // Use relative time + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar()); + if (event.startDate - now < this.config.getRelative * oneHour) { + // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow() timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } else { - /* Check to see if the user displays absolute or relative dates with their events - * Also check to see if an event is happening within an 'urgency' time frameElement - * For example, if the user set an .urgency of 7 days, those events that fall within that - * time frame will be displayed with 'in xxx' time format or moment.fromNow() - * - * Note: this needs to be put in its own function, as the whole thing repeats again verbatim - */ - if (this.config.timeFormat === "absolute") { - if (this.config.urgency > 1 && event.startDate - now < this.config.urgency * oneDay) { - // This event falls within the config.urgency period that the user has set - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD"))); - } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat)); - } - } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD"))); - } - } - if (this.config.showEnd) { - timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.fullDayEventDateFormat)); - } - } else { - if (event.startDate >= new Date()) { - if (event.startDate - now < 2 * oneDay) { - // This event is within the next 48 hours (2 days) - if (event.startDate - now < this.config.getRelative * oneHour) { - // If event is within 6 hour, display 'in xxx' time format or moment.fromNow() - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); - } else { - if (this.config.timeFormat === "absolute" && !this.config.nextDaysRelative) { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); - } else { - // Otherwise just say 'Today/Tomorrow at such-n-such time' - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar()); - } - } - } else { - /* Check to see if the user displays absolute or relative dates with their events - * Also check to see if an event is happening within an 'urgency' time frameElement - * For example, if the user set an .urgency of 7 days, those events that fall within that - * time frame will be displayed with 'in xxx' time format or moment.fromNow() - * - * Note: this needs to be put in its own function, as the whole thing repeats again verbatim - */ - if (this.config.timeFormat === "absolute") { - if (this.config.urgency > 1 && event.startDate - now < this.config.urgency * oneDay) { - // This event falls within the config.urgency period that the user has set - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); - } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); - } - } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); - } - } - } else { + // Ongoing event timeWrapper.innerHTML = this.capFirst( this.translate("RUNNING", { fallback: this.translate("RUNNING") + " {timeUntilEnd}", @@ -365,12 +357,7 @@ Module.register("calendar", { }) ); } - if (this.config.showEnd) { - timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); - } } - //timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll'); timeWrapper.className = "time light " + this.timeClassForUrl(event.url); eventWrapper.appendChild(timeWrapper); } @@ -524,13 +511,31 @@ Module.register("calendar", { return a.startDate - b.startDate; }); + // Limit the number of days displayed // If limitDays is set > 0, limit display to that number of days if (this.config.limitDays > 0) { + var newEvents = []; var lastDate = today.clone().subtract(1, "days").format("YYYYMMDD"); var days = 0; - var newevents = []; - for (var e in events) { + for (var e of events) { + eventDate = moment(e.startDate, "x").format("YYYYMMDD"); + // if date of event is later than lastdate + // check if we already are showing max unique days + if (eventDate > lastDate) { + // if the only entry in the first day is a full day event that day is not counted as unique + if (newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) { + days--; + } + days++; + if (days > this.config.limitDays) { + continue; + } else { + lastDate = eventDate; + } + } + newEvents.push(e); } + events = newEvents; } return events.slice(0, this.config.maximumEntries);