UNPKG

idea-toolbox

Version:
245 lines (244 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppointmentNotificationUnitsOfTime = exports.AppointmentNotificationMethods = exports.AppointmentNotification = exports.AppointmentAttendance = exports.AppointmentAttendee = exports.AppointmentLinkedObjectTypes = exports.AppointmentLinkedObject = exports.AppointmentKeys = exports.Appointment = void 0; const resource_model_1 = require("./resource.model"); /** * Represents an appointment (event) of a calendar. * * Table: `idea_appointments`. * * Indexes: * - calendarId-startTime-index (LSI, all) * - calendarId-masterAppointmentId-index (LSI, keys); to manage occurences * - internalNotificationFiresOn-internalNotificationFiresAt-index (GSI); includes: * internalNotificationProject, internalNotificationTeamId, internalNotificationUserId, * notifications, title, startTime, endTime */ class Appointment extends resource_model_1.Resource { load(x) { super.load(x); this.appointmentId = this.clean(x.appointmentId, String); this.calendarId = this.clean(x.calendarId, String); this.iCalUID = this.clean(x.iCalUID, String); if (x.masterAppointmentId) this.masterAppointmentId = this.clean(x.masterAppointmentId, String); this.title = this.clean(x.title, String); this.location = this.clean(x.location, String); this.description = this.clean(x.description, String); this.startTime = this.clean(x.startTime, d => new Date(d).getTime()); this.endTime = this.clean(x.endTime, d => new Date(d).getTime()); this.allDay = this.clean(x.allDay, Boolean); this.fixAllDayTime(); this.timezone = this.clean(x.timezone, String, Intl.DateTimeFormat().resolvedOptions().timeZone); if (x.linkToOrigin) this.linkToOrigin = this.clean(x.linkToOrigin, String); this.notifications = this.cleanArray(x.notifications, n => new AppointmentNotification(n)); if (!this.linkToOrigin && this.notifications.length) { // appointment comes from an internal calendar, notifications will fire this.internalNotificationProject = this.clean(x.internalNotificationProject, String); this.internalNotificationTeamId = this.clean(x.internalNotificationTeamId, String); this.internalNotificationUserId = this.clean(x.internalNotificationUserId, String); this.removeDuplicateNotifications(); this.calculateFiringTime(); } if (x.linkedTo) this.linkedTo = this.cleanArray(x.linkedTo, o => new AppointmentLinkedObject(o)); this.attendees = this.cleanArray(x.attendees, a => new AppointmentAttendee(a)); } /** * Set a default start/end day for all-day events, to be compatible with external services. */ fixAllDayTime() { if (this.allDay) { const start = new Date(this.startTime); start.setHours(0, 0, 0); this.startTime = start.getTime(); const end = new Date(this.endTime); end.setHours(13, 0, 0); this.endTime = end.getTime(); } } safeLoad(newData, safeData) { super.safeLoad(newData, safeData); this.appointmentId = safeData.appointmentId; this.calendarId = safeData.calendarId; this.iCalUID = safeData.iCalUID; if (safeData.masterAppointmentId) this.masterAppointmentId = safeData.masterAppointmentId; if (safeData.linkedTo) this.linkedTo = safeData.linkedTo; if (!this.linkToOrigin) if (this.notifications.length) { this.internalNotificationProject = safeData.internalNotificationProject; this.internalNotificationTeamId = safeData.internalNotificationTeamId; this.internalNotificationUserId = safeData.internalNotificationUserId; this.removeDuplicateNotifications(); this.calculateFiringTime(); } else { delete this.internalNotificationProject; delete this.internalNotificationTeamId; delete this.internalNotificationUserId; delete this.internalNotificationFiresAt; delete this.internalNotificationFiresOn; } } validate() { const e = super.validate(); if (this.iE(this.title)) e.push('title'); if (this.iE(this.startTime)) e.push('startTime'); if (this.iE(this.endTime)) e.push('endTime'); if (this.iE(this.timezone)) e.push('timezone'); return e; } /** * Helper to remove duplicates notifications for the same appointment. */ removeDuplicateNotifications() { this.notifications = this.notifications.filter((n, index, self) => index === self.findIndex(t => t.method === n.method && t.minutes === n.minutes)); } /** * Calculate the firing time for internal appointments. */ calculateFiringTime() { // find the first notification to fire (max number of minutes to substract from the start time) const maxNumMinutes = Math.max.apply(null, this.notifications.map(n => n.minutes)); // prepare the support firing attributes const at = new Date(this.startTime); at.setMinutes(at.getMinutes() - maxNumMinutes); this.internalNotificationFiresOn = String(at.getFullYear()).concat(('00' + String(at.getMonth() + 1)).slice(-2), ('00' + String(at.getDate())).slice(-2), ('00' + String(at.getHours())).slice(-2)); this.internalNotificationFiresAt = at.getMinutes(); } /** * Get the information on an attendee. * The latter can be identified by email or, by default, as the attendee marked as `self`. */ getAttendee(email) { return this.attendees.find(a => (email ? a.email === email : a.self)); } /** * Get the attendance of the desired attendee. * The latter can be identified by email or, by default, as the attendee marked as `self`. */ getAttendance(email) { const attendee = this.getAttendee(email); return attendee ? attendee.attendance : undefined; } /** * Whether the user is the organizer of the event. * The user can be identified by email or, by default, as the attendee marked as `self`. */ isOrganizer(email) { // if the array is empty, the event is owned by the current user (there aren't other attendees) if (!this.attendees.length) return true; // otherwise, check whether the user is the organizer const attendee = this.getAttendee(email); return attendee ? attendee.organizer : false; } } exports.Appointment = Appointment; /** * A brief view of the appointment, composed by only its keys. */ class AppointmentKeys extends resource_model_1.Resource { load(x) { super.load(x); this.appointmentId = this.clean(x.appointmentId, String); this.calendarId = this.clean(x.calendarId, String); if (x.teamId) this.teamId = this.clean(x.teamId, String); } validate() { const e = super.validate(); if (this.iE(this.appointmentId)) e.push('appointmentId'); if (this.iE(this.calendarId)) e.push('calendarId'); return e; } } exports.AppointmentKeys = AppointmentKeys; /** * A generic structure to reference to a linked object. */ class AppointmentLinkedObject extends resource_model_1.Resource { load(x) { super.load(x); this.type = this.clean(x.type, Number); this.id = this.clean(x.id, String); } validate() { const e = super.validate(); if (!(this.type in AppointmentLinkedObjectTypes)) e.push('type'); if (this.iE(this.id)) e.push('id'); return e; } } exports.AppointmentLinkedObject = AppointmentLinkedObject; /** * The linked object types. */ var AppointmentLinkedObjectTypes; (function (AppointmentLinkedObjectTypes) { AppointmentLinkedObjectTypes[AppointmentLinkedObjectTypes["SCARLETT_ACTIVITY"] = 100] = "SCARLETT_ACTIVITY"; AppointmentLinkedObjectTypes[AppointmentLinkedObjectTypes["ARTHUR_ACTIVITY"] = 200] = "ARTHUR_ACTIVITY"; })(AppointmentLinkedObjectTypes || (exports.AppointmentLinkedObjectTypes = AppointmentLinkedObjectTypes = {})); /** * The info about the attendee to an appointment. */ class AppointmentAttendee extends resource_model_1.Resource { load(x) { super.load(x); this.email = this.clean(x.email, String); this.organizer = this.clean(x.organizer, Boolean); this.self = this.clean(x.self, Boolean); this.attendance = this.clean(x.attendance, Number, AppointmentAttendance.NEEDS_ACTION); } } exports.AppointmentAttendee = AppointmentAttendee; /** * Possible attendance status for the appointment. */ var AppointmentAttendance; (function (AppointmentAttendance) { AppointmentAttendance[AppointmentAttendance["DECLINED"] = -1] = "DECLINED"; AppointmentAttendance[AppointmentAttendance["NEEDS_ACTION"] = 0] = "NEEDS_ACTION"; AppointmentAttendance[AppointmentAttendance["TENTATIVE"] = 1] = "TENTATIVE"; AppointmentAttendance[AppointmentAttendance["ACCEPTED"] = 2] = "ACCEPTED"; })(AppointmentAttendance || (exports.AppointmentAttendance = AppointmentAttendance = {})); /** * The info about the appointment notification. */ class AppointmentNotification extends resource_model_1.Resource { load(x) { super.load(x); this.method = this.clean(x.method, String); this.minutes = this.clean(x.minutes, Number, 0); } } exports.AppointmentNotification = AppointmentNotification; /** * Possible notification methods (currently supported for Google Calendars and internal calendars). */ var AppointmentNotificationMethods; (function (AppointmentNotificationMethods) { AppointmentNotificationMethods["PUSH"] = "PUSH"; AppointmentNotificationMethods["EMAIL"] = "EMAIL"; })(AppointmentNotificationMethods || (exports.AppointmentNotificationMethods = AppointmentNotificationMethods = {})); /** * Possible notification units of time. */ var AppointmentNotificationUnitsOfTime; (function (AppointmentNotificationUnitsOfTime) { AppointmentNotificationUnitsOfTime["MINUTES"] = "MINUTES"; AppointmentNotificationUnitsOfTime["HOURS"] = "HOURS"; AppointmentNotificationUnitsOfTime["DAYS"] = "DAYS"; AppointmentNotificationUnitsOfTime["WEEKS"] = "WEEKS"; })(AppointmentNotificationUnitsOfTime || (exports.AppointmentNotificationUnitsOfTime = AppointmentNotificationUnitsOfTime = {}));