289 lines
9.6 KiB
TypeScript
289 lines
9.6 KiB
TypeScript
import * as dotenv from 'dotenv';
|
|
import {Guid} from 'guid-typescript';
|
|
import {Event} from './event.interface';
|
|
import {NachklangCalendarDB} from '../Calendar.db';
|
|
|
|
|
|
dotenv.config();
|
|
|
|
/**
|
|
* Returns all events for the given calendar
|
|
* @param calendarId The calendar Id
|
|
*/
|
|
export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
let eventRows: Event[] = [];
|
|
try {
|
|
const calendarQuery = 'SELECT calendar_id, includes_calendars FROM calendars WHERE calendar_id = ?';
|
|
const calendarRes = await conn.query(calendarQuery, calendarId);
|
|
let calendarsToFetch: number[] = [calendarId];
|
|
for(let row of calendarRes) {
|
|
let includes: number[] = JSON.parse(row.includes_calendars);
|
|
calendarsToFetch = [...calendarsToFetch, ...includes];
|
|
}
|
|
|
|
const eventsQuery = `
|
|
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name as created_by_name, u2.full_name as last_modified_by_name, v.* FROM events e
|
|
INNER JOIN (
|
|
SELECT event_id, MAX(event_version_id) AS latest_version
|
|
FROM event_versions
|
|
GROUP BY event_id
|
|
) latest_versions
|
|
ON e.event_id = latest_versions.event_id
|
|
INNER JOIN event_versions v
|
|
ON v.event_id = latest_versions.event_id AND v.event_version_id = latest_versions.latest_version
|
|
LEFT OUTER JOIN users u ON u.user_id = e.created_by_id
|
|
LEFT OUTER JOIN users u2 ON u2.user_id = v.version_created_by_id
|
|
WHERE e.calendar_id IN (?) AND v.status = 'PUBLIC'
|
|
ORDER BY e.event_id`;
|
|
const eventsRes = await conn.query(eventsQuery, [calendarsToFetch]);
|
|
|
|
for (let row of eventsRes) {
|
|
eventRows.push({
|
|
eventId: row.event_id,
|
|
calendarId: row.calendar_id,
|
|
uuid: row.uuid,
|
|
name: row.name,
|
|
description: row.description,
|
|
startDateTime: row.start_datetime,
|
|
endDateTime: row.end_datetime,
|
|
createdDate: row.created_date,
|
|
lastModifiedDate: row.version_created_at,
|
|
location: row.location,
|
|
createdBy: row.created_by_name,
|
|
createdById: row.created_by_id,
|
|
lastModifiedBy: row.last_modified_by_name,
|
|
lastModifiedById: row.version_created_by_id,
|
|
url: row.url,
|
|
wholeDay: row.whole_day,
|
|
repeatFrequency: row.repeat_frequency
|
|
});
|
|
}
|
|
|
|
return eventRows;
|
|
} catch (err) {
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Returns all events for the given calendar for the admin UI (therefore includes admin relevant information and
|
|
* ignores the calendar includes
|
|
* @param calendarId
|
|
*/
|
|
export const getAllEventsAdmin = async (calendarId: number): Promise<Event[]> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
let eventRows: Event[] = [];
|
|
try {
|
|
const eventsQuery = `
|
|
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name as created_by_name, u2.full_name as last_modified_by_name, v.* FROM events e
|
|
INNER JOIN (
|
|
SELECT event_id, MAX(event_version_id) AS latest_version
|
|
FROM event_versions
|
|
GROUP BY event_id
|
|
) latest_versions
|
|
ON e.event_id = latest_versions.event_id
|
|
INNER JOIN event_versions v
|
|
ON v.event_id = latest_versions.event_id AND v.event_version_id = latest_versions.latest_version
|
|
LEFT OUTER JOIN users u ON u.user_id = e.created_by_id
|
|
LEFT OUTER JOIN users u2 ON u2.user_id = v.version_created_by_id
|
|
WHERE e.calendar_id = ?
|
|
ORDER BY e.event_id`;
|
|
const eventsRes = await conn.query(eventsQuery, calendarId);
|
|
|
|
for (let row of eventsRes) {
|
|
eventRows.push({
|
|
eventId: row.event_id,
|
|
calendarId: row.calendar_id,
|
|
uuid: row.uuid,
|
|
name: row.name,
|
|
description: row.description,
|
|
startDateTime: row.start_datetime,
|
|
endDateTime: row.end_datetime,
|
|
createdDate: row.created_date,
|
|
lastModifiedDate: row.version_created_at,
|
|
location: row.location,
|
|
createdBy: row.created_by_name,
|
|
createdById: row.created_by_id,
|
|
lastModifiedBy: row.last_modified_by_name,
|
|
lastModifiedById: row.version_created_by_id,
|
|
url: row.url,
|
|
wholeDay: row.whole_day,
|
|
repeatFrequency: row.repeat_frequency,
|
|
status: row.status
|
|
});
|
|
}
|
|
|
|
return eventRows;
|
|
} catch (err) {
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Create the given event in the database
|
|
* @param event The event to create
|
|
*/
|
|
export const createEvent = async (event: Event): Promise<number> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
try {
|
|
let eventUUID = Guid.create().toString();
|
|
const eventsQuery = 'INSERT INTO events (calendar_id, uuid, created_by_id) VALUES (?,?,?) RETURNING event_id';
|
|
const eventsRes = await conn.execute(eventsQuery, [event.calendarId, eventUUID, event.createdById]);
|
|
|
|
const versionQuery = 'INSERT INTO event_versions (event_id, name, description, start_datetime, end_datetime, whole_day, repeat_frequency, location, url, status, version_created_by_id) VALUES (?,?,?,?,?,?,?,?,?,?,?);'
|
|
const versionRes = await conn.execute(versionQuery, [eventsRes[0].event_id, event.name, event.description, event.startDateTime, event.endDateTime, event.wholeDay, event.repeatFrequency, event.location, event.url, event.status, event.createdById]);
|
|
|
|
await conn.commit();
|
|
|
|
return eventsRes[0].event_id;
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.commit();
|
|
await conn.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Update the given event in the database
|
|
* @param event The event to update
|
|
*/
|
|
export const updateEvent = async (event: Event): Promise<number> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
try {
|
|
const versionQuery = 'INSERT INTO event_versions (event_id, name, description, start_datetime, end_datetime, whole_day, repeat_frequency, location, url, status, version_created_by_id) VALUES (?,?,?,?,?,?,?,?,?,?,?);'
|
|
const versionRes = await conn.execute(versionQuery, [event.eventId, event.name, event.description, event.startDateTime, event.endDateTime, event.wholeDay, event.repeatFrequency, event.location, event.url, event.status, event.createdById]);
|
|
|
|
await conn.commit();
|
|
|
|
return versionRes.affectedRows;
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.commit();
|
|
await conn.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Deletes the given event from the database
|
|
* @param event The event to delete
|
|
*/
|
|
export const deleteEvent = async (event: Event): Promise<boolean> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
try {
|
|
const versionQuery = 'INSERT INTO event_versions (event_id, status, version_created_by_id) VALUES (?,?,?);'
|
|
const versionRes = await conn.execute(versionQuery, [event.eventId, 'DELETED', event.createdById]);
|
|
|
|
await conn.commit();
|
|
|
|
return versionRes.affectedRows === 1;
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.commit();
|
|
await conn.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Moves an event to the specified calendar
|
|
* @param event The event to move. Has to have the target calendar set already.
|
|
*/
|
|
export const moveEvent = async (event: Event): Promise<boolean> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
try {
|
|
const eventQuery = 'UPDATE events SET calendar_id = ? WHERE event_id = ?';
|
|
const eventRes = await conn.execute(eventQuery, [event.calendarId, event.eventId]);
|
|
|
|
await conn.commit();
|
|
|
|
return eventRes.affectedRows === 1;
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.commit();
|
|
await conn.end();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the next upcoming event for the given calendar
|
|
* @param calendarId The calendar Id
|
|
*/
|
|
export const getNextUpcomingEvent = async (calendarId: number): Promise<Event | null> => {
|
|
let conn = await NachklangCalendarDB.getConnection();
|
|
try {
|
|
const calendarQuery = 'SELECT calendar_id, includes_calendars FROM calendars WHERE calendar_id = ?';
|
|
const calendarRes = await conn.query(calendarQuery, calendarId);
|
|
let calendarsToFetch: number[] = [calendarId];
|
|
for(let row of calendarRes) {
|
|
let includes: number[] = JSON.parse(row.includes_calendars);
|
|
calendarsToFetch = [...calendarsToFetch, ...includes];
|
|
}
|
|
|
|
const now = new Date();
|
|
const eventsQuery = `
|
|
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name as created_by_name, u2.full_name as last_modified_by_name, v.* FROM events e
|
|
INNER JOIN (
|
|
SELECT event_id, MAX(event_version_id) AS latest_version
|
|
FROM event_versions
|
|
GROUP BY event_id
|
|
) latest_versions
|
|
ON e.event_id = latest_versions.event_id
|
|
INNER JOIN event_versions v
|
|
ON v.event_id = latest_versions.event_id AND v.event_version_id = latest_versions.latest_version
|
|
LEFT OUTER JOIN users u ON u.user_id = e.created_by_id
|
|
LEFT OUTER JOIN users u2 ON u2.user_id = v.version_created_by_id
|
|
WHERE e.calendar_id IN (?) AND v.status = 'PUBLIC' AND v.start_datetime > ?
|
|
ORDER BY v.start_datetime ASC
|
|
LIMIT 1`;
|
|
const eventsRes = await conn.query(eventsQuery, [calendarsToFetch, now]);
|
|
|
|
if (eventsRes.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const row = eventsRes[0];
|
|
return {
|
|
eventId: row.event_id,
|
|
calendarId: row.calendar_id,
|
|
uuid: row.uuid,
|
|
name: row.name,
|
|
description: row.description,
|
|
startDateTime: row.start_datetime,
|
|
endDateTime: row.end_datetime,
|
|
createdDate: row.created_date,
|
|
lastModifiedDate: row.version_created_at,
|
|
location: row.location,
|
|
createdBy: row.created_by_name,
|
|
createdById: row.created_by_id,
|
|
lastModifiedBy: row.last_modified_by_name,
|
|
lastModifiedById: row.version_created_by_id,
|
|
url: row.url,
|
|
wholeDay: row.whole_day,
|
|
repeatFrequency: row.repeat_frequency
|
|
} as Event;
|
|
} catch (err) {
|
|
throw err;
|
|
} finally {
|
|
// Return connection
|
|
await conn.end();
|
|
}
|
|
}
|