From e24dfa6b1ae63710c13d913109996c701a986759 Mon Sep 17 00:00:00 2001 From: "CarJem Generations (Carter Wallace)" Date: Wed, 15 Feb 2023 15:53:24 -0500 Subject: [PATCH] Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter --- CHANGELOG.md | 1 + modules/default/calendar/calendar.js | 87 ++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78060d8c..67c0ae3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not al ### Added +- Added new calendar options for colored entries and improved styling (#3033) - Added test for remoteFile option in compliments module - Added hourlyWeather functionality to Weather.gov weather provider - Removed weatherEndpoint definition from weathergov.js (not used) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 762d4b9d..917437de 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -40,7 +40,6 @@ Module.register("calendar", { hideTime: false, showTimeToday: false, colored: false, - coloredSymbolOnly: false, customEvents: [], // Array of {keyword: "", symbol: "", color: ""} where Keyword is a regexp and symbol/color are to be applied for matched tableClass: "small", calendars: [ @@ -61,7 +60,13 @@ Module.register("calendar", { sliceMultiDayEvents: false, broadcastPastEvents: false, nextDaysRelative: false, - selfSignedCert: false + selfSignedCert: false, + coloredText: false, + coloredBorder: false, + coloredSymbol: false, + coloredBackground: false, + limitDaysNeverSkip: false, + flipDateHeaderTitle: false }, requiresVersion: "2.1.0", @@ -90,6 +95,17 @@ Module.register("calendar", { Log.info("Starting module: " + this.name); + if (this.config.colored) { + Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!"); + this.config.coloredText = true; + this.config.coloredSymbol = true; + } + if (this.config.coloredSymbolOnly) { + Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!"); + this.config.coloredText = false; + this.config.coloredSymbol = true; + } + // Set locale. moment.updateLocale(config.language, this.getLocaleSpecification(config.timeFormat)); @@ -214,7 +230,7 @@ Module.register("calendar", { if (this.config.timeFormat === "dateheaders") { if (lastSeenDate !== dateAsString) { const dateRow = document.createElement("tr"); - dateRow.className = "normal"; + dateRow.className = "dateheader normal"; if (event.today) dateRow.className += " today"; else if (event.tomorrow) dateRow.className += " tomorrow"; @@ -237,19 +253,27 @@ Module.register("calendar", { const eventWrapper = document.createElement("tr"); - if (this.config.colored && !this.config.coloredSymbolOnly) { - eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url); + if (this.config.coloredText) { + eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url, false); } - eventWrapper.className = "normal event"; + if (this.config.coloredBackground) { + eventWrapper.style.backgroundColor = this.colorForUrl(event.url, true); + } + + if (this.config.coloredBorder) { + eventWrapper.style.borderColor = this.colorForUrl(event.url, false); + } + + eventWrapper.className = "event-wrapper normal event"; if (event.today) eventWrapper.className += " today"; else if (event.tomorrow) eventWrapper.className += " tomorrow"; const symbolWrapper = document.createElement("td"); if (this.config.displaySymbol) { - if (this.config.colored && this.config.coloredSymbolOnly) { - symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url); + if (this.config.coloredSymbol) { + symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url, false); } const symbolClass = this.symbolClassForUrl(event.url); @@ -281,7 +305,7 @@ Module.register("calendar", { const thisYear = new Date(parseInt(event.startDate)).getFullYear(), yearDiff = thisYear - event.firstYear; - repeatingCountTitle = ", " + yearDiff + repeatingCountTitle; + repeatingCountTitle = ", " + yearDiff + ". " + repeatingCountTitle; } } @@ -292,11 +316,11 @@ Module.register("calendar", { let needle = new RegExp(this.config.customEvents[ev].keyword, "gi"); if (needle.test(event.title)) { // Respect parameter ColoredSymbolOnly also for custom events - if (!this.config.coloredSymbolOnly) { + if (this.config.coloredText) { eventWrapper.style.cssText = "color:" + this.config.customEvents[ev].color; titleWrapper.style.cssText = "color:" + this.config.customEvents[ev].color; } - if (this.config.displaySymbol) { + if (this.config.displaySymbol && this.config.coloredSymbol) { symbolWrapper.style.cssText = "color:" + this.config.customEvents[ev].color; } break; @@ -309,32 +333,35 @@ Module.register("calendar", { const titleClass = this.titleClassForUrl(event.url); - if (!this.config.colored) { + if (!this.config.coloredText) { titleWrapper.className = "title bright " + titleClass; } else { titleWrapper.className = "title " + titleClass; } if (this.config.timeFormat === "dateheaders") { + if (this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); + if (event.fullDayEvent) { titleWrapper.colSpan = "2"; titleWrapper.classList.add("align-left"); } else { const timeWrapper = document.createElement("td"); - timeWrapper.className = "time light align-left " + this.timeClassForUrl(event.url); + timeWrapper.className = "time light " + (this.config.flipDateHeaderTitle ? "align-right " : "align-left ") + this.timeClassForUrl(event.url); timeWrapper.style.paddingLeft = "2px"; + timeWrapper.style.textAlign = this.config.flipDateHeaderTitle ? "right" : "left"; timeWrapper.innerHTML = moment(event.startDate, "x").format("LT"); // Add endDate to dataheaders if showEnd is enabled if (this.config.showEnd) { - timeWrapper.innerHTML += " - " + moment(event.endDate, "x").format("LT"); + timeWrapper.innerHTML += " - " + this.capFirst(moment(event.endDate, "x").format("LT")); } eventWrapper.appendChild(timeWrapper); - titleWrapper.classList.add("align-right"); - } - eventWrapper.appendChild(titleWrapper); + if (!this.config.flipDateHeaderTitle) titleWrapper.classList.add("align-right"); + } + if (!this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); } else { const timeWrapper = document.createElement("td"); @@ -423,18 +450,17 @@ Module.register("calendar", { eventWrapper.appendChild(timeWrapper); } - wrapper.appendChild(eventWrapper); - // Create fade effect. if (index >= startFade) { currentFadeStep = index - startFade; eventWrapper.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep; } + wrapper.appendChild(eventWrapper); if (this.config.showLocation) { if (event.location !== false) { const locationRow = document.createElement("tr"); - locationRow.className = "normal xsmall light"; + locationRow.className = "event-wrapper-location normal xsmall light"; if (event.today) locationRow.className += " today"; else if (event.tomorrow) locationRow.className += " tomorrow"; @@ -443,6 +469,18 @@ Module.register("calendar", { locationRow.appendChild(symbolCell); } + if (this.config.coloredText) { + locationRow.style.cssText = "color:" + this.colorForUrl(event.url, false); + } + + if (this.config.coloredBackground) { + locationRow.style.backgroundColor = this.colorForUrl(event.url, true); + } + + if (this.config.coloredBorder) { + locationRow.style.borderColor = this.colorForUrl(event.url, false); + } + const descCell = document.createElement("td"); descCell.className = "location"; descCell.colSpan = "2"; @@ -602,7 +640,7 @@ Module.register("calendar", { // 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) { + if (!this.config.limitDaysNeverSkip && newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) { days--; } days++; @@ -738,10 +776,11 @@ Module.register("calendar", { * Retrieves the color for a specific calendar url. * * @param {string} url The calendar url + * @param {boolean} isBg Determines if we fetch the bgColor or not * @returns {string} The color */ - colorForUrl: function (url) { - return this.getCalendarProperty(url, "color", "#fff"); + colorForUrl: function (url, isBg) { + return this.getCalendarProperty(url, isBg ? "bgColor" : "color", "#fff"); }, /** @@ -898,7 +937,7 @@ Module.register("calendar", { for (const event of eventList) { event.symbol = this.symbolsForEvent(event); event.calendarName = this.calendarNameForUrl(event.url); - event.color = this.colorForUrl(event.url); + event.color = this.colorForUrl(event.url, false); delete event.url; }