mirror of
				https://github.com/karl0ss/homepage.git
				synced 2025-11-04 08:20:58 +00:00 
			
		
		
		
	Add option to specify a timezone for events (#2623)
* Add option to specify a timezone for events * Amend message, update docs
This commit is contained in:
		
							parent
							
								
									674d7f2e01
								
							
						
					
					
						commit
						1f2081af5d
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user