Skip to content

Commit 7cbb029

Browse files
Merge branch 'develop' into replace-oauth2-server-lib
2 parents 63b9220 + 3fda478 commit 7cbb029

File tree

47 files changed

+699
-522
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+699
-522
lines changed

.changeset/dry-jeans-thank.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rocket.chat/meteor": patch
3+
---
4+
5+
Fixes an issue that allowed departments to be removed via API even with setting `Omnichannel_enable_department_removal` disabled

.changeset/funny-ears-kick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rocket.chat/meteor': patch
3+
---
4+
5+
Fixes a rerender on each sidebar item click

.changeset/slow-flies-hear.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@rocket.chat/meteor": minor
3+
"@rocket.chat/core-typings": minor
4+
"@rocket.chat/model-typings": minor
5+
---
6+
7+
Replaces Livechat Visitors by Contacts on workspaces' MAC count.
8+
This allows a more accurate and potentially smaller MAC count in case Contact Identification is enabled, since multiple visitors may be associated to the same contact.

apps/meteor/app/cloud/server/functions/buildRegistrationData.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { LivechatRooms, Statistics, Users } from '@rocket.chat/models';
1+
import { LivechatContacts, Statistics, Users } from '@rocket.chat/models';
22
import moment from 'moment';
33

44
import { settings } from '../../../settings/server';
@@ -69,7 +69,7 @@ export async function buildWorkspaceRegistrationData<T extends string | undefine
6969
const workspaceType = settings.get<string>('Server_Type');
7070

7171
const seats = await Users.getActiveLocalUserCount();
72-
const [macs] = await LivechatRooms.getMACStatisticsForPeriod(moment.utc().format('YYYY-MM'));
72+
const MAC = await LivechatContacts.countContactsOnPeriod(moment.utc().format('YYYY-MM'));
7373

7474
const license = settings.get<string>('Enterprise_License');
7575

@@ -102,7 +102,7 @@ export async function buildWorkspaceRegistrationData<T extends string | undefine
102102
setupComplete: setupWizardState === 'completed',
103103
connectionDisable: false,
104104
npsEnabled,
105-
MAC: macs?.contactsCount ?? 0,
105+
MAC,
106106
// activeContactsBillingMonth: stats.omnichannelContactsBySource.contactsCount,
107107
// activeContactsYesterday: stats.uniqueContactsOfYesterday.contactsCount,
108108
statsToken: stats.statsToken,

apps/meteor/app/livechat-enterprise/client/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { hasLicense } from '../../license/client';
2-
import './startup';
32

43
void hasLicense('livechat-enterprise').then((enabled) => {
54
if (!enabled) {

apps/meteor/app/livechat-enterprise/client/startup.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { useSetting } from '@rocket.chat/ui-contexts';
2+
import { useEffect } from 'react';
3+
4+
import { useHasLicenseModule } from '../../../client/hooks/useHasLicenseModule';
5+
import { businessHourManager } from '../../livechat/client/views/app/business-hours/BusinessHours';
6+
import type { IBusinessHourBehavior } from '../../livechat/client/views/app/business-hours/IBusinessHourBehavior';
7+
import { SingleBusinessHourBehavior } from '../../livechat/client/views/app/business-hours/Single';
8+
import { MultipleBusinessHoursBehavior } from '../client/views/business-hours/Multiple';
9+
10+
const businessHours: Record<string, IBusinessHourBehavior> = {
11+
multiple: new MultipleBusinessHoursBehavior(),
12+
single: new SingleBusinessHourBehavior(),
13+
};
14+
15+
export const useLivechatEnterprise = () => {
16+
const businessHourType = useSetting('Livechat_business_hour_type') as string;
17+
const hasLicense = useHasLicenseModule('livechat-enterprise');
18+
19+
useEffect(() => {
20+
if (businessHourType && hasLicense) {
21+
businessHourManager.registerBusinessHourBehavior(businessHours[businessHourType.toLowerCase()]);
22+
}
23+
}, [businessHourType, hasLicense]);
24+
};

apps/meteor/app/livechat/imports/server/rest/departments.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Match, check } from 'meteor/check';
66
import { API } from '../../../../api/server';
77
import { getPaginationItems } from '../../../../api/server/helpers/getPaginationItems';
88
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
9+
import { settings } from '../../../../settings/server';
910
import {
1011
findDepartments,
1112
findDepartmentById,
@@ -164,6 +165,12 @@ API.v1.addRoute(
164165
_id: String,
165166
});
166167

168+
const isRemoveEnabled = settings.get<boolean>('Omnichannel_enable_department_removal');
169+
170+
if (!isRemoveEnabled) {
171+
return API.v1.failure('error-department-removal-disabled');
172+
}
173+
167174
await removeDepartment(this.urlParams._id);
168175

169176
return API.v1.success();

apps/meteor/app/livechat/server/hooks/markRoomResponded.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { IOmnichannelRoom, IMessage } from '@rocket.chat/core-typings';
22
import { isEditedMessage, isMessageFromVisitor, isSystemMessage } from '@rocket.chat/core-typings';
33
import type { Updater } from '@rocket.chat/models';
4-
import { LivechatRooms, LivechatVisitors, LivechatInquiry } from '@rocket.chat/models';
4+
import { LivechatRooms, LivechatContacts, LivechatInquiry } from '@rocket.chat/models';
55
import moment from 'moment';
66

77
import { callbacks } from '../../../../lib/callbacks';
@@ -17,11 +17,11 @@ export async function markRoomResponded(
1717
}
1818

1919
const monthYear = moment().format('YYYY-MM');
20-
const isVisitorActive = await LivechatVisitors.isVisitorActiveOnPeriod(room.v._id, monthYear);
20+
const isContactActive = await LivechatContacts.isContactActiveOnPeriod({ visitorId: room.v._id, source: room.source }, monthYear);
2121

2222
// Case: agent answers & visitor is not active, we mark visitor as active
23-
if (!isVisitorActive) {
24-
await LivechatVisitors.markVisitorActiveForPeriod(room.v._id, monthYear);
23+
if (!isContactActive) {
24+
await LivechatContacts.markContactActiveForPeriod({ visitorId: room.v._id, source: room.source }, monthYear);
2525
}
2626

2727
if (!room.v?.activity?.includes(monthYear)) {

apps/meteor/app/livechat/server/lib/Helper.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,6 @@ export const prepareLivechatRoom = async (
8787
const extraRoomInfo = await callbacks.run('livechat.beforeRoom', roomInfo, extraData);
8888
const { _id, username, token, department: departmentId, status = 'online' } = guest;
8989
const newRoomAt = new Date();
90-
91-
const { activity } = guest;
92-
logger.debug({
93-
msg: `Creating livechat room for visitor ${_id}`,
94-
visitor: { _id, username, departmentId, status, activity },
95-
});
96-
9790
const source = extraRoomInfo.source || roomInfo.source;
9891

9992
if (settings.get<string>('Livechat_Require_Contact_Verification') === 'always') {
@@ -103,14 +96,20 @@ export const prepareLivechatRoom = async (
10396
const contactId = await migrateVisitorIfMissingContact(_id, source);
10497
const contact =
10598
contactId &&
106-
(await LivechatContacts.findOneById<Pick<ILivechatContact, '_id' | 'name' | 'channels'>>(contactId, {
107-
projection: { name: 1, channels: 1 },
99+
(await LivechatContacts.findOneById<Pick<ILivechatContact, '_id' | 'name' | 'channels' | 'activity'>>(contactId, {
100+
projection: { name: 1, channels: 1, activity: 1 },
108101
}));
109102
if (!contact) {
110103
throw new Error('error-invalid-contact');
111104
}
112105
const verified = Boolean(contact.channels.some((channel) => isVerifiedChannelInSource(channel, _id, source)));
113106

107+
const activity = guest.activity || contact.activity;
108+
logger.debug({
109+
msg: `Creating livechat room for visitor ${_id}`,
110+
visitor: { _id, username, departmentId, status, activity },
111+
});
112+
114113
// TODO: Solve `u` missing issue
115114
return {
116115
_id: rid,
@@ -199,7 +198,11 @@ export const createLivechatInquiry = async ({
199198

200199
const extraInquiryInfo = await callbacks.run('livechat.beforeInquiry', extraData);
201200

202-
const { _id, username, token, department, status = UserStatus.ONLINE, activity } = guest;
201+
const { _id, username, token, department, status = UserStatus.ONLINE } = guest;
202+
const inquirySource = extraData?.source || { type: OmnichannelSourceType.OTHER };
203+
const activity =
204+
guest.activity ||
205+
(await LivechatContacts.findOneByVisitor({ visitorId: guest._id, source: inquirySource }, { projection: { activity: 1 } }))?.activity;
203206

204207
const ts = new Date();
205208

0 commit comments

Comments
 (0)