[#78] added valarm support

This commit is contained in:
Camille Moussu
2025-09-08 17:35:16 +02:00
parent 18413ab203
commit b87b77beef
6 changed files with 83 additions and 34 deletions
+10 -2
View File
@@ -56,9 +56,10 @@ export const getCalendarDetailAsync = createAsyncThunk<
const events: CalendarEvent[] = calendar._embedded["dav:item"].flatMap( const events: CalendarEvent[] = calendar._embedded["dav:item"].flatMap(
(eventdata: any) => { (eventdata: any) => {
const vevents = eventdata.data[2] as any[][]; // array of ['vevent', RawEntry[], []] const vevents = eventdata.data[2] as any[][]; // array of ['vevent', RawEntry[], []]
const valarm = eventdata.data[2][0][2][0];
const eventURL = eventdata._links.self.href; const eventURL = eventdata._links.self.href;
return vevents.map((vevent: any[]) => { return vevents.map((vevent: any[]) => {
return parseCalendarEvent(vevent[1], color, calId, eventURL); return parseCalendarEvent(vevent[1], color, calId, eventURL, valarm);
}); });
} }
); );
@@ -88,8 +89,15 @@ export const putEventAsync = createAsyncThunk<
(eventdata: any) => { (eventdata: any) => {
const vevents = eventdata.data[2] as any[][]; const vevents = eventdata.data[2] as any[][];
const eventURL = eventdata._links.self.href; const eventURL = eventdata._links.self.href;
const valarm = eventdata.data[3][0][1];
return vevents.map((vevent: any[]) => { return vevents.map((vevent: any[]) => {
return parseCalendarEvent(vevent[1], cal.color ?? "", cal.id, eventURL); return parseCalendarEvent(
vevent[1],
cal.color ?? "",
cal.id,
eventURL,
valarm
);
}); });
} }
); );
+2 -2
View File
@@ -16,10 +16,10 @@ export async function getEvent(event: CalendarEvent) {
return { ...eventjson, ...event }; return { ...eventjson, ...event };
} }
export async function putEvent(event: CalendarEvent) { export async function putEvent(event: CalendarEvent, calOwnerEmail?: string) {
const response = await api(`dav${event.URL}`, { const response = await api(`dav${event.URL}`, {
method: "PUT", method: "PUT",
body: JSON.stringify(calendarEventToJCal(event)), body: JSON.stringify(calendarEventToJCal(event, calOwnerEmail)),
headers: { headers: {
"content-type": "text/calendar; charset=utf-8", "content-type": "text/calendar; charset=utf-8",
}, },
+26 -26
View File
@@ -91,7 +91,7 @@ export default function EventDisplayModal({
const [repetition, setRepetition] = useState<RepetitionObject>( const [repetition, setRepetition] = useState<RepetitionObject>(
event.repetition ?? ({} as RepetitionObject) event.repetition ?? ({} as RepetitionObject)
); );
const [alarm, setAlarm] = useState(""); const [alarm, setAlarm] = useState(event.alarm.trigger);
const [busy, setBusy] = useState(""); const [busy, setBusy] = useState("");
const [eventClass, setEventClass] = useState(event?.class ?? "PUBLIC"); const [eventClass, setEventClass] = useState(event?.class ?? "PUBLIC");
const [timezone, setTimezone] = useState(event?.timezone ?? "UTC"); const [timezone, setTimezone] = useState(event?.timezone ?? "UTC");
@@ -160,6 +160,7 @@ export default function EventDisplayModal({
attendee: [organizer, ...attendees], attendee: [organizer, ...attendees],
transp: "OPAQUE", transp: "OPAQUE",
color: userPersonnalCalendars[calendarid]?.color, color: userPersonnalCalendars[calendarid]?.color,
alarm: { trigger: alarm, action: "EMAIL" },
}; };
const [baseId, recurrenceId] = event.uid.split("/"); const [baseId, recurrenceId] = event.uid.split("/");
@@ -471,31 +472,30 @@ export default function EventDisplayModal({
isOwn={isOwn} isOwn={isOwn}
/> />
<FormControl fullWidth margin="dense" size="small"> <FormControl fullWidth margin="dense" size="small">
<InputLabel id="alarm">Alarm</InputLabel> <InputLabel id="alarm">Alarm</InputLabel>
<Select <Select
labelId="alarm" labelId="alarm"
value={alarm} label="Alarm"
disabled={!isOwn} value={alarm}
onChange={(e: SelectChangeEvent) => disabled={!isOwn}
setAlarm(e.target.value) onChange={(e: SelectChangeEvent) => setAlarm(e.target.value)}
} >
> <MenuItem value={""}>No Alarm</MenuItem>
<MenuItem value={""}>No Alarm</MenuItem> <MenuItem value={"-PT1M"}>1 minute</MenuItem>
<MenuItem value={"-PT1M"}>1 minute</MenuItem> <MenuItem value={"-PT5M"}>2 minutes</MenuItem>
<MenuItem value={"-PT5M"}>2 minutes</MenuItem> <MenuItem value={"-PT10M"}>10 minutes</MenuItem>
<MenuItem value={"-PT10M"}>10 minutes</MenuItem> <MenuItem value={"-PT15M"}>15 minutes</MenuItem>
<MenuItem value={"-PT15M"}>15 minutes</MenuItem> <MenuItem value={"-PT30M"}>30 minutes</MenuItem>
<MenuItem value={"-PT30M"}>30 minutes</MenuItem> <MenuItem value={"-PT1H"}>1 hours</MenuItem>
<MenuItem value={"-PT1H"}>1 hours</MenuItem> <MenuItem value={"-PT2H"}>2 hours</MenuItem>
<MenuItem value={"-PT2H"}>2 hours</MenuItem> <MenuItem value={"-PT5H"}>5 hours</MenuItem>
<MenuItem value={"-PT5H"}>5 hours</MenuItem> <MenuItem value={"-PT12H"}>12 hours</MenuItem>
<MenuItem value={"-PT12H"}>12 hours</MenuItem> <MenuItem value={"-PT1D"}>1 day</MenuItem>
<MenuItem value={"-PT1D"}>1 day</MenuItem> <MenuItem value={"-PT2D"}>2 days</MenuItem>
<MenuItem value={"-PT2D"}>2 days</MenuItem> <MenuItem value={"-PT1W"}>1 week</MenuItem>
<MenuItem value={"-PT1W"}>1 week</MenuItem> </Select>
</Select> </FormControl>
</FormControl>
<FormControl fullWidth margin="dense" size="small"> <FormControl fullWidth margin="dense" size="small">
<InputLabel id="Visibility">Visibility</InputLabel> <InputLabel id="Visibility">Visibility</InputLabel>
+1
View File
@@ -117,6 +117,7 @@ function EventPopover({
], ],
transp: "OPAQUE", transp: "OPAQUE",
color: userPersonnalCalendars[calendarid]?.color, color: userPersonnalCalendars[calendarid]?.color,
alarm: { trigger: alarm, action: "EMAIL" },
}; };
if (end) { if (end) {
newEvent.end = new Date(end); newEvent.end = new Date(end);
+6
View File
@@ -22,6 +22,7 @@ export interface CalendarEvent {
status?: string; status?: string;
timezone: string; timezone: string;
repetition?: RepetitionObject; repetition?: RepetitionObject;
alarm: AlarmObject;
} }
export interface RepetitionObject { export interface RepetitionObject {
@@ -31,3 +32,8 @@ export interface RepetitionObject {
occurrences?: number; occurrences?: number;
endDate?: string; endDate?: string;
} }
export interface AlarmObject {
trigger: string;
action: string;
}
+38 -4
View File
@@ -1,6 +1,6 @@
import { Calendars } from "../Calendars/CalendarTypes"; import { Calendars } from "../Calendars/CalendarTypes";
import { userAttendee } from "../User/userDataTypes"; import { userAttendee } from "../User/userDataTypes";
import { CalendarEvent } from "./EventsTypes"; import { AlarmObject, CalendarEvent } from "./EventsTypes";
import ICAL from "ical.js"; import ICAL from "ical.js";
import { TIMEZONES } from "../../utils/timezone-data"; import { TIMEZONES } from "../../utils/timezone-data";
type RawEntry = [string, Record<string, string>, string, any]; type RawEntry = [string, Record<string, string>, string, any];
@@ -9,7 +9,8 @@ export function parseCalendarEvent(
data: RawEntry[], data: RawEntry[],
color: string, color: string,
calendarid: string, calendarid: string,
eventURL: string eventURL: string,
valarm?: RawEntry[]
): CalendarEvent { ): CalendarEvent {
const event: Partial<CalendarEvent> = { color, attendee: [] }; const event: Partial<CalendarEvent> = { color, attendee: [] };
let recurrenceId; let recurrenceId;
@@ -103,6 +104,21 @@ export function parseCalendarEvent(
event.uid = `${event.uid}/${recurrenceId}`; event.uid = `${event.uid}/${recurrenceId}`;
} }
if (valarm) {
console.log(valarm);
event.alarm = {} as AlarmObject;
for (const [key, params, type, value] of valarm[1]) {
switch (key.toLowerCase()) {
case "action":
event.alarm.action = value;
break;
case "trigger":
event.alarm.trigger = value;
break;
}
}
}
event.URL = eventURL; event.URL = eventURL;
if (!event.uid || !event.start) { if (!event.uid || !event.start) {
console.error( console.error(
@@ -115,7 +131,10 @@ export function parseCalendarEvent(
return event as CalendarEvent; return event as CalendarEvent;
} }
export function calendarEventToJCal(event: CalendarEvent): any[] { export function calendarEventToJCal(
event: CalendarEvent,
calOwnerEmail?: string
): any[] {
const tzid = event.timezone; // Fallback to UTC if no timezone provided const tzid = event.timezone; // Fallback to UTC if no timezone provided
const vevent: any[] = [ const vevent: any[] = [
@@ -138,8 +157,23 @@ export function calendarEventToJCal(event: CalendarEvent): any[] {
], ],
["summary", {}, "text", event.title ?? ""], ["summary", {}, "text", event.title ?? ""],
], ],
[],
]; ];
if (event.alarm) {
const valarm = [
["trigger", {}, "duration", event.alarm.trigger],
["action", {}, "text", event.alarm.action],
["attendee", {}, "cal-address", `mailto:${calOwnerEmail}`],
["summary", {}, "text", event.title],
[
"description",
{},
"text",
"This is an automatic alarm sent by OpenPaas",
],
];
vevent.push([["valarm", valarm]]);
}
vevent.push([]);
if (event.end) { if (event.end) {
if (event.allday && event.end.getTime() === event.start.getTime()) { if (event.allday && event.end.getTime() === event.start.getTime()) {