Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
464616b
[FIX] Units filter not working on current chats panel
Aug 25, 2022
bd79f6d
Merge branch 'develop' into current-chats-units-filter
murtaza98 Aug 29, 2022
b108e3b
Old rooms without the associated unit will not be displayed on the cu…
Aug 29, 2022
afef7ba
Fix issues in previous commit
Aug 29, 2022
6b9a93d
Fix typescript issues
Aug 29, 2022
3e5c755
CRS
Aug 29, 2022
2c143b9
Merge branch 'develop' into current-chats-units-filter
Aug 30, 2022
2971bbe
Simplify LivechatRooms model for EE
Aug 30, 2022
62a8306
Fix builds: load EE omni models only if license if present
Aug 30, 2022
54fc670
Merge branch 'develop' into current-chats-units-filter
murtaza98 Sep 5, 2022
cc206ea
Merge branch 'develop' into current-chats-units-filter
murtaza98 Sep 5, 2022
ecca87e
Update apps/meteor/ee/app/models/server/models/LivechatUnit.js
murtaza98 Sep 5, 2022
250d7dc
CRS
Sep 5, 2022
172344d
more CRS: Converting some EE livechat room model method
Sep 5, 2022
a1ed234
Merge branch 'develop' into current-chats-units-filter
Sep 13, 2022
dc88a03
CRS
Sep 13, 2022
3e8e240
Merge branch 'develop' into current-chats-units-filter
Sep 15, 2022
e81c89c
Remove monitor from any connected units when they are removed as monitor
Sep 15, 2022
4b0cac1
CRS
Sep 16, 2022
461847d
Merge branch 'develop' into current-chats-units-filter
kodiakhq[bot] Sep 22, 2022
5f032c5
Merge branch 'develop' into current-chats-units-filter
kodiakhq[bot] Sep 22, 2022
dcf3d4a
Merge branch 'develop' into current-chats-units-filter
kodiakhq[bot] Sep 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions apps/meteor/ee/app/license/server/getStatistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,51 @@ import { log } from 'console';

import { CannedResponse, LivechatPriority, LivechatTag, LivechatUnit } from '@rocket.chat/models';

import { getModules, getTags } from './license';
import { getModules, getTags, hasLicense } from './license';
import { Analytics } from '../../../../server/sdk';

