Calendar SQL and CRUD
This commit is contained in:
@@ -1,173 +1,56 @@
|
||||
// import Database, { sql } from '/lib/interfaces/database.ts';
|
||||
import Database, { sql } from '/lib/interfaces/database.ts';
|
||||
import { Calendar, CalendarEvent } from '/lib/types.ts';
|
||||
import { CALENDAR_COLOR_OPTIONS, getRandomItem } from '/lib/utils.ts';
|
||||
// import { getUserById } from './user.ts';
|
||||
|
||||
// const db = new Database();
|
||||
const db = new Database();
|
||||
|
||||
// TODO: Build this
|
||||
export async function getCalendars(userId: string): Promise<Calendar[]> {
|
||||
// TODO: Remove this
|
||||
await new Promise((resolve) => setTimeout(() => resolve(true), 1));
|
||||
const calendars = await db.query<Calendar>(
|
||||
sql`SELECT * FROM "bewcloud_calendars" WHERE "user_id" = $1 ORDER BY "created_at" ASC`,
|
||||
[
|
||||
userId,
|
||||
],
|
||||
);
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'family-1',
|
||||
user_id: userId,
|
||||
name: 'Family',
|
||||
color: 'bg-purple-500',
|
||||
is_visible: true,
|
||||
revision: 'fake-rev',
|
||||
extra: {
|
||||
default_transparency: 'opaque',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'personal-1',
|
||||
user_id: userId,
|
||||
name: 'Personal',
|
||||
color: 'bg-sky-600',
|
||||
is_visible: true,
|
||||
revision: 'fake-rev',
|
||||
extra: {
|
||||
default_transparency: 'opaque',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'house-chores-1',
|
||||
user_id: userId,
|
||||
name: 'House Chores',
|
||||
color: 'bg-red-700',
|
||||
is_visible: true,
|
||||
revision: 'fake-rev',
|
||||
extra: {
|
||||
default_transparency: 'opaque',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
];
|
||||
return calendars;
|
||||
}
|
||||
|
||||
// TODO: Build this
|
||||
export async function getCalendarEvents(userId: string, calendarIds: string[]): Promise<CalendarEvent[]> {
|
||||
// TODO: Remove this
|
||||
await new Promise((resolve) => setTimeout(() => resolve(true), 1));
|
||||
const calendarEvents = await db.query<CalendarEvent>(
|
||||
sql`SELECT * FROM "bewcloud_calendar_events" WHERE "user_id" = $1 AND "calendar_id" = ANY($2) ORDER BY "start_date" ASC`,
|
||||
[
|
||||
userId,
|
||||
calendarIds,
|
||||
],
|
||||
);
|
||||
|
||||
const now = new Date();
|
||||
const today = now.toISOString().substring(0, 10);
|
||||
const tomorrow = new Date(new Date(now).setDate(now.getDate() + 1)).toISOString().substring(0, 10);
|
||||
const twoDaysFromNow = new Date(new Date(now).setDate(now.getDate() + 2)).toISOString().substring(0, 10);
|
||||
|
||||
const calendarEvents = [
|
||||
{
|
||||
id: 'event-1',
|
||||
user_id: userId,
|
||||
calendar_id: 'family-1',
|
||||
revision: 'fake-rev',
|
||||
title: 'Dentist',
|
||||
start_date: new Date(`${today}T14:00:00.000Z`),
|
||||
end_date: new Date(`${today}T15:00:00.000Z`),
|
||||
is_all_day: false,
|
||||
status: 'scheduled',
|
||||
extra: {
|
||||
organizer_email: 'user@example.com',
|
||||
transparency: 'default',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'event-2',
|
||||
user_id: userId,
|
||||
calendar_id: 'family-1',
|
||||
revision: 'fake-rev',
|
||||
title: 'Dermatologist',
|
||||
start_date: new Date(`${today}T16:30:00.000Z`),
|
||||
end_date: new Date(`${today}T17:30:00.000Z`),
|
||||
is_all_day: false,
|
||||
status: 'scheduled',
|
||||
extra: {
|
||||
organizer_email: 'user@example.com',
|
||||
transparency: 'default',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'event-3',
|
||||
user_id: userId,
|
||||
calendar_id: 'house-chores-1',
|
||||
revision: 'fake-rev',
|
||||
title: 'Vacuum',
|
||||
start_date: new Date(`${tomorrow}T15:00:00.000Z`),
|
||||
end_date: new Date(`${tomorrow}T16:00:00.000Z`),
|
||||
is_all_day: false,
|
||||
status: 'scheduled',
|
||||
extra: {
|
||||
organizer_email: 'user@example.com',
|
||||
transparency: 'default',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'event-4',
|
||||
user_id: userId,
|
||||
calendar_id: 'personal-1',
|
||||
revision: 'fake-rev',
|
||||
title: 'Schedule server updates',
|
||||
start_date: new Date(`${twoDaysFromNow}T09:00:00.000Z`),
|
||||
end_date: new Date(`${twoDaysFromNow}T21:00:00.000Z`),
|
||||
is_all_day: true,
|
||||
status: 'scheduled',
|
||||
extra: {
|
||||
organizer_email: 'user@example.com',
|
||||
transparency: 'default',
|
||||
},
|
||||
updated_at: new Date(),
|
||||
created_at: new Date(),
|
||||
},
|
||||
] as const;
|
||||
|
||||
return calendarEvents.filter((calendarEvent) => calendarIds.includes(calendarEvent.calendar_id));
|
||||
return calendarEvents;
|
||||
}
|
||||
|
||||
// TODO: Build this
|
||||
export async function getCalendarEvent(id: string, calendarId: string, userId: string): Promise<CalendarEvent> {
|
||||
// TODO: Build this
|
||||
// const calendarEvents = await db.query<CalendarEvent>(
|
||||
// sql`SELECT * FROM "bewcloud_calendar_events" WHERE "id" = $1 AND "calendar_id" = $2 AND "user_id" = $3 LIMIT 1`,
|
||||
// [
|
||||
// id,
|
||||
// calendarId,
|
||||
// userId,
|
||||
// ],
|
||||
// );
|
||||
const calendarEvents = await db.query<CalendarEvent>(
|
||||
sql`SELECT * FROM "bewcloud_calendar_events" WHERE "id" = $1 AND "calendar_id" = $2 AND "user_id" = $3 LIMIT 1`,
|
||||
[
|
||||
id,
|
||||
calendarId,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
|
||||
// return calendarEvents[0];
|
||||
const calendarEvents = await getCalendarEvents(userId, [calendarId]);
|
||||
|
||||
return calendarEvents.find((calendarEvent) => calendarEvent.id === id)!;
|
||||
return calendarEvents[0];
|
||||
}
|
||||
|
||||
export async function getCalendar(id: string, userId: string) {
|
||||
// TODO: Build this
|
||||
// const calendars = await db.query<Calendar>(
|
||||
// sql`SELECT * FROM "bewcloud_calendars" WHERE "id" = $1 AND "user_id" = $2 LIMIT 1`,
|
||||
// [
|
||||
// id,
|
||||
// userId,
|
||||
// ],
|
||||
// );
|
||||
const calendars = await db.query<Calendar>(
|
||||
sql`SELECT * FROM "bewcloud_calendars" WHERE "id" = $1 AND "user_id" = $2 LIMIT 1`,
|
||||
[
|
||||
id,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
|
||||
// return calendars[0];
|
||||
|
||||
const calendars = await getCalendars(userId);
|
||||
|
||||
return calendars.find((calendar) => calendar.id === id)!;
|
||||
return calendars[0];
|
||||
}
|
||||
|
||||
export async function createCalendar(userId: string, name: string, color?: string) {
|
||||
@@ -177,30 +60,27 @@ export async function createCalendar(userId: string, name: string, color?: strin
|
||||
|
||||
const revision = crypto.randomUUID();
|
||||
|
||||
// TODO: Build this
|
||||
// const newCalendar = (await db.query<Calendar>(
|
||||
// sql`INSERT INTO "bewcloud_calendars" (
|
||||
// "user_id",
|
||||
// "revision",
|
||||
// "name",
|
||||
// "color",
|
||||
// "extra"
|
||||
// ) VALUES ($1, $2, $3, $4, $5)
|
||||
// RETURNING *`,
|
||||
// [
|
||||
// userId,
|
||||
// revision,
|
||||
// name,
|
||||
// color,
|
||||
// JSON.stringify(extra),
|
||||
// ],
|
||||
// ))[0];
|
||||
const newColor = color || getRandomItem(CALENDAR_COLOR_OPTIONS);
|
||||
|
||||
// TODO: Generate new, non-existing color
|
||||
const newColor = color || 'bg-green-600';
|
||||
|
||||
const calendars = await getCalendars(userId);
|
||||
const newCalendar = { ...calendars[0], id: crypto.randomUUID(), revision, extra, name, color: newColor };
|
||||
const newCalendar = (await db.query<Calendar>(
|
||||
sql`INSERT INTO "bewcloud_calendars" (
|
||||
"user_id",
|
||||
"revision",
|
||||
"name",
|
||||
"color",
|
||||
"is_visible",
|
||||
"extra"
|
||||
) VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *`,
|
||||
[
|
||||
userId,
|
||||
revision,
|
||||
name,
|
||||
newColor,
|
||||
true,
|
||||
JSON.stringify(extra),
|
||||
],
|
||||
))[0];
|
||||
|
||||
return newCalendar;
|
||||
}
|
||||
@@ -208,43 +88,43 @@ export async function createCalendar(userId: string, name: string, color?: strin
|
||||
export async function updateCalendar(calendar: Calendar) {
|
||||
const revision = crypto.randomUUID();
|
||||
|
||||
// TODO: Build this
|
||||
// await db.query(
|
||||
// sql`UPDATE "bewcloud_calendars" SET
|
||||
// "revision" = $3,
|
||||
// "name" = $4,
|
||||
// "color" = $5,
|
||||
// "extra" = $6,
|
||||
// "updated_at" = now()
|
||||
// WHERE "id" = $1 AND "revision" = $2`,
|
||||
// [
|
||||
// calendar.id,
|
||||
// calendar.revision,
|
||||
// revision,
|
||||
// calendar.name,
|
||||
// calendar.color,
|
||||
// JSON.stringify(calendar.extra),
|
||||
// ],
|
||||
// );
|
||||
|
||||
calendar.revision = revision;
|
||||
|
||||
// TODO: Remove this
|
||||
await new Promise((resolve) => setTimeout(() => resolve(true), 1));
|
||||
await db.query(
|
||||
sql`UPDATE "bewcloud_calendars" SET
|
||||
"revision" = $3,
|
||||
"name" = $4,
|
||||
"color" = $5,
|
||||
"is_visible" = $6,
|
||||
"extra" = $7,
|
||||
"updated_at" = now()
|
||||
WHERE "id" = $1 AND "revision" = $2`,
|
||||
[
|
||||
calendar.id,
|
||||
calendar.revision,
|
||||
revision,
|
||||
calendar.name,
|
||||
calendar.color,
|
||||
calendar.is_visible,
|
||||
JSON.stringify(calendar.extra),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
export async function deleteCalendar(_id: string, _userId: string) {
|
||||
// TODO: Build this
|
||||
// await db.query(
|
||||
// sql`DELETE FROM "bewcloud_calendars" WHERE "id" = $1 AND "user_id" = $2`,
|
||||
// [
|
||||
// id,
|
||||
// userId,
|
||||
// ],
|
||||
// );
|
||||
export async function deleteCalendar(id: string, userId: string) {
|
||||
await db.query(
|
||||
sql`DELETE FROM "bewcloud_calendar_events" WHERE "calendar_id" = $1 AND "user_id" = $2`,
|
||||
[
|
||||
id,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
|
||||
// TODO: Remove this
|
||||
await new Promise((resolve) => setTimeout(() => resolve(true), 1));
|
||||
await db.query(
|
||||
sql`DELETE FROM "bewcloud_calendars" WHERE "id" = $1 AND "user_id" = $2`,
|
||||
[
|
||||
id,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: When creating, updating, or deleting events, also update the calendar's revision
|
||||
|
||||
@@ -105,18 +105,20 @@ export async function updateNewsFeed(newsFeed: NewsFeed) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function deleteNewsFeed(id: string) {
|
||||
export async function deleteNewsFeed(id: string, userId: string) {
|
||||
await db.query(
|
||||
sql`DELETE FROM "bewcloud_news_feed_articles" WHERE "feed_id" = $1`,
|
||||
sql`DELETE FROM "bewcloud_news_feed_articles" WHERE "feed_id" = $1 AND "user_id" = $2`,
|
||||
[
|
||||
id,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
|
||||
await db.query(
|
||||
sql`DELETE FROM "bewcloud_news_feeds" WHERE "id" = $1`,
|
||||
sql`DELETE FROM "bewcloud_news_feeds" WHERE "id" = $1 AND "user_id" = $2`,
|
||||
[
|
||||
id,
|
||||
userId,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,6 @@ export interface ContactField {
|
||||
type: ContactFieldType;
|
||||
}
|
||||
|
||||
// TODO: Finish (more fields)
|
||||
export interface Calendar {
|
||||
id: string;
|
||||
user_id: string;
|
||||
@@ -148,7 +147,6 @@ export interface Calendar {
|
||||
created_at: Date;
|
||||
}
|
||||
|
||||
// TODO: Finish (more fields)
|
||||
export interface CalendarEvent {
|
||||
id: string;
|
||||
user_id: string;
|
||||
|
||||
27
lib/utils.ts
27
lib/utils.ts
@@ -23,6 +23,29 @@ export const DAV_RESPONSE_HEADER = '1, 2, 3, 4, addressbook, calendar-access';
|
||||
// 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-auto-schedule, calendar-availability, nc-calendar-trashbin, nc-calendar-webcal-cache, calendarserver-subscribed, oc-resource-sharing, oc-calendar-publishing, calendarserver-sharing, addressbook, nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar
|
||||
// 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-auto-schedule, calendar-availability, nc-calendar-trashbin, nc-calendar-webcal-cache, calendarserver-subscribed, oc-resource-sharing, oc-calendar-publishing, calendarserver-sharing, nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar
|
||||
|
||||
export const CALENDAR_COLOR_OPTIONS = [
|
||||
'bg-red-700',
|
||||
'bg-red-950',
|
||||
'bg-orange-700',
|
||||
'bg-orange-950',
|
||||
'bg-amber-700',
|
||||
'bg-yellow-800',
|
||||
'bg-lime-700',
|
||||
'bg-lime-950',
|
||||
'bg-green-700',
|
||||
'bg-emerald-800',
|
||||
'bg-teal-700',
|
||||
'bg-cyan-700',
|
||||
'bg-sky-800',
|
||||
'bg-blue-900',
|
||||
'bg-indigo-700',
|
||||
'bg-violet-700',
|
||||
'bg-purple-800',
|
||||
'bg-fuchsia-700',
|
||||
'bg-pink-800',
|
||||
'bg-rose-700',
|
||||
] as const;
|
||||
|
||||
export function isRunningLocally(request: Request) {
|
||||
return request.url.includes('localhost');
|
||||
}
|
||||
@@ -805,3 +828,7 @@ export function getDaysForWeek(
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
export function getRandomItem<T>(items: Readonly<Array<T>>): T {
|
||||
return items[Math.floor(Math.random() * items.length)];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user