Add option to specify a timezone for events (#2623)

* Add option to specify a timezone for events

* Amend message, update docs
pull/2628/head
Denis Papec 11 months ago committed by GitHub
parent 674d7f2e01
commit 1f2081af5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,6 +27,7 @@ widget:
url: https://domain.url/with/link/to.ics # URL with calendar events url: https://domain.url/with/link/to.ics # URL with calendar events
name: My Events # required - name for these calendar events name: My Events # required - name for these calendar events
color: zinc # optional - defaults to pre-defined color for the service (zinc for ical) color: zinc # optional - defaults to pre-defined color for the service (zinc for ical)
timezone: America/Los_Angeles # optional - force timezone for events (if it's the same - no change, if missing or different in ical - will be converted to this timezone)
params: # optional - additional params for the service params: # optional - additional params for the service
showName: true # optional - show name before event title in event line - defaults to false showName: true # optional - show name before event title in event line - defaults to false
``` ```

@ -2,7 +2,7 @@ import { DateTime } from "luxon";
import classNames from "classnames"; import classNames from "classnames";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import Event from "./event"; import Event, { compareDateTimezoneAware } from "./event";
export default function Agenda({ service, colorVariants, events, showDate }) { export default function Agenda({ service, colorVariants, events, showDate }) {
const { widget } = service; const { widget } = service;
@ -15,8 +15,10 @@ export default function Agenda({ service, colorVariants, events, showDate }) {
const eventsArray = Object.keys(events) const eventsArray = Object.keys(events)
.filter( .filter(
(eventKey) => (eventKey) =>
showDate.minus({ days: widget?.previousDays ?? 0 }).startOf("day").ts <= showDate
events[eventKey].date?.startOf("day").ts, .setZone(events[eventKey].date.zoneName)
.minus({ days: widget?.previousDays ?? 0 })
.startOf("day").ts <= events[eventKey].date?.startOf("day").ts,
) )
.map((eventKey) => events[eventKey]) .map((eventKey) => events[eventKey])
.sort((a, b) => a.date - b.date) .sort((a, b) => a.date - b.date)
@ -56,7 +58,7 @@ export default function Agenda({ service, colorVariants, events, showDate }) {
event={event} event={event}
colorVariants={colorVariants} colorVariants={colorVariants}
showDate={j === 0} showDate={j === 0}
showTime={widget?.showTime && event.date.startOf("day").ts === showDate.startOf("day").ts} showTime={widget?.showTime && compareDateTimezoneAware(showDate, event)}
/> />
))} ))}
</div> </div>

@ -39,3 +39,7 @@ export default function Event({ event, colorVariants, showDate = false, showTime
</div> </div>
); );
} }
export function compareDateTimezoneAware(date, event) {
return date.setZone(event.date.zoneName).startOf("day").valueOf() === event.date.startOf("day").valueOf();
}

@ -23,8 +23,9 @@ export default function Integration({ config, params, setEvents, hideErrors }) {
} }
} }
const startDate = DateTime.fromISO(params.start); const zone = config?.timezone || null;
const endDate = DateTime.fromISO(params.end); const startDate = DateTime.fromISO(params.start, { zone });
const endDate = DateTime.fromISO(params.end, { zone });
if (icalError || !parsedIcal || !startDate.isValid || !endDate.isValid) { if (icalError || !parsedIcal || !startDate.isValid || !endDate.isValid) {
return; return;
@ -43,12 +44,15 @@ export default function Integration({ config, params, setEvents, hideErrors }) {
const duration = event.dtend.value - event.dtstart.value; const duration = event.dtend.value - event.dtstart.value;
const days = duration / (1000 * 60 * 60 * 24); const days = duration / (1000 * 60 * 60 * 24);
const now = DateTime.now().setZone(zone);
const eventDate = DateTime.fromJSDate(date, { zone });
for (let j = 0; j < days; j += 1) { for (let j = 0; j < days; j += 1) {
eventsToAdd[`${event?.uid?.value}${i}${j}${type}`] = { eventsToAdd[`${event?.uid?.value}${i}${j}${type}`] = {
title, title,
date: DateTime.fromJSDate(date).plus({ days: j }), date: eventDate.plus({ days: j }),
color: config?.color ?? "zinc", color: config?.color ?? "zinc",
isCompleted: DateTime.fromJSDate(date) < DateTime.now(), isCompleted: eventDate < now,
additional: event.location?.value, additional: event.location?.value,
type: "ical", type: "ical",
}; };

@ -3,7 +3,7 @@ import { DateTime, Info } from "luxon";
import classNames from "classnames"; import classNames from "classnames";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import Event from "./event"; import Event, { compareDateTimezoneAware } from "./event";
const cellStyle = "relative w-10 flex items-center justify-center flex-col"; const cellStyle = "relative w-10 flex items-center justify-center flex-col";
const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer"; const monthButton = "pl-6 pr-6 ml-2 mr-2 hover:bg-theme-100/20 dark:hover:bg-white/5 rounded-md cursor-pointer";
@ -12,9 +12,7 @@ export function Day({ weekNumber, weekday, events, colorVariants, showDate, setS
const currentDate = DateTime.now(); const currentDate = DateTime.now();
const cellDate = showDate.set({ weekday, weekNumber }).startOf("day"); const cellDate = showDate.set({ weekday, weekNumber }).startOf("day");
const filteredEvents = events?.filter( const filteredEvents = events?.filter((event) => compareDateTimezoneAware(cellDate, event));
(event) => event.date?.startOf("day").toUnixInteger() === cellDate.toUnixInteger(),
);
const dayStyles = (displayDate) => { const dayStyles = (displayDate) => {
let style = "h-9 "; let style = "h-9 ";
@ -173,7 +171,7 @@ export default function Monthly({ service, colorVariants, events, showDate, setS
<div className="flex flex-col"> <div className="flex flex-col">
{eventsArray {eventsArray
?.filter((event) => showDate.startOf("day").ts === event.date?.startOf("day").ts) ?.filter((event) => compareDateTimezoneAware(showDate, event))
.slice(0, widget?.maxEvents ?? 10) .slice(0, widget?.maxEvents ?? 10)
.map((event) => ( .map((event) => (
<Event <Event
@ -181,7 +179,7 @@ export default function Monthly({ service, colorVariants, events, showDate, setS
event={event} event={event}
colorVariants={colorVariants} colorVariants={colorVariants}
showDateColumn={widget?.showTime ?? false} showDateColumn={widget?.showTime ?? false}
showTime={widget?.showTime && event.date.startOf("day").ts === showDate.startOf("day").ts} showTime={widget?.showTime && compareDateTimezoneAware(showDate, event)}
/> />
))} ))}
</div> </div>

Loading…
Cancel
Save