Skip to content

Commit

Permalink
Regression: Contact manager edit/view not working (#26155)
Browse files Browse the repository at this point in the history
Co-authored-by: murtaza98 <murtaza.patrawala@rocket.chat>
  • Loading branch information
2 people authored and weslley543 committed Jul 19, 2022
1 parent c6663cb commit 04c1947
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 144 deletions.
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/api/lib/users.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { Users } from '@rocket.chat/models';

import { hasAllPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { hasAllPermissionAsync, hasAtLeastOnePermissionAsync } from '../../../../authorization/server/functions/hasPermission';

/**
* @param {IRole['_id']} role the role id
Expand Down Expand Up @@ -41,7 +41,7 @@ async function findUsers({ role, text, pagination: { offset, count, sort } }) {
};
}
export async function findAgents({ userId, text, pagination: { offset, count, sort } }) {
if (!(await hasAllPermissionAsync(userId, ['view-l-room', 'transfer-livechat-guest']))) {
if (!(await hasAtLeastOnePermissionAsync(userId, ['manage-livechat-agents', 'transfer-livechat-guest', 'edit-omnichannel-contact']))) {
throw new Error('error-not-authorized');
}

Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/livechat/server/api/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ import './v1/customField.js';
import './v1/room.js';
import './v1/videoCall.js';
import './v1/transfer.js';
import './v1/contact.js';
import './v1/contact';
77 changes: 0 additions & 77 deletions apps/meteor/app/livechat/server/api/v1/contact.js

This file was deleted.

70 changes: 70 additions & 0 deletions apps/meteor/app/livechat/server/api/v1/contact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { LivechatVisitors } from '@rocket.chat/models';

import { API } from '../../../../api/server';
import { Contacts } from '../../lib/Contacts';

API.v1.addRoute(
'omnichannel/contact',
{ authRequired: true },
{
async post() {
check(this.bodyParams, {
_id: Match.Maybe(String),
token: String,
name: String,
email: Match.Maybe(String),
phone: Match.Maybe(String),
username: Match.Maybe(String),
customFields: Match.Maybe(Object),
contactManager: Match.Maybe({
username: String,
}),
});

const contact = await Contacts.registerContact(this.bodyParams);

return API.v1.success({ contact });
},
async get() {
check(this.queryParams, {
contactId: String,
});

const contact = await LivechatVisitors.findOneById(this.queryParams.contactId);

return API.v1.success({ contact });
},
},
);

API.v1.addRoute(
'omnichannel/contact.search',
{ authRequired: true },
{
async get() {
check(this.queryParams, {
email: Match.Maybe(String),
phone: Match.Maybe(String),
});

const { email, phone } = this.queryParams;

if (!email && !phone) {
throw new Meteor.Error('error-invalid-params');
}

const query = Object.assign(
{},
{
...(email && { visitorEmails: { address: email } }),
...(phone && { phone: { phoneNumber: phone } }),
},
);

const contact = await LivechatVisitors.findOne(query);
return API.v1.success({ contact });
},
},
);
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import s from 'underscore.string';
import { LivechatVisitors, LivechatRooms, Users } from '@rocket.chat/models';
import { MatchKeysAndValues, OnlyFieldsOfType } from 'mongodb';
import { LivechatVisitors, Users, LivechatRooms } from '@rocket.chat/models';
import { ILivechatCustomField, ILivechatVisitor, IOmnichannelRoom } from '@rocket.chat/core-typings';

import { LivechatCustomField, Rooms, LivechatInquiry, Subscriptions } from '../../../models/server';

type RegisterContactProps = {
_id?: string;
token: string;
name: string;
username?: string;
email?: string;
phone?: string;
customFields?: Record<string, unknown | string>;
contactManager?: {
username: string;
};
};

export const Contacts = {
async registerContact({ token, name, email, phone, username, customFields = {}, contactManager = {} } = {}) {
async registerContact({
token,
name,
email = '',
phone,
username,
customFields = {},
contactManager,
}: RegisterContactProps): Promise<string> {
check(token, String);

const visitorEmail = s.trim(email).toLowerCase();
Expand All @@ -23,11 +46,6 @@ export const Contacts = {
}

let contactId;
const updateUser = {
$set: {
token,
},
};

const user = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });

Expand All @@ -46,31 +64,39 @@ export const Contacts = {
const userData = {
username,
ts: new Date(),
token,
};

contactId = await LivechatVisitors.insertOne(userData);
contactId = (await LivechatVisitors.insertOne(userData)).insertedId;
}
}

updateUser.$set.name = name;
updateUser.$set.phone = (phone && [{ phoneNumber: phone }]) || null;
updateUser.$set.visitorEmails = (visitorEmail && [{ address: visitorEmail }]) || null;

const allowedCF = LivechatCustomField.find({ scope: 'visitor' }, { fields: { _id: 1 } }).map(({ _id }) => _id);
const allowedCF: ILivechatCustomField['_id'][] = LivechatCustomField.find({ scope: 'visitor' }, { fields: { _id: 1 } }).map(
({ _id }: ILivechatCustomField) => _id,
);

const livechatData = Object.keys(customFields)
.filter((key) => allowedCF.includes(key) && customFields[key] !== '' && customFields[key] !== undefined)
.reduce((obj, key) => {
.reduce((obj: Record<string, unknown | string>, key) => {
obj[key] = customFields[key];
return obj;
}, {});

updateUser.$set.livechatData = livechatData;
updateUser.$set.contactManager = (contactManager?.username && { username: contactManager.username }) || null;
const updateUser: { $set: MatchKeysAndValues<ILivechatVisitor>; $unset?: OnlyFieldsOfType<ILivechatVisitor> } = {
$set: {
token,
name,
livechatData,
...(phone && { phone: [{ phoneNumber: phone }] }),
...(visitorEmail && { visitorEmails: [{ address: visitorEmail }] }),
...(contactManager?.username && { contactManager: { username: contactManager.username } }),
},
...(!contactManager?.username && { $unset: { contactManager: 1 } }),
};

await LivechatVisitors.updateById(contactId, updateUser);
await LivechatVisitors.updateOne({ _id: contactId }, updateUser);

const rooms = await LivechatRooms.findByVisitorId(contactId).toArray();
const rooms: IOmnichannelRoom[] = await LivechatRooms.findByVisitorId(contactId, {}).toArray();

rooms?.length &&
rooms.forEach((room) => {
Expand Down
13 changes: 8 additions & 5 deletions apps/meteor/client/components/AutoCompleteAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,29 @@ import { AsyncStatePhase } from '../lib/asyncState';
import { useAgentsList } from './Omnichannel/hooks/useAgentsList';

const AutoCompleteAgent = (props) => {
const { value, onChange = () => {}, haveAll = false } = props;
const { value, onChange = () => {}, haveAll = false, haveNoAgentsSelectedOption = false } = props;
const [agentsFilter, setAgentsFilter] = useState('');

const debouncedAgentsFilter = useDebouncedValue(agentsFilter, 500);

const { itemsList: AgentsList, loadMoreItems: loadMoreAgents } = useAgentsList(
useMemo(() => ({ text: debouncedAgentsFilter, haveAll }), [debouncedAgentsFilter, haveAll]),
useMemo(
() => ({ text: debouncedAgentsFilter, haveAll, haveNoAgentsSelectedOption }),
[debouncedAgentsFilter, haveAll, haveNoAgentsSelectedOption],
),
);

const { phase: agentsPhase, items: agentsItems, itemCount: agentsTotal } = useRecordList(AgentsList);

const sortedByName = agentsItems.sort((a, b) => {
if (a.value === 'all') {
if (['all', 'no-agent-selected'].includes(a.value)) {
return -1;
}

if (a.usename > b.usename) {
if (a.username > b.username) {
return 1;
}
if (a.usename < b.usename) {
if (a.username < b.username) {
return -1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RecordList } from '../../../lib/lists/RecordList';
type AgentsListOptions = {
text: string;
haveAll: boolean;
haveNoAgentsSelectedOption: boolean;
};

export const useAgentsList = (
Expand Down Expand Up @@ -52,12 +53,19 @@ export const useAgentsList = (
_updatedAt: new Date(),
});

options.haveNoAgentsSelectedOption &&
items.unshift({
label: t('Empty_no_agent_selected'),
value: 'no-agent-selected',
_updatedAt: new Date(),
});

return {
items,
itemCount: total + 1,
};
},
[getAgents, options.haveAll, options.text, t],
[getAgents, options.haveAll, options.haveNoAgentsSelectedOption, options.text, t],
);

const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25);
Expand Down
Loading

0 comments on commit 04c1947

Please sign in to comment.