src/meetings/MeetingManager.js
import {EventEmitter} from '../eventemitter';
import {bindMethods} from '../utils';
import Meeting from './Meeting';
/**
* ContactManager instance is obtained by calling the {@link Session#getMeetingManager}
* method of {@link Session} and must not be directly instantiated.
* Once the MeetingManager instance is obtained {@link MeetingManager#init} method
* must be called to initialize it.
*
* ## Events
*
* - **`create`** is emitted every time a new meeting is created.
* - {@link Meeting} `meeting` The meeting that has just been created.
* - **`delete`** is emitted when some meeting is deleted.
* - {@link Meeting} `meeting` The meeting that has just been deleted.
*
* @example <caption>Get meeting list</caption>
* meetingManager.init().then(function() {
* meetingManager.getMeetings().forEach(function(meeting) {
* console.log(meeting.name);
* });
* });
*/
export class MeetingManager extends EventEmitter {
/** @protected */
constructor(meetingService) {
super();
this._meetingService = meetingService;
/**
* @type {Array<Meeting>}
*/
this._meetings = [];
/**
* @type {Promise}
*/
this._initializing = null;
/**
* The text to be sent by SMS to the participants in the meetings. The {{url}} string will be expanded with the
* meeting link
*
* @type {String}
*/
this._message = '';
bindMethods(this, [
'onUserInMeeting',
'onLocalMeetingRemove',
]);
}
/**
* Initializes the meeting manager
* @param {Object} query Object used for filtering the meetings
* @returns {Promise<ContactManager, Error>} A promise that returns when fulfilled
* the contact manager instance
*/
init(query = {}) {
if (this._initializing !== null) {
return this._initializing;
}
this._meetingService.emitter.on('update', this.onUserInMeeting);
this._initializing = this._meetingService.get(query).then((meetings) => {
meetings.forEach((meeting) => {
if (this._meetings.some(elem => elem.id === meeting.id)) {
return meeting;
}
let oMeeting = new Meeting(this._meetingService, meeting);
this._meetings.push(oMeeting);
this.emit('meeting-recovered', oMeeting);
});
return this;
});
return this._initializing;
}
/**
* Uninitializes the meeting manager
* @returns {Promise<undefined, Error>} A promise that is fulfilled when unitialization finishes
*/
uninit() {
if (this._initializing === null) {
return Promise.resolve();
}
return this._initializing.then(() => {
this._meetingService.emitter.off('update', this.onUserInMeeting);
this._meetings = [];
this._initializing = null;
});
}
/**
* Creates a meeting
* @param {string} name The name of the meeting.
* @param {Object[]} participants The participants of the new meeting session.
* @param {number} validSince The timestamp of the moment when the meeting starts.
* @param {boolean} [sendSmsViaWac=false] If true, an invitation for the meeting will be sent in an SMS by the server.
* @return {Promise<Meeting>} The just created meeting
*/
createMeeting(name, participants, validSince, sendSmsViaWac = false) {
return Promise.resolve().then(() => {
this._checkInitializingOfService();
if (sendSmsViaWac) {
participants = this._insertSendSMSFlagInParticipants(participants);
}
return this._meetingService.create({name, participants, validSince});
}).then((meetingCreated) => {
return {
meeting: this._addMeeting(meetingCreated),
phones: this._getPhonesFromParticipants(participants),
};
});
}
/**
* Update a meeting
* @param {String} id Meeting id
* @param {String} name Name of the meeting updated
* @param {Array} participants Array with the participants of the meeting updated
* @param {Object} validSince Updated date formatted string
* @param {boolean} sendSmsViaWac Flag used to decided
*/
updateMeeting(id, name, participants, validSince, sendSmsViaWac) {
return Promise.resolve().then(() => {
this._checkInitializingOfService();
if (sendSmsViaWac) {
participants = this._insertSendSMSFlagInParticipants(participants);
}
return this._meetingService.update(id, {name, participants, validSince});
}).then((meetingUpdated) => {
this._updateMeeting(meetingUpdated);
return meetingUpdated;
});
}
/**
* Insert a flag in each participant to indicate if the WAC
* has to send the invite or not
* @params {Array<Object>} participants
* @return {Array<Object} Updated participants
*/
_insertSendSMSFlagInParticipants(participants) {
return participants.map((participant) => {
participant.sendSMS = true;
return participant;
});
}
/**
* Retrieves a list with the available meetings
* @return {Array<Meetings>}
*/
getMeetings() {
return this._meetings;
}
/**
* Set the message to send in a SMS
* @param {String} value Text for the SMS
*/
set message(value) {
this._message = value;
}
/**
* Adds a new contact to the list
* @private
* @param {Meeting} data
* @return {Meeting} The new created meeting
*/
_addMeeting(data) {
if (this._meetings.some(meeting => meeting.id === data.id)) {
return;
}
const meeting = new Meeting(this._meetingService, data);
this._meetings.push(meeting);
this.emit('create', meeting);
return meeting;
}
/**
* Update an exisitng meeting in the meeting list
* @private
* @param {Meeting} data The updated meeting
*/
_updateMeeting(data) {
let index = this._meetings.findIndex(meeting => meeting.id === data.id);
if (index < 0) {
return;
}
this._meetings[index] = new Meeting(this._meetingService, data);
}
/**
* Remove an existing meeting from the list
* @private
* @param {string} id ID of the meeting to remove
* @return {Meeting} The just removed meeting if any
*/
_rmMeeting(id) {
let index = this._meetings.findIndex(meeting => meeting.id === id);
if (index < 0) {
return;
}
let meeting = this._meetings.splice(index, 1)[0];
meeting.off('delete', this.onLocalMeetingRemove);
return meeting;
}
/**
* Internal callback for Meeting event
* @private
* @param {Meeting} meeting
*/
onLocalMeetingRemove(meeting) {
if (!this._rmMeeting(meeting.id)) {
this.emit('delete', meeting);
}
}
/**
* Internal callback for WAC event
* @private
* @param {Object} eventMeeting
*/
onUserInMeeting(eventMeeting) {
let meeting = this._meetings.find(elem => eventMeeting.id === elem.id);
if (!meeting) {
return;
}
meeting.phone = eventMeeting.phone;
if (meeting.phone !== '') {
this.emit('participant-connected');
} else {
this.emit('participant-disconnected');
}
}
_checkInitializingOfService() {
if (this._initializing === null) {
throw new Error('MeetingManager not initialized');
}
}
/**
* Get phones that are used to create the meeting
* @param {string[]} participants A list of objects
* @return {string[]} A list that contains phones
*/
_getPhonesFromParticipants(participants) {
return participants.map(participant => participant.phone).filter(phone => phone);
}
}