src/groups/GroupManager.js
import {List} from 'immutable';
import {bindMethods} from '../utils/bindMethods';
import {Group} from './Group';
import {EventEmitter} from '../eventemitter';
function comparator(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
}
/**
* This class allows manager the groups. To obtain an instance of the
* class @link {Session#getGroupManager} method must be used.
*
* # Events
* - `groups` - Emitted every time a group list changes.
*/
export class GroupManager {
/** @protected */
static newInstance(groupService, phonebookService, userManager) {
const groupManager = new GroupManager(groupService, phonebookService, userManager);
return groupManager.init();
}
/** @private */
constructor(groupService, phonebookService, userManager) {
/** @private */
this.groupService = groupService;
/** @private */
this.phonebookService = phonebookService;
/** @private */
this.userManager = userManager;
/** @private */
this.groups = List();
/** @type {EventEmitter} */
this.emitter = new EventEmitter();
bindMethods(this, [
'onDelete',
'onPut',
]);
}
/** @private */
async init() {
this.groupService.emitter.on('put', this.onPut);
this.groupService.emitter.on('delete', this.onDelete);
const groups = await this.groupService.fetch();
for (const group of groups) {
group.participants = await this.convertToAddresses(group.participants);
}
this.groups = List.of(...await Promise.all(groups.map(datum => this.newGroup(datum))));
this.groups = this.groups.sort(comparator);
return this;
}
/** @protected */
uninit() {
this.groupService.emitter.off('put', this.onPut);
this.groupService.emitter.off('delete', this.onDelete);
}
/** @private */
async convertToAddresses(ids) {
let participants = [];
for (const id of ids) {
const user = await this.userManager.resolveUser(id);
participants.push(`${user.username}@${user.domain}`);
}
return participants;
}
/** @private */
async convertToIds(participants) {
let ids = [];
for (const participant of participants) {
const user = await this.userManager.resolveUser(participant);
ids.push(user.id);
}
return ids;
}
/** @private */
async onPut(event) {
event.participants = await this.convertToAddresses(event.participants);
const index = this.groups.findIndex(group => group.getId() === event.id);
const group = await this.newGroup(event);
if (index < 0) {
this.groups = this.groups.push(group);
} else {
this.groups = this.groups.set(index, group);
}
this.groups = this.groups.sort(comparator);
this.emitter.emit('groups');
return group;
}
/** @private */
onDelete({id}) {
this.groups = this.groups.filter(group => group.getId() !== id);
this.emitter.emit('groups');
}
/** @private */
async newGroup({id, name, participants}) {
const res = await this.phonebookService.getPhonebooksBySubscriberId(id);
const phonebook = res.map(p => p.contacts).reduce((acc, value) => acc.concat(value), []);
return Group.of({id, name, participants, phonebook});
}
/**
* Allows access to the list of groups
* @return {ImmutableList<Group>}
*/
getGroups() {
return this.groups;
}
/**
* Creates a new group
* @param {string} name The name of the new group
* @param {string[]} participants List of the addresses of the initial participants
* @return {Promise<Group>}
*/
async createGroup(name, participants) {
const participantIds = await this.convertToIds(participants);
const datum = await this.groupService.create(name, participantIds);
const group = await this.onPut(datum);
return group;
}
/**
* Saves a group (Still no WAC support)
* @experimental
* @param {Group} group The group to be persisted
* @return {Promise}
*/
async saveGroup(group) {
const participantIds = await this.convertToIds(group.getParticipants().toJS());
await this.groupService.update(group.getId(), group.getName(), participantIds);
}
/**
* Deletes a group
* @param {Group} group The group to be deleted
* @return {Promise}
*/
async deleteGroup(group) {
await this.groupService.delete(group.getId());
await this.onDelete({id: group.getId()});
}
/**
* Obtain phonebooks asociated with a group. Phonebooks are a list of contacts
* many groups can susbscribe to.
*
* @return {Array} containing the phonebooks asociated to the group
* @property {string[]} subscribers ids of the group subscribers
* @property {string} name phonebookName
* @property {string} id phonebookId
* @property {Object[]} contacts list of ponebook contacts
* @property {string} contacts.name contact name
* @property {string} contacts.address contact address
* @deprecated
*/
getPhonebook(group) {
return this.phonebookService.getPhonebooksBySubscriberId(group.getId());
}
}