type ENTERPRISE_STATISTICS = {
type ENTERPRISE_STATISTICS = GenericStats & Partial<EEOnlyStats>;

type GenericStats = {
modules: string[];
tags: string[];
seatRequests: number;
};

type EEOnlyStats = {
livechatTags: number;
cannedResponses: number;
priorities: number;
businessUnits: number;
};

export async function getStatistics(): Promise<ENTERPRISE_STATISTICS> {
const statsPms: Array<Promise<any>> = [];
const genericStats: GenericStats = {
modules: getModules(),
tags: getTags().map(({ name }) => name),
seatRequests: await Analytics.getSeatRequestCount(),
};

const statistics: ENTERPRISE_STATISTICS = {} as any;
const eeModelsStats = await getEEStatistics();

const modules = getModules();
statistics.modules = modules;
const statistics = {
...genericStats,
...eeModelsStats,
};

const tags = getTags().map(({ name }) => name);
statistics.tags = tags;
return statistics;
}

// These models are only available on EE license so don't import them inside CE license as it will break the build
async function getEEStatistics(): Promise<EEOnlyStats | undefined> {
if (!hasLicense('livechat-enterprise')) {
return;
}

const statsPms: Array<Promise<any>> = [];

const statistics: Partial<EEOnlyStats> = {};

statsPms.push(
Analytics.getSeatRequestCount().then((count) => {
statistics.seatRequests = count;
}),
);
// Number of livechat tags
statsPms.push(
LivechatTag.col.count().then((count) => {
Expand Down Expand Up @@ -66,5 +82,6 @@ export async function getStatistics(): Promise<ENTERPRISE_STATISTICS> {
);

await Promise.all(statsPms).catch(log);
return statistics;

return statistics as EEOnlyStats;
}
6 changes: 4 additions & 2 deletions apps/meteor/ee/app/livechat-enterprise/server/api/units.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { IOmnichannelBusinessUnit } from '@rocket.chat/core-typings';

import { API } from '../../../../../app/api/server';
import { findUnits, findUnitById, findUnitMonitors } from './lib/units';
import { LivechatEnterprise } from '../lib/LivechatEnterprise';
Expand Down Expand Up @@ -44,7 +46,7 @@ API.v1.addRoute(
},
async post() {
const { unitData, unitMonitors, unitDepartments } = this.bodyParams;
return API.v1.success(LivechatEnterprise.saveUnit(null, unitData, unitMonitors, unitDepartments));
return API.v1.success(LivechatEnterprise.saveUnit(null, unitData, unitMonitors, unitDepartments) as IOmnichannelBusinessUnit);
},
},
);
Expand All @@ -65,7 +67,7 @@ API.v1.addRoute(
const { unitData, unitMonitors, unitDepartments } = this.bodyParams;
const { id } = this.urlParams;

return LivechatEnterprise.saveUnit(id, unitData, unitMonitors, unitDepartments);
return API.v1.success(LivechatEnterprise.saveUnit(id, unitData, unitMonitors, unitDepartments) as IOmnichannelBusinessUnit);
},
async delete() {
const { id } = this.urlParams;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LivechatRooms } from '@rocket.chat/models';

import { callbacks } from '../../../../../lib/callbacks';
import LivechatRooms from '../../../../../app/models/server/models/LivechatRooms';
import LivechatDepartment from '../../../../../app/models/server/models/LivechatDepartment';

callbacks.add(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { LivechatRooms } from '@rocket.chat/models';

import { callbacks } from '../../../../../lib/callbacks';
import LivechatRooms from '../../../../../app/models/server/models/LivechatRooms';

callbacks.add(
'livechat.afterForwardChatToAgent',
(options: { rid?: string } = {}) => {
const { rid } = options;

const room = LivechatRooms.findOneById(rid);
if (!room) {
if (!rid) {
return options;
}

(LivechatRooms as any).unsetPredictedVisitorAbandonmentByRoomId(rid);
Promise.await(LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(rid));

return options;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LivechatRooms } from '@rocket.chat/models';

import { callbacks } from '../../../../../lib/callbacks';
import LivechatRooms from '../../../../../app/models/server/models/LivechatRooms';
import LivechatDepartment from '../../../../../app/models/server/models/LivechatDepartment';
import { cbLogger } from '../lib/logger';

Expand All @@ -8,12 +9,12 @@ callbacks.add(
(options) => {
const { rid, newDepartmentId } = options;

const room = LivechatRooms.findOneById(rid);
const room = Promise.await(LivechatRooms.findOneById(rid));
if (!room) {
cbLogger.debug('Skipping callback. No room found');
return options;
}
LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(room._id);
Promise.await(LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(room._id));

const department = LivechatDepartment.findOneById(newDepartmentId, {
fields: { ancestors: 1 },
Expand All @@ -31,7 +32,7 @@ callbacks.add(
}

cbLogger.debug(`Updating department ${newDepartmentId} ancestors for room ${rid}`);
LivechatRooms.updateDepartmentAncestorsById(room._id, ancestors);
Promise.await(LivechatRooms.updateDepartmentAncestorsById(room._id, ancestors));

return options;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
import { LivechatRooms } from '@rocket.chat/models';

import { callbacks } from '../../../../../lib/callbacks';
import { LivechatRooms } from '../../../../../app/models/server';
import { settings } from '../../../../../app/settings/server';
import { cbLogger } from '../lib/logger';

const unsetPredictedVisitorAbandonment = ({ room }: { room: any }): void => {
const unsetPredictedVisitorAbandonment = ({ room }: { room: IOmnichannelRoom }): void => {
if (!room?._id || !room?.omnichannel?.predictedVisitorAbandonmentAt) {
cbLogger.debug('Skipping callback. No room or no visitor abandonment info');
return;
}

(LivechatRooms as any).unsetPredictedVisitorAbandonmentByRoomId(room._id);
Promise.await(LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(room._id));
};

settings.watch('Livechat_abandoned_rooms_action', (value) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
import { LivechatInquiry } from '@rocket.chat/models';
import { LivechatInquiry, Users } from '@rocket.chat/models';

import LivechatUnit from '../../../models/server/models/LivechatUnit';
import LivechatTag from '../../../models/server/models/LivechatTag';
import { Users, LivechatRooms, Subscriptions, Messages } from '../../../../../app/models/server';
import { LivechatRooms, Subscriptions, Messages } from '../../../../../app/models/server';
import LivechatPriority from '../../../models/server/models/LivechatPriority';
import { addUserRoles } from '../../../../../server/lib/roles/addUserRoles';
import { removeUserFromRoles } from '../../../../../server/lib/roles/removeUserFromRoles';
Expand All @@ -20,12 +20,13 @@ import { settings } from '../../../../../app/settings/server';
import { logger, queueLogger } from './logger';
import { callbacks } from '../../../../../lib/callbacks';
import { AutoCloseOnHoldScheduler } from './AutoCloseOnHoldScheduler';
import { LivechatUnitMonitors } from '../../../models/server';

export const LivechatEnterprise = {
addMonitor(username) {
async addMonitor(username) {
check(username, String);

const user = Users.findOneByUsername(username, { fields: { _id: 1, username: 1 } });
const user = await Users.findOneByUsername(username, { fields: { _id: 1, username: 1 } });

if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
Expand All @@ -40,22 +41,26 @@ export const LivechatEnterprise = {
return false;
},

removeMonitor(username) {
async removeMonitor(username) {
check(username, String);

const user = Users.findOneByUsername(username, { fields: { _id: 1 } });
const user = await Users.findOneByUsername(username, { fields: { _id: 1 } });

if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'livechat:removeMonitor',
});
}

if (removeUserFromRoles(user._id, ['livechat-monitor'])) {
return true;
const removeRoleResult = removeUserFromRoles(user._id, ['livechat-monitor']);
if (!removeRoleResult) {
return false;
}

return false;
// remove this monitor from any unit it is assigned to
LivechatUnitMonitors.removeByMonitorId(user._id);

return true;
},

removeUnit(_id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { SyncedCron } from 'meteor/littledata:synced-cron';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import { Meteor } from 'meteor/meteor';
import { LivechatVisitors } from '@rocket.chat/models';
import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models';

import { settings } from '../../../../../app/settings/server';
import { LivechatRooms, LivechatDepartment, Users } from '../../../../../app/models/server';
import { LivechatDepartment, Users } from '../../../../../app/models/server';
import { Livechat } from '../../../../../app/livechat/server/lib/Livechat';
import { LivechatEnterprise } from './LivechatEnterprise';

Expand Down Expand Up @@ -91,15 +91,16 @@ export class VisitorInactivityMonitor {
const guest = visitor.name || visitor.username;
const comment = TAPi18n.__('Omnichannel_On_Hold_due_to_inactivity', { guest, timeout });

LivechatEnterprise.placeRoomOnHold(room, comment, this.user) && LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(room._id);
LivechatEnterprise.placeRoomOnHold(room, comment, this.user) &&
(await LivechatRooms.unsetPredictedVisitorAbandonmentByRoomId(room._id));
}

handleAbandonedRooms() {
const action = settings.get('Livechat_abandoned_rooms_action');
if (!action || action === 'none') {
return;
}
LivechatRooms.findAbandonedOpenRooms(new Date()).forEach((room) => {
Promise.await(LivechatRooms.findAbandonedOpenRooms(new Date())).forEach((room) => {
switch (action) {
case 'close': {
this.closeRooms(room);
Expand Down
1 change: 0 additions & 1 deletion apps/meteor/ee/app/models/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import './models/LivechatRooms';
import './models/LivechatInquiry';
import './models/Messages';
import './models/Users';
import './raw/LivechatRooms';
import './raw/LivechatDepartmentAgents';

export { CannedResponse, LivechatTag, LivechatUnit, LivechatUnitMonitors, LivechatPriority };
28 changes: 1 addition & 27 deletions apps/meteor/ee/app/models/server/models/LivechatRooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,9 @@ overwriteClassOnLicense('livechat-enterprise', LivechatRooms, {
find: applyRestrictions('find'),
update: applyRestrictions('update'),
remove: applyRestrictions('remove'),
updateDepartmentAncestorsById(originalFn, _id, departmentAncestors) {
const query = {
_id,
};
const update = departmentAncestors ? { $set: { departmentAncestors } } : { $unset: { departmentAncestors: 1 } };
return this.update(query, update);
},
});

// TODO: Engineering day - Move all these methods to the LivechatRooms model - apps/meteor/ee/server/models/raw/LivechatRooms.ts
LivechatRooms.prototype.setPredictedVisitorAbandonment = function (roomId, willBeAbandonedAt) {
const query = {
_id: roomId,
Expand All @@ -36,15 +30,6 @@ LivechatRooms.prototype.setPredictedVisitorAbandonment = function (roomId, willB
return this.update(query, update);
};

LivechatRooms.prototype.findAbandonedOpenRooms = function (date) {
return this.find({
'omnichannel.predictedVisitorAbandonmentAt': { $lte: date },
'waitingResponse': { $exists: false },
'closedAt': { $exists: false },
'open': true,
});
};

LivechatRooms.prototype.setOnHold = function (roomId) {
return this.update({ _id: roomId }, { $set: { onHold: true } });
};
Expand All @@ -69,17 +54,6 @@ LivechatRooms.prototype.unsetPredictedVisitorAbandonment = function () {
);
};

LivechatRooms.prototype.unsetPredictedVisitorAbandonmentByRoomId = function (roomId) {
return this.update(
{
_id: roomId,
},
{
$unset: { 'omnichannel.predictedVisitorAbandonmentAt': 1 },
},
);
};

LivechatRooms.prototype.unsetAllOnHoldFieldsByRoomId = function (roomId) {
return this.update(
{
Expand Down
9 changes: 8 additions & 1 deletion apps/meteor/ee/app/models/server/models/LivechatUnit.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import _ from 'underscore';
import { LivechatRooms } from '@rocket.chat/models';

import LivechatDepartmentInstance, { LivechatDepartment } from '../../../../../app/models/server/models/LivechatDepartment';
import { getUnitsFromUser } from '../../../livechat-enterprise/server/lib/units';
Expand Down Expand Up @@ -105,7 +106,12 @@ export class LivechatUnit extends LivechatDepartment {
);
});

return _.extend(record, { _id });
Promise.await(LivechatRooms.associateRoomsWithDepartmentToUnit(departmentsToSave, _id));

return {
...record,
...(_id && { _id }),
};
}

// REMOVE
Expand All @@ -129,6 +135,7 @@ export class LivechatUnit extends LivechatDepartment {
removeById(_id) {
LivechatUnitMonitors.removeByUnitId(_id);
this.removeParentAndAncestorById(_id);
Promise.await(LivechatRooms.removeUnitAssociationFromRooms(_id));

const query = { _id };
return this.remove(query);
Expand Down
25 changes: 0 additions & 25 deletions apps/meteor/ee/app/models/server/raw/LivechatRooms.js

This file was deleted.

6 changes: 6 additions & 0 deletions apps/meteor/ee/server/models/LivechatRooms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { registerModel } from '@rocket.chat/models';

import { db } from '../../../server/database/utils';
import { LivechatRoomsRawEE } from './raw/LivechatRooms';

registerModel('ILivechatRoomsModel', new LivechatRoomsRawEE(db));
Loading