Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user