Import Calendar Events
This commit is contained in:
@@ -15,7 +15,7 @@ export default function CalendarViewWeek(
|
|||||||
const today = new Date().toISOString().substring(0, 10);
|
const today = new Date().toISOString().substring(0, 10);
|
||||||
|
|
||||||
const hourFormat = new Intl.DateTimeFormat('en-GB', { hour12: false, hour: '2-digit', minute: '2-digit' });
|
const hourFormat = new Intl.DateTimeFormat('en-GB', { hour12: false, hour: '2-digit', minute: '2-digit' });
|
||||||
const weekDayFormat = new Intl.DateTimeFormat('en-GB', { weekday: 'short' });
|
const weekDayFormat = new Intl.DateTimeFormat('en-GB', { weekday: 'short', day: 'numeric', month: '2-digit' });
|
||||||
|
|
||||||
const days = getDaysForWeek(new Date(startDate));
|
const days = getDaysForWeek(new Date(startDate));
|
||||||
|
|
||||||
|
|||||||
81
components/calendar/ImportEventsModal.tsx
Normal file
81
components/calendar/ImportEventsModal.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { useSignal } from '@preact/signals';
|
||||||
|
import { useEffect } from 'preact/hooks';
|
||||||
|
|
||||||
|
import { Calendar } from '/lib/types.ts';
|
||||||
|
|
||||||
|
interface ImportEventsModalProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
calendars: Pick<Calendar, 'id' | 'name' | 'color'>[];
|
||||||
|
onClickImport: (calendarId: string) => void;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ImportEventsModal(
|
||||||
|
{ isOpen, calendars, onClickImport, onClose }: ImportEventsModalProps,
|
||||||
|
) {
|
||||||
|
const newCalendarId = useSignal<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isOpen) {
|
||||||
|
newCalendarId.value = null;
|
||||||
|
} else {
|
||||||
|
newCalendarId.value = calendars[0]!.id;
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section
|
||||||
|
class={`fixed ${isOpen ? 'block' : 'hidden'} z-40 w-screen h-screen inset-0 bg-gray-900 bg-opacity-60`}
|
||||||
|
>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
class={`fixed ${
|
||||||
|
newCalendarId.value ? 'block' : 'hidden'
|
||||||
|
} z-50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96 bg-slate-600 text-white rounded-md px-8 py-6 drop-shadow-lg`}
|
||||||
|
>
|
||||||
|
<h1 class='text-2xl font-semibold my-5'>Import Events</h1>
|
||||||
|
<section class='py-5 my-2 border-y border-slate-500'>
|
||||||
|
<fieldset class='block mb-2'>
|
||||||
|
<label class='text-slate-300 block pb-1' for='event_calendar'>Calendar</label>
|
||||||
|
<section class='flex items-center justify-between'>
|
||||||
|
<select
|
||||||
|
class='input-field mr-2'
|
||||||
|
name='event_calendar'
|
||||||
|
id='event_calendar'
|
||||||
|
value={newCalendarId.value || ''}
|
||||||
|
onChange={(event) => {
|
||||||
|
newCalendarId.value = event.currentTarget.value;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{calendars.map((calendar) => <option value={calendar.id}>{calendar.name}</option>)}
|
||||||
|
</select>
|
||||||
|
<span
|
||||||
|
class={`w-5 h-5 block ${
|
||||||
|
calendars.find((calendar) => calendar.id === newCalendarId.value)?.color
|
||||||
|
} rounded-full`}
|
||||||
|
title={calendars.find((calendar) => calendar.id === newCalendarId.value)?.color}
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
</fieldset>
|
||||||
|
</section>
|
||||||
|
<footer class='flex justify-between'>
|
||||||
|
<button
|
||||||
|
class='px-5 py-2 bg-slate-600 hover:bg-slate-500 text-white cursor-pointer rounded-md'
|
||||||
|
onClick={() => onClickImport(newCalendarId.value!)}
|
||||||
|
>
|
||||||
|
Choose File
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class='px-5 py-2 bg-slate-600 hover:bg-slate-500 text-white cursor-pointer rounded-md'
|
||||||
|
onClick={() => onClose()}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
import { useSignal } from '@preact/signals';
|
import { useSignal } from '@preact/signals';
|
||||||
|
|
||||||
import { Calendar, CalendarEvent } from '/lib/types.ts';
|
import { Calendar, CalendarEvent } from '/lib/types.ts';
|
||||||
import { baseUrl, capitalizeWord, formatCalendarEventsToVCalendar } from '/lib/utils.ts';
|
import {
|
||||||
|
baseUrl,
|
||||||
|
capitalizeWord,
|
||||||
|
formatCalendarEventsToVCalendar,
|
||||||
|
parseVCalendarFromTextContents,
|
||||||
|
} from '/lib/utils.ts';
|
||||||
import { RequestBody as GetRequestBody, ResponseBody as GetResponseBody } from '/routes/api/calendar/get-events.tsx';
|
import { RequestBody as GetRequestBody, ResponseBody as GetResponseBody } from '/routes/api/calendar/get-events.tsx';
|
||||||
import { RequestBody as AddRequestBody, ResponseBody as AddResponseBody } from '/routes/api/calendar/add-event.tsx';
|
import { RequestBody as AddRequestBody, ResponseBody as AddResponseBody } from '/routes/api/calendar/add-event.tsx';
|
||||||
import {
|
import {
|
||||||
RequestBody as DeleteRequestBody,
|
RequestBody as DeleteRequestBody,
|
||||||
ResponseBody as DeleteResponseBody,
|
ResponseBody as DeleteResponseBody,
|
||||||
} from '/routes/api/calendar/delete-event.tsx';
|
} from '/routes/api/calendar/delete-event.tsx';
|
||||||
// import { RequestBody as ImportRequestBody, ResponseBody as ImportResponseBody } from '/routes/api/calendar/import-events.tsx';
|
import { RequestBody as ImportRequestBody, ResponseBody as ImportResponseBody } from '/routes/api/calendar/import.tsx';
|
||||||
import CalendarViewDay from './CalendarViewDay.tsx';
|
import CalendarViewDay from './CalendarViewDay.tsx';
|
||||||
import CalendarViewWeek from './CalendarViewWeek.tsx';
|
import CalendarViewWeek from './CalendarViewWeek.tsx';
|
||||||
import CalendarViewMonth from './CalendarViewMonth.tsx';
|
import CalendarViewMonth from './CalendarViewMonth.tsx';
|
||||||
import AddEventModal, { NewCalendarEvent } from './AddEventModal.tsx';
|
import AddEventModal, { NewCalendarEvent } from './AddEventModal.tsx';
|
||||||
import ViewEventModal from './ViewEventModal.tsx';
|
import ViewEventModal from './ViewEventModal.tsx';
|
||||||
import SearchEvents from './SearchEvents.tsx';
|
import SearchEvents from './SearchEvents.tsx';
|
||||||
|
import ImportEventsModal from './ImportEventsModal.tsx';
|
||||||
|
|
||||||
interface MainCalendarProps {
|
interface MainCalendarProps {
|
||||||
initialCalendars: Pick<Calendar, 'id' | 'name' | 'color' | 'is_visible'>[];
|
initialCalendars: Pick<Calendar, 'id' | 'name' | 'color' | 'is_visible'>[];
|
||||||
@@ -38,6 +44,9 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
|
|||||||
const newEventModal = useSignal<{ isOpen: boolean; initialStartDate?: Date; initiallyAllDay?: boolean }>({
|
const newEventModal = useSignal<{ isOpen: boolean; initialStartDate?: Date; initiallyAllDay?: boolean }>({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
});
|
});
|
||||||
|
const openImportModal = useSignal<
|
||||||
|
{ isOpen: boolean }
|
||||||
|
>({ isOpen: false });
|
||||||
|
|
||||||
const dateFormat = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: 'long' });
|
const dateFormat = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: 'long' });
|
||||||
const today = new Date().toISOString().substring(0, 10);
|
const today = new Date().toISOString().substring(0, 10);
|
||||||
@@ -247,6 +256,11 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onClickImportICS() {
|
function onClickImportICS() {
|
||||||
|
openImportModal.value = { isOpen: true };
|
||||||
|
isImportExportOptionsDropdownOpen.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClickChooseImportCalendar(calendarId: string) {
|
||||||
isImportExportOptionsDropdownOpen.value = false;
|
isImportExportOptionsDropdownOpen.value = false;
|
||||||
|
|
||||||
if (isImporting.value) {
|
if (isImporting.value) {
|
||||||
@@ -266,7 +280,7 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (fileRead) => {
|
reader.onload = async (fileRead) => {
|
||||||
const importFileContents = fileRead.target?.result;
|
const importFileContents = fileRead.target?.result;
|
||||||
|
|
||||||
if (!importFileContents || isImporting.value) {
|
if (!importFileContents || isImporting.value) {
|
||||||
@@ -275,24 +289,33 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
|
|||||||
|
|
||||||
isImporting.value = true;
|
isImporting.value = true;
|
||||||
|
|
||||||
// try {
|
openImportModal.value = { isOpen: false };
|
||||||
// const partialContacts = parseVCardFromTextContents(importFileContents!.toString());
|
|
||||||
|
|
||||||
// const requestBody: ImportRequestBody = { partialContacts, page };
|
try {
|
||||||
// const response = await fetch(`/api/calendar/import`, {
|
const partialCalendarEvents = parseVCalendarFromTextContents(importFileContents!.toString());
|
||||||
// method: 'POST',
|
|
||||||
// body: JSON.stringify(requestBody),
|
|
||||||
// });
|
|
||||||
// const result = await response.json() as ImportResponseBody;
|
|
||||||
|
|
||||||
// if (!result.success) {
|
const requestBody: ImportRequestBody = {
|
||||||
// throw new Error('Failed to import contact!');
|
partialCalendarEvents,
|
||||||
// }
|
calendarIds: visibleCalendars.map((calendar) => calendar.id),
|
||||||
|
calendarView: view,
|
||||||
|
calendarStartDate: startDate,
|
||||||
|
calendarId,
|
||||||
|
};
|
||||||
|
|
||||||
// contacts.value = [...result.contacts];
|
const response = await fetch(`/api/calendar/import`, {
|
||||||
// } catch (error) {
|
method: 'POST',
|
||||||
// console.error(error);
|
body: JSON.stringify(requestBody),
|
||||||
// }
|
});
|
||||||
|
const result = await response.json() as ImportResponseBody;
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
throw new Error('Failed to import file!');
|
||||||
|
}
|
||||||
|
|
||||||
|
calendarEvents.value = [...result.newCalendarEvents];
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
isImporting.value = false;
|
isImporting.value = false;
|
||||||
};
|
};
|
||||||
@@ -601,6 +624,15 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
|
|||||||
onClickDelete={onClickDeleteEvent}
|
onClickDelete={onClickDeleteEvent}
|
||||||
onClose={onCloseOpenEvent}
|
onClose={onCloseOpenEvent}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ImportEventsModal
|
||||||
|
isOpen={openImportModal.value.isOpen}
|
||||||
|
calendars={calendars.value}
|
||||||
|
onClickImport={onClickChooseImportCalendar}
|
||||||
|
onClose={() => {
|
||||||
|
openImportModal.value = { isOpen: false };
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import * as $api_calendar_add from './routes/api/calendar/add.tsx';
|
|||||||
import * as $api_calendar_delete_event from './routes/api/calendar/delete-event.tsx';
|
import * as $api_calendar_delete_event from './routes/api/calendar/delete-event.tsx';
|
||||||
import * as $api_calendar_delete from './routes/api/calendar/delete.tsx';
|
import * as $api_calendar_delete from './routes/api/calendar/delete.tsx';
|
||||||
import * as $api_calendar_get_events from './routes/api/calendar/get-events.tsx';
|
import * as $api_calendar_get_events from './routes/api/calendar/get-events.tsx';
|
||||||
|
import * as $api_calendar_import from './routes/api/calendar/import.tsx';
|
||||||
import * as $api_calendar_search_events from './routes/api/calendar/search-events.tsx';
|
import * as $api_calendar_search_events from './routes/api/calendar/search-events.tsx';
|
||||||
import * as $api_calendar_update from './routes/api/calendar/update.tsx';
|
import * as $api_calendar_update from './routes/api/calendar/update.tsx';
|
||||||
import * as $api_contacts_add from './routes/api/contacts/add.tsx';
|
import * as $api_contacts_add from './routes/api/contacts/add.tsx';
|
||||||
@@ -72,6 +73,7 @@ const manifest = {
|
|||||||
'./routes/api/calendar/delete-event.tsx': $api_calendar_delete_event,
|
'./routes/api/calendar/delete-event.tsx': $api_calendar_delete_event,
|
||||||
'./routes/api/calendar/delete.tsx': $api_calendar_delete,
|
'./routes/api/calendar/delete.tsx': $api_calendar_delete,
|
||||||
'./routes/api/calendar/get-events.tsx': $api_calendar_get_events,
|
'./routes/api/calendar/get-events.tsx': $api_calendar_get_events,
|
||||||
|
'./routes/api/calendar/import.tsx': $api_calendar_import,
|
||||||
'./routes/api/calendar/search-events.tsx': $api_calendar_search_events,
|
'./routes/api/calendar/search-events.tsx': $api_calendar_search_events,
|
||||||
'./routes/api/calendar/update.tsx': $api_calendar_update,
|
'./routes/api/calendar/update.tsx': $api_calendar_update,
|
||||||
'./routes/api/contacts/add.tsx': $api_contacts_add,
|
'./routes/api/contacts/add.tsx': $api_contacts_add,
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export async function createCalendarEvent(
|
|||||||
|
|
||||||
const status: CalendarEvent['status'] = 'scheduled';
|
const status: CalendarEvent['status'] = 'scheduled';
|
||||||
|
|
||||||
const newCalendar = (await db.query<Calendar>(
|
const newCalendarEvent = (await db.query<CalendarEvent>(
|
||||||
sql`INSERT INTO "bewcloud_calendar_events" (
|
sql`INSERT INTO "bewcloud_calendar_events" (
|
||||||
"user_id",
|
"user_id",
|
||||||
"calendar_id",
|
"calendar_id",
|
||||||
@@ -217,7 +217,7 @@ export async function createCalendarEvent(
|
|||||||
|
|
||||||
await updateCalendarRevision(calendar);
|
await updateCalendarRevision(calendar);
|
||||||
|
|
||||||
return newCalendar;
|
return newCalendarEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateCalendarEvent(calendarEvent: CalendarEvent, oldCalendarId?: string) {
|
export async function updateCalendarEvent(calendarEvent: CalendarEvent, oldCalendarId?: string) {
|
||||||
|
|||||||
42
lib/utils.ts
42
lib/utils.ts
@@ -657,7 +657,7 @@ export function formatCalendarEventsToVCalendar(
|
|||||||
): string {
|
): string {
|
||||||
const vCalendarText = calendarEvents.map((calendarEvent) =>
|
const vCalendarText = calendarEvents.map((calendarEvent) =>
|
||||||
`BEGIN:VEVENT
|
`BEGIN:VEVENT
|
||||||
DTSTAMP:${new Date(calendarEvent.start_date).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
DTSTAMP:${new Date(calendarEvent.created_at).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
||||||
DTSTART:${new Date(calendarEvent.start_date).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
DTSTART:${new Date(calendarEvent.start_date).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
||||||
DTEND:${new Date(calendarEvent.end_date).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
DTEND:${new Date(calendarEvent.end_date).toISOString().substring(0, 19).replaceAll('-', '').replaceAll(':', '')}
|
||||||
ORGANIZER;CN=:MAILTO:${calendarEvent.extra.organizer_email}
|
ORGANIZER;CN=:MAILTO:${calendarEvent.extra.organizer_email}
|
||||||
@@ -698,7 +698,7 @@ export function parseVCalendarFromTextContents(text: string): Partial<CalendarEv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finish contact
|
// Finish contact
|
||||||
if (line.startsWith('END:VCARD')) {
|
if (line.startsWith('END:VEVENT')) {
|
||||||
partialCalendarEvents.push(partialCalendarEvent);
|
partialCalendarEvents.push(partialCalendarEvent);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -747,6 +747,44 @@ export function parseVCalendarFromTextContents(text: string): Partial<CalendarEv
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line.startsWith('DTSTART')) {
|
||||||
|
const startDateInfo = line.split(':')[1] || '';
|
||||||
|
const [dateInfo, hourInfo] = startDateInfo.split('T');
|
||||||
|
|
||||||
|
const year = dateInfo.substring(0, 4);
|
||||||
|
const month = dateInfo.substring(4, 6);
|
||||||
|
const day = dateInfo.substring(6, 8);
|
||||||
|
|
||||||
|
const hours = hourInfo.substring(0, 2);
|
||||||
|
const minutes = hourInfo.substring(2, 4);
|
||||||
|
const seconds = hourInfo.substring(4, 6);
|
||||||
|
|
||||||
|
const startDate = new Date(`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.000Z`);
|
||||||
|
|
||||||
|
partialCalendarEvent.start_date = startDate;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.startsWith('DTEND')) {
|
||||||
|
const endDateInfo = line.split(':')[1] || '';
|
||||||
|
const [dateInfo, hourInfo] = endDateInfo.split('T');
|
||||||
|
|
||||||
|
const year = dateInfo.substring(0, 4);
|
||||||
|
const month = dateInfo.substring(4, 6);
|
||||||
|
const day = dateInfo.substring(6, 8);
|
||||||
|
|
||||||
|
const hours = hourInfo.substring(0, 2);
|
||||||
|
const minutes = hourInfo.substring(2, 4);
|
||||||
|
const seconds = hourInfo.substring(4, 6);
|
||||||
|
|
||||||
|
const endDate = new Date(`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.000Z`);
|
||||||
|
|
||||||
|
partialCalendarEvent.end_date = endDate;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return partialCalendarEvents;
|
return partialCalendarEvents;
|
||||||
|
|||||||
90
routes/api/calendar/import.tsx
Normal file
90
routes/api/calendar/import.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { Handlers } from 'fresh/server.ts';
|
||||||
|
|
||||||
|
import { CalendarEvent, FreshContextState } from '/lib/types.ts';
|
||||||
|
import { concurrentPromises } from '/lib/utils.ts';
|
||||||
|
import { createCalendarEvent, getCalendar, getCalendarEvents, updateCalendarEvent } from '/lib/data/calendar.ts';
|
||||||
|
|
||||||
|
interface Data {}
|
||||||
|
|
||||||
|
export interface RequestBody {
|
||||||
|
calendarIds: string[];
|
||||||
|
calendarView: 'day' | 'week' | 'month';
|
||||||
|
calendarStartDate: string;
|
||||||
|
partialCalendarEvents: Partial<CalendarEvent>[];
|
||||||
|
calendarId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResponseBody {
|
||||||
|
success: boolean;
|
||||||
|
newCalendarEvents: 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.calendarId || !requestBody.calendarIds || !requestBody.partialCalendarEvents ||
|
||||||
|
!requestBody.calendarView || !requestBody.calendarStartDate
|
||||||
|
) {
|
||||||
|
return new Response('Bad Request', { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const calendar = await getCalendar(requestBody.calendarId, context.state.user.id);
|
||||||
|
|
||||||
|
if (!calendar) {
|
||||||
|
return new Response('Not Found', { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestBody.partialCalendarEvents.length === 0) {
|
||||||
|
return new Response('Not found', { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
await concurrentPromises(
|
||||||
|
requestBody.partialCalendarEvents.map((partialCalendarEvent) => async () => {
|
||||||
|
if (partialCalendarEvent.title && partialCalendarEvent.start_date && partialCalendarEvent.end_date) {
|
||||||
|
const calendarEvent = await createCalendarEvent(
|
||||||
|
context.state.user!.id,
|
||||||
|
requestBody.calendarId,
|
||||||
|
partialCalendarEvent.title,
|
||||||
|
new Date(partialCalendarEvent.start_date),
|
||||||
|
new Date(partialCalendarEvent.end_date),
|
||||||
|
partialCalendarEvent.is_all_day,
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsedExtra = JSON.stringify(partialCalendarEvent.extra || {});
|
||||||
|
|
||||||
|
if (parsedExtra !== '{}') {
|
||||||
|
calendarEvent.extra = partialCalendarEvent.extra!;
|
||||||
|
|
||||||
|
await updateCalendarEvent(calendarEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
5,
|
||||||
|
);
|
||||||
|
|
||||||
|
const dateRange = { start: new Date(requestBody.calendarStartDate), end: new Date(requestBody.calendarStartDate) };
|
||||||
|
|
||||||
|
if (requestBody.calendarView === 'day') {
|
||||||
|
dateRange.start.setDate(dateRange.start.getDate() - 1);
|
||||||
|
dateRange.end.setDate(dateRange.end.getDate() + 1);
|
||||||
|
} else if (requestBody.calendarView === 'week') {
|
||||||
|
dateRange.start.setDate(dateRange.start.getDate() - 7);
|
||||||
|
dateRange.end.setDate(dateRange.end.getDate() + 7);
|
||||||
|
} else {
|
||||||
|
dateRange.start.setDate(dateRange.start.getDate() - 7);
|
||||||
|
dateRange.end.setDate(dateRange.end.getDate() + 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newCalendarEvents = await getCalendarEvents(context.state.user.id, requestBody.calendarIds, dateRange);
|
||||||
|
|
||||||
|
const responseBody: ResponseBody = { success: true, newCalendarEvents };
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(responseBody));
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user