Skip to content

Commit

Permalink
feat(Alarm): Add support for email alarm type
Browse files Browse the repository at this point in the history
In ICalAlarm, the methods `summary()`, `createAttendee()` and `attendees()` have been added to support `EMAIL` alarms in addition to `DISPLAY` and `AUDIO`.

close #576
  • Loading branch information
sebbo2002 committed Feb 29, 2024
1 parent 9174a32 commit 5398f09
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 17 deletions.
115 changes: 109 additions & 6 deletions src/alarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import {
generateCustomAttributes,
checkDate,
toDurationString,
toJSON
toJSON,
checkNameAndMail
} from './tools.js';
import {ICalDateTimeValue} from './types.js';
import ICalAttendee, { ICalAttendeeData } from './attendee.js';


export enum ICalAlarmType {
display = 'display',
audio = 'audio'
audio = 'audio',
email = 'email'
}

export const ICalAlarmRelatesTo = {
Expand Down Expand Up @@ -47,6 +50,8 @@ export interface ICalAlarmBaseData {
repeat?: ICalAlarmRepeatData | null;
attach?: string | ICalAttachment | null;
description?: string | null;
summary?: string | null;
attendees?: ICalAttendee[] | ICalAttendeeData[];
x?: {key: string, value: string}[] | [string, string][] | Record<string, string>;
}

Expand All @@ -63,6 +68,8 @@ interface ICalInternalAlarmData {
interval: number | null;
attach: ICalAttachment | null;
description: string | null;
summary: string | null;
attendees: ICalAttendee[];
x: [string, string][];
}

Expand All @@ -74,6 +81,8 @@ export interface ICalAlarmJSONData {
interval: number | null;
attach: ICalAttachment | null;
description: string | null;
summary: string | null;
attendees: ICalAttendee[];
x: {key: string, value: string}[];
}

Expand Down Expand Up @@ -116,6 +125,8 @@ export default class ICalAlarm {
interval: null,
attach: null,
description: null,
summary: null,
attendees: [],
x: []
};

Expand All @@ -131,6 +142,8 @@ export default class ICalAlarm {
data.repeat && this.repeat(data.repeat);
data.attach !== undefined && this.attach(data.attach);
data.description !== undefined && this.description(data.description);
data.summary !== undefined && this.summary(data.summary);
data.attendees !== undefined && this.attendees(data.attendees);
data.x !== undefined && this.x(data.x);
}

Expand Down Expand Up @@ -467,15 +480,17 @@ export default class ICalAlarm {

/**
* Get the alarm description. Used to set the alarm message
* if alarm type is display. Defaults to the event's summary.
* if alarm type is `display`. If the alarm type is `email`, it's
* used to set the email body. Defaults to the event's summary.
*
* @since 0.2.1
*/
description (): string | null;

/**
* Set the alarm description. Used to set the alarm message
* if alarm type is display. Defaults to the event's summary.
* if alarm type is `display`. If the alarm type is `email`, it's
* used to set the email body. Defaults to the event's summary.
*
* @since 0.2.1
*/
Expand All @@ -494,6 +509,79 @@ export default class ICalAlarm {
}


/**
* Get the alarm summary. Used to set the email subject
* if alarm type is `email`. Defaults to the event's summary.
*
* @since 7.0.0
*/
summary (): string | null;

/**
* Set the alarm summary. Used to set the email subject
* if alarm type is display. Defaults to the event's summary.
*
* @since 0.2.1
*/
summary (summary: string | null): this;
summary (summary?: string | null): this | string | null {
if (summary === undefined) {
return this.data.summary;
}
if (!summary) {
this.data.summary = null;
return this;
}

this.data.summary = summary;
return this;
}


/**
* Creates a new {@link ICalAttendee} and returns it. Use options to prefill
* the attendee's attributes. Calling this method without options will create
* an empty attendee.
*
* @since 7.0.0
*/
createAttendee(data: ICalAttendee | ICalAttendeeData | string): ICalAttendee {
if (data instanceof ICalAttendee) {
this.data.attendees.push(data);
return data;
}
if (typeof data === 'string') {
data = { email: data, ...checkNameAndMail('data', data) };
}

const attendee = new ICalAttendee(data, this);
this.data.attendees.push(attendee);
return attendee;
}


/**
* Get all attendees
* @since 7.0.0
*/
attendees(): ICalAttendee[];

/**
* Add multiple attendees to your event
*
* @since 7.0.0
*/
attendees(attendees: (ICalAttendee | ICalAttendeeData | string)[]): this;
attendees(attendees?: (ICalAttendee | ICalAttendeeData | string)[]): this | ICalAttendee[] {
if (!attendees) {
return this.data.attendees;
}

attendees.forEach(attendee => this.createAttendee(attendee));
return this;
}


/**
* Set X-* attributes. Woun't filter double attributes,
* which are also added by another method (e.g. type),
Expand Down Expand Up @@ -627,13 +715,28 @@ export default class ICalAlarm {
}

// DESCRIPTION
if (this.data.type === 'display' && this.data.description) {
if (this.data.type !== 'audio' && this.data.description) {
g += 'DESCRIPTION:' + escape(this.data.description, false) + '\r\n';
}
else if (this.data.type === 'display') {
else if (this.data.type !== 'audio') {
g += 'DESCRIPTION:' + escape(this.event.summary(), false) + '\r\n';
}

// SUMMARY
if (this.data.type === 'email' && this.data.summary) {
g += 'SUMMARY:' + escape(this.data.summary, false) + '\r\n';
}
else if (this.data.type === 'email') {
g += 'SUMMARY:' + escape(this.event.summary(), false) + '\r\n';
}

// ATTENDEES
if (this.data.type === 'email') {
this.data.attendees.forEach(attendee => {
g += attendee.toString();
});
}

// CUSTOM X ATTRIBUTES
g += generateCustomAttributes(this.data);

Expand Down
23 changes: 12 additions & 11 deletions src/attendee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import {addOrGetCustomAttributes, checkEnum, checkNameAndMail, escape} from './tools.js';
import ICalEvent from './event.js';
import ICalAlarm from './alarm.js';


interface ICalInternalAttendeeData {
Expand Down Expand Up @@ -94,16 +95,16 @@ export enum ICalAttendeeType {
*/
export default class ICalAttendee {
private readonly data: ICalInternalAttendeeData;
private readonly event: ICalEvent;
private readonly parent: ICalEvent | ICalAlarm;

/**
* Constructor of {@link ICalAttendee}. The event reference is
* required to query the calendar's timezone when required.
*
* @param data Attendee Data
* @param event Reference to ICalEvent object
* @param parent Reference to ICalEvent object
*/
constructor(data: ICalAttendeeData, event: ICalEvent) {
constructor(data: ICalAttendeeData, parent: ICalEvent | ICalAlarm) {
this.data = {
name: null,
email: '',
Expand All @@ -117,8 +118,8 @@ export default class ICalAttendee {
delegatedFrom: null,
x: []
};
this.event = event;
if (!this.event) {
this.parent = parent;
if (!this.parent) {
throw new Error('`event` option required!');
}
if (!data.email) {
Expand Down Expand Up @@ -367,14 +368,14 @@ export default class ICalAttendee {
if(typeof delegatedTo === 'string') {
this.data.delegatedTo = new ICalAttendee(
{ email: delegatedTo, ...checkNameAndMail('delegatedTo', delegatedTo) },
this.event,
this.parent,
);
}
else if(delegatedTo instanceof ICalAttendee) {
this.data.delegatedTo = delegatedTo;
}
else {
this.data.delegatedTo = new ICalAttendee(delegatedTo, this.event);
this.data.delegatedTo = new ICalAttendee(delegatedTo, this.parent);
}

this.data.status = ICalAttendeeStatus.DELEGATED;
Expand Down Expand Up @@ -409,14 +410,14 @@ export default class ICalAttendee {
else if(typeof delegatedFrom === 'string') {
this.data.delegatedFrom = new ICalAttendee(
{ email: delegatedFrom, ...checkNameAndMail('delegatedFrom', delegatedFrom) },
this.event,
this.parent,
);
}
else if(delegatedFrom instanceof ICalAttendee) {
this.data.delegatedFrom = delegatedFrom;
}
else {
this.data.delegatedFrom = new ICalAttendee(delegatedFrom, this.event);
this.data.delegatedFrom = new ICalAttendee(delegatedFrom, this.parent);
}

return this;
Expand All @@ -439,7 +440,7 @@ export default class ICalAttendee {
* @since 0.2.0
*/
delegatesTo (options: ICalAttendee | ICalAttendeeData | string): ICalAttendee {
const a = options instanceof ICalAttendee ? options : this.event.createAttendee(options);
const a = options instanceof ICalAttendee ? options : this.parent.createAttendee(options);
this.delegatedTo(a);
a.delegatedFrom(this);
return a;
Expand All @@ -462,7 +463,7 @@ export default class ICalAttendee {
* @since 0.2.0
*/
delegatesFrom (options: ICalAttendee | ICalAttendeeData | string): ICalAttendee {
const a = options instanceof ICalAttendee ? options : this.event.createAttendee(options);
const a = options instanceof ICalAttendee ? options : this.parent.createAttendee(options);
this.delegatedFrom(a);
a.delegatedTo(this);
return a;
Expand Down
Loading

0 comments on commit 5398f09

Please sign in to comment.