Files
workavia-calendar-front/src/features/Events/utils/parseCalendarEvent.ts
T
Camille Moussu a9e7b1ac82 [refactor] preparation for PR adressing #638 (#644)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2026-03-17 09:32:27 +01:00

217 lines
6.4 KiB
TypeScript

import { convertEventDateTimeToISO } from "@/utils/timezone";
import moment from "moment-timezone";
import { Calendar } from "../../Calendars/CalendarTypes";
import {
RepetitionRule,
VCalComponent,
VObjectProperty,
} from "../../Calendars/types/CalendarData";
import { userAttendee } from "../../User/models/attendee";
import { createAttendee } from "../../User/models/attendee.mapper";
import { AlarmObject, CalendarEvent } from "../EventsTypes";
import { inferTimezoneFromValue } from "./inferTimezoneFromValue";
import { buildDelegatedEventURL } from "./buildDelegatedEventURL";
import { formatDateToICal } from "./formatDateToICal";
export function parseCalendarEvent(
data: VObjectProperty[],
color: Record<string, string>,
calendar: Calendar,
eventURL: string,
valarm?: VCalComponent
): CalendarEvent {
const event: Partial<CalendarEvent> = { color, attendee: [] };
let recurrenceId;
let duration;
const dateRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
for (const [key, params, , value] of data) {
switch (key.toLowerCase()) {
case "uid":
event.uid = String(value);
break;
case "transp":
event.transp = String(value);
break;
case "dtstart": {
event.start = String(value);
const detectedTz = inferTimezoneFromValue(
params as Record<string, string>
);
if (detectedTz) {
event.timezone = detectedTz;
}
if (dateRegex.test(String(value))) {
event.allday = true;
} else {
event.allday = false;
}
break;
}
case "dtend": {
event.end = String(value);
if (!event.timezone) {
const detectedTz = inferTimezoneFromValue(
params as Record<string, string>
);
if (detectedTz) {
event.timezone = detectedTz;
}
}
if (dateRegex.test(String(value))) {
event.allday = true;
} else {
event.allday = false;
}
break;
}
case "class":
if (
["PRIVATE", "PUBLIC", "CONFIDENTIAL"].includes(
String(value).toUpperCase()
)
) {
event.class = String(value).toUpperCase() as CalendarEvent["class"];
}
break;
case "x-openpaas-videoconference":
event.x_openpass_videoconference = String(value);
break;
case "summary":
event.title = String(value);
break;
case "description":
event.description = String(value);
break;
case "location":
event.location = String(value);
break;
case "organizer": {
const paramsObj = params as Record<string, string>;
event.organizer = {
cn: paramsObj?.cn ?? "",
cal_address: String(value).replace(/^mailto:/i, ""),
};
break;
}
case "attendee": {
const paramsObj = params as Record<string, string>;
if (
!event.attendee?.find(
(attendee) =>
attendee.cal_address === String(value).replace(/^mailto:/i, "")
)
) {
(event.attendee as userAttendee[]).push(
createAttendee({
cn: paramsObj?.cn,
cal_address: String(value).replace(/^mailto:/i, ""),
partstat: paramsObj?.partstat as userAttendee["partstat"],
rsvp: paramsObj?.rsvp as userAttendee["rsvp"],
role: paramsObj?.role as userAttendee["role"],
cutype: paramsObj?.cutype as userAttendee["cutype"],
})
);
}
break;
}
case "dtstamp":
event.stamp = String(value);
break;
case "sequence":
event.sequence = Number(value);
break;
case "recurrence-id":
recurrenceId = String(value);
break;
case "exdate":
if (!event.exdates) event.exdates = [];
event.exdates.push(String(value));
break;
case "status":
event.status = String(value);
break;
case "duration":
duration = String(value);
break;
case "rrule": {
const ruleValue = value as RepetitionRule;
event.repetition = { freq: ruleValue.freq.toLowerCase() };
if (ruleValue.byday) {
if (typeof ruleValue.byday === "string") {
event.repetition.byday = [ruleValue.byday];
} else {
event.repetition.byday = ruleValue.byday;
}
}
if (ruleValue.until) {
event.repetition.endDate = ruleValue.until;
}
if (ruleValue.count) {
event.repetition.occurrences = ruleValue.count;
}
if (ruleValue.interval) {
event.repetition.interval = ruleValue.interval;
}
break;
}
}
}
if (recurrenceId && event.uid) {
event.uid = `${event.uid}/${recurrenceId}`;
event.recurrenceId = recurrenceId;
}
if (valarm) {
event.alarm = {} as AlarmObject;
for (const [key, , , value] of valarm[1]) {
switch (key.toLowerCase()) {
case "action":
event.alarm.action = String(value);
break;
case "trigger":
event.alarm.trigger = String(value);
break;
}
}
}
event.calId = calendar.id;
event.URL = calendar.delegated
? buildDelegatedEventURL(calendar, eventURL)
: eventURL;
if (!event.uid || !event.start) {
console.error(
`missing crucial event param in calendar ${calendar.id} `,
data
);
event.error = `missing crucial event param in calendar ${calendar.id} `;
}
const eventTimezone = event.timezone;
if (!event.end) {
const start = event.start ? new Date(event.start) : new Date();
const timeToAdd = duration
? moment.duration(duration).asMilliseconds()
: moment.duration(30, "minutes").asMilliseconds();
const artificialEnd = new Date(start.getTime() + timeToAdd);
event.end = formatDateToICal(artificialEnd, false, eventTimezone);
}
if (!event.allday && event.start && eventTimezone) {
const startISO = convertEventDateTimeToISO(event.start, eventTimezone);
if (startISO) {
event.start = startISO;
}
}
if (!event.allday && event.end && eventTimezone) {
const endISO = convertEventDateTimeToISO(event.end, eventTimezone);
if (endISO) {
event.end = endISO;
}
}
return event as CalendarEvent;
}