feat(calendar): implement local calendar invitations with email notifications
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m19s
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m19s
- Added functionality to create, accept, decline, and delete local calendar invitations. - Integrated email notifications for calendar event invitations and deletions. - Updated database schema to support local invitations and outbound event tracking. - Enhanced the calendar UI to display pending invitations and allow users to manage them. - Localized new strings for invitations in English and German.
This commit is contained in:
@@ -558,6 +558,65 @@ export async function initDatabase() {
|
||||
`);
|
||||
}
|
||||
|
||||
// Track outbound calendar event federation sends for deletion propagation
|
||||
if (isPostgres) {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS calendar_event_outbound (
|
||||
id SERIAL PRIMARY KEY,
|
||||
event_uid TEXT NOT NULL,
|
||||
remote_domain TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(event_uid, remote_domain)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_out_event_uid ON calendar_event_outbound(event_uid);
|
||||
`);
|
||||
} else {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS calendar_event_outbound (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_uid TEXT NOT NULL,
|
||||
remote_domain TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(event_uid, remote_domain)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_out_event_uid ON calendar_event_outbound(event_uid);
|
||||
`);
|
||||
}
|
||||
|
||||
// Local calendar event invitations (share-with-acceptance flow)
|
||||
if (isPostgres) {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS calendar_local_invitations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
event_id INTEGER NOT NULL REFERENCES calendar_events(id) ON DELETE CASCADE,
|
||||
from_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
to_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
status TEXT DEFAULT 'pending' CHECK(status IN ('pending','accepted','declined')),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(event_id, to_user_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_local_inv_to_user ON calendar_local_invitations(to_user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_local_inv_event ON calendar_local_invitations(event_id);
|
||||
`);
|
||||
} else {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS calendar_local_invitations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_id INTEGER NOT NULL,
|
||||
from_user_id INTEGER NOT NULL,
|
||||
to_user_id INTEGER NOT NULL,
|
||||
status TEXT DEFAULT 'pending' CHECK(status IN ('pending','accepted','declined')),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(event_id, to_user_id),
|
||||
FOREIGN KEY (event_id) REFERENCES calendar_events(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (from_user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (to_user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_local_inv_to_user ON calendar_local_invitations(to_user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cal_local_inv_event ON calendar_local_invitations(event_id);
|
||||
`);
|
||||
}
|
||||
|
||||
// ── Default admin (only on very first start) ────────────────────────────
|
||||
const adminAlreadySeeded = await db.get("SELECT value FROM settings WHERE key = 'admin_seeded'");
|
||||
if (!adminAlreadySeeded) {
|
||||
|
||||
Reference in New Issue
Block a user