This implements a basic CalDav UI, titled "Calendar". It allows creating new calendars and events with a start and end date, URL, location, and description. You can also import and export ICS (VCALENDAR + VEVENT) files. It allows editing the ICS directly, for power users. Additionally, you can hide/display events from certain calendars, change their names and their colors. If there's no calendar created yet in your CalDav server (first-time setup), it'll automatically create one, titled "Calendar". You can also change the display timezone for the calendar from the settings. Finally, there's some minor documentation fixes and some other minor tweaks. Closes #56 Closes #89
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import { Handlers } from 'fresh/server.ts';
|
|
|
|
import { FreshContextState } from '/lib/types.ts';
|
|
import { CalendarEvent, CalendarEventModel } from '/lib/models/calendar.ts';
|
|
|
|
interface Data {}
|
|
|
|
export interface RequestBody {
|
|
calendarIds: string[];
|
|
searchTerm: string;
|
|
}
|
|
|
|
export interface ResponseBody {
|
|
success: boolean;
|
|
matchingCalendarEvents: CalendarEvent[];
|
|
}
|
|
|
|
export const handler: Handlers<Data, FreshContextState> = {
|
|
async POST(request, context) {
|
|
if (!context.state.user) {
|
|
return new Response('Unauthorized', { status: 401 });
|
|
}
|
|
|
|
const requestBody = await request.clone().json() as RequestBody;
|
|
|
|
if (
|
|
!requestBody.calendarIds || !requestBody.searchTerm
|
|
) {
|
|
return new Response('Bad Request', { status: 400 });
|
|
}
|
|
|
|
const allCalendarEvents = await CalendarEventModel.list(
|
|
context.state.user.id,
|
|
requestBody.calendarIds,
|
|
);
|
|
|
|
const lowerSearchTerm = requestBody.searchTerm.toLowerCase();
|
|
|
|
const matchingCalendarEvents = allCalendarEvents.filter((calendarEvent) =>
|
|
calendarEvent.title.toLowerCase().includes(lowerSearchTerm) ||
|
|
calendarEvent.description?.toLowerCase().includes(lowerSearchTerm) ||
|
|
calendarEvent.location?.toLowerCase().includes(lowerSearchTerm) ||
|
|
calendarEvent.eventUrl?.toLowerCase().includes(lowerSearchTerm) ||
|
|
calendarEvent.organizerEmail?.toLowerCase().includes(lowerSearchTerm) ||
|
|
calendarEvent.attendees?.some((attendee) => attendee.email.toLowerCase().includes(lowerSearchTerm)) ||
|
|
calendarEvent.reminders?.some((reminder) => reminder.description?.toLowerCase().includes(lowerSearchTerm))
|
|
).sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
|
|
|
|
const responseBody: ResponseBody = { success: true, matchingCalendarEvents };
|
|
|
|
return new Response(JSON.stringify(responseBody));
|
|
},
|
|
};
|