Skip to content

Commit

Permalink
Merge branch 'develop' into regression/info-page-route
Browse files Browse the repository at this point in the history
  • Loading branch information
casalsgh authored Oct 23, 2023
2 parents 1baff28 + 72653e6 commit 71821f6
Show file tree
Hide file tree
Showing 37 changed files with 411 additions and 110 deletions.
5 changes: 5 additions & 0 deletions .changeset/cuddly-ties-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

fix: custom-css injection
5 changes: 5 additions & 0 deletions .changeset/hip-pans-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fix: Omnichannel webhook is not retrying requests
5 changes: 5 additions & 0 deletions .changeset/lazy-shoes-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---

chore: adding some portugueses translations to the app details page
5 changes: 5 additions & 0 deletions .changeset/rotten-dryers-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Add pagination & tooltips to agent's dropdown on forwarding modal
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type WorkspaceRegistrationData<T> = {
MAC: number;
// activeContactsBillingMonth: number;
// activeContactsYesterday: number;
statsToken?: string;
};

export async function buildWorkspaceRegistrationData<T extends string | undefined>(contactEmail: T): Promise<WorkspaceRegistrationData<T>> {
Expand Down Expand Up @@ -92,5 +93,6 @@ export async function buildWorkspaceRegistrationData<T extends string | undefine
MAC: stats.omnichannelContactsBySource?.contactsCount ?? 0,
// activeContactsBillingMonth: stats.omnichannelContactsBySource.contactsCount,
// activeContactsYesterday: stats.uniqueContactsOfYesterday.contactsCount,
statsToken: stats.statsToken,
};
}
13 changes: 8 additions & 5 deletions apps/meteor/app/livechat/imports/server/rest/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ import { hasAtLeastOnePermissionAsync } from '../../../../authorization/server/f
import { findAgents, findManagers } from '../../../server/api/lib/users';
import { Livechat } from '../../../server/lib/Livechat';

const emptyStringArray: string[] = [];

API.v1.addRoute(
'livechat/users/:type',
{
authRequired: true,
permissionsRequired: {
GET: {
permissions: ['manage-livechat-agents'],
operation: 'hasAll',
},
POST: { permissions: ['view-livechat-manager'], operation: 'hasAll' },
'POST': ['view-livechat-manager'],
'*': emptyStringArray,
},
validateParams: {
GET: isLivechatUsersManagerGETProps,
Expand All @@ -39,9 +38,13 @@ API.v1.addRoute(
return API.v1.unauthorized();
}

const { onlyAvailable, excludeId, showIdleAgents } = this.queryParams;
return API.v1.success(
await findAgents({
text,
onlyAvailable,
excludeId,
showIdleAgents,
pagination: {
offset,
count,
Expand Down
39 changes: 35 additions & 4 deletions apps/meteor/app/livechat/server/api/lib/users.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ILivechatAgent, IRole } from '@rocket.chat/core-typings';
import { Users } from '@rocket.chat/models';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import type { FilterOperators } from 'mongodb';

/**
* @param {IRole['_id']} role the role id
Expand All @@ -10,18 +11,39 @@ import { escapeRegExp } from '@rocket.chat/string-helpers';
async function findUsers({
role,
text,
onlyAvailable = false,
excludeId,
showIdleAgents = true,
pagination: { offset, count, sort },
}: {
role: IRole['_id'];
text?: string;
onlyAvailable?: boolean;
excludeId?: string;
showIdleAgents?: boolean;
pagination: { offset: number; count: number; sort: any };
}): Promise<{ users: ILivechatAgent[]; count: number; offset: number; total: number }> {
const query = {};
const query: FilterOperators<ILivechatAgent> = {};
const orConditions: FilterOperators<ILivechatAgent>['$or'] = [];
if (text) {
const filterReg = new RegExp(escapeRegExp(text), 'i');
Object.assign(query, {
$or: [{ username: filterReg }, { name: filterReg }, { 'emails.address': filterReg }],
});
orConditions.push({ $or: [{ username: filterReg }, { name: filterReg }, { 'emails.address': filterReg }] });
}

if (onlyAvailable) {
query.statusLivechat = 'available';
}

if (excludeId) {
query._id = { $ne: excludeId };
}

if (!showIdleAgents) {
orConditions.push({ $or: [{ status: { $exists: true, $ne: 'offline' }, roles: { $ne: 'bot' } }, { roles: 'bot' }] });
}

if (orConditions.length) {
query.$and = orConditions;
}

const [
Expand Down Expand Up @@ -52,14 +74,23 @@ async function findUsers({
}
export async function findAgents({
text,
onlyAvailable = false,
excludeId,
showIdleAgents = true,
pagination: { offset, count, sort },
}: {
text?: string;
onlyAvailable: boolean;
excludeId?: string;
showIdleAgents?: boolean;
pagination: { offset: number; count: number; sort: any };
}): Promise<ReturnType<typeof findUsers>> {
return findUsers({
role: 'livechat-agent',
text,
onlyAvailable,
excludeId,
showIdleAgents,
pagination: {
offset,
count,
Expand Down
20 changes: 13 additions & 7 deletions apps/meteor/app/livechat/server/lib/LivechatTyped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -796,12 +796,15 @@ class LivechatClass {
attempts = 10,
) {
if (!attempts) {
Livechat.logger.error({ msg: 'Omnichannel webhook call failed. Max attempts reached' });
return;
}
const timeout = settings.get<number>('Livechat_http_timeout');
const secretToken = settings.get<string>('Livechat_secret_token');
const webhookUrl = settings.get<string>('Livechat_webhookUrl');
try {
const result = await fetch(settings.get('Livechat_webhookUrl'), {
Livechat.webhookLogger.debug({ msg: 'Sending webhook request', postData });
const result = await fetch(webhookUrl, {
method: 'POST',
headers: {
...(secretToken && { 'X-RocketChat-Livechat-Token': secretToken }),
Expand All @@ -812,17 +815,20 @@ class LivechatClass {

if (result.status === 200) {
metrics.totalLivechatWebhooksSuccess.inc();
} else {
metrics.totalLivechatWebhooksFailures.inc();
return result;
}
return result;

metrics.totalLivechatWebhooksFailures.inc();
throw new Error(await result.text());
} catch (err) {
Livechat.webhookLogger.error({ msg: `Response error on ${11 - attempts} try ->`, err });
const retryAfter = timeout * 4;
Livechat.webhookLogger.error({ msg: `Error response on ${11 - attempts} try ->`, err });
// try 10 times after 20 seconds each
attempts - 1 && Livechat.webhookLogger.warn(`Will try again in ${(timeout / 1000) * 4} seconds ...`);
attempts - 1 &&
Livechat.webhookLogger.warn({ msg: `Webhook call failed. Retrying`, newAttemptAfterSeconds: retryAfter / 1000, webhookUrl });
setTimeout(async () => {
await Livechat.sendRequest(postData, attempts - 1);
}, timeout * 4);
}, retryAfter);
}
}

Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/app/statistics/server/lib/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,9 @@ export const statistics = {
async save(): Promise<IStats> {
const rcStatistics = await statistics.get();
rcStatistics.createdAt = new Date();
await Statistics.insertOne(rcStatistics);
const { insertedId } = await Statistics.insertOne(rcStatistics);
rcStatistics._id = insertedId;

return rcStatistics;
},
};
2 changes: 0 additions & 2 deletions apps/meteor/app/ui-master/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ Meteor.startup(() => {
})(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX);

injectIntoHead('base', `<base href="${baseUrl}">`);

injectIntoHead('css-theme', '');
});

const renderDynamicCssList = withDebouncing({ wait: 500 })(async () => {
Expand Down
30 changes: 14 additions & 16 deletions apps/meteor/client/components/AutoCompleteAgent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,51 @@ type AutoCompleteAgentProps = {
value: string;
error?: string;
placeholder?: string;
onChange: (value: string) => void;
haveAll?: boolean;
haveNoAgentsSelectedOption?: boolean;
excludeId?: string;
showIdleAgents?: boolean;
onlyAvailable?: boolean;
withTitle?: boolean;
onChange: (value: string) => void;
};

const AutoCompleteAgent = ({
value,
error,
placeholder,
onChange,
haveAll = false,
haveNoAgentsSelectedOption = false,
excludeId,
showIdleAgents = false,
onlyAvailable = false,
withTitle = false,
onChange,
}: AutoCompleteAgentProps): ReactElement => {
const [agentsFilter, setAgentsFilter] = useState<string>('');

const debouncedAgentsFilter = useDebouncedValue(agentsFilter, 500);

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

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

const sortedByName = agentsItems.sort((a, b) => {
if (a.label > b.label) {
return 1;
}
if (a.label < b.label) {
return -1;
}

return 0;
});

return (
<PaginatedSelectFiltered
withTitle={withTitle}
value={value}
error={error}
placeholder={placeholder}
onChange={onChange}
flexShrink={0}
filter={agentsFilter}
setFilter={setAgentsFilter as (value: string | number | undefined) => void}
options={sortedByName}
options={agentsItems}
data-qa='autocomplete-agent'
endReached={
agentsPhase === AsyncStatePhase.LOADING ? (): void => undefined : (start): void => loadMoreAgents(start, Math.min(50, agentsTotal))
Expand Down
17 changes: 12 additions & 5 deletions apps/meteor/client/components/Omnichannel/hooks/useAgentsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ type AgentsListOptions = {
text: string;
haveAll: boolean;
haveNoAgentsSelectedOption: boolean;
excludeId?: string;
showIdleAgents?: boolean;
onlyAvailable?: boolean;
};

type AgentOption = { value: string; label: string; _updatedAt: Date; _id: string };
Expand All @@ -26,6 +29,7 @@ export const useAgentsList = (
const reload = useCallback(() => setItemsList(new RecordList<AgentOption>()), []);

const getAgents = useEndpoint('GET', '/v1/livechat/users/agent');
const { text, onlyAvailable = false, showIdleAgents = false, excludeId, haveAll, haveNoAgentsSelectedOption } = options;

useComponentDidUpdate(() => {
options && reload();
Expand All @@ -34,7 +38,10 @@ export const useAgentsList = (
const fetchData = useCallback(
async (start, end) => {
const { users: agents, total } = await getAgents({
...(options.text && { text: options.text }),
...(text && { text }),
...(excludeId && { excludeId }),
showIdleAgents,
onlyAvailable,
offset: start,
count: end + start,
sort: `{ "name": 1 }`,
Expand All @@ -43,22 +50,22 @@ export const useAgentsList = (
const items = agents.map<AgentOption>((agent) => {
const agentOption = {
_updatedAt: new Date(agent._updatedAt),
label: agent.username || agent._id,
label: `${agent.name || agent._id} (@${agent.username})`,
value: agent._id,
_id: agent._id,
};
return agentOption;
});

options.haveAll &&
haveAll &&
items.unshift({
label: t('All'),
value: 'all',
_updatedAt: new Date(),
_id: 'all',
});

options.haveNoAgentsSelectedOption &&
haveNoAgentsSelectedOption &&
items.unshift({
label: t('Empty_no_agent_selected'),
value: 'no-agent-selected',
Expand All @@ -71,7 +78,7 @@ export const useAgentsList = (
itemCount: total + 1,
};
},
[getAgents, options.haveAll, options.haveNoAgentsSelectedOption, options.text, t],
[excludeId, getAgents, haveAll, haveNoAgentsSelectedOption, onlyAvailable, showIdleAgents, t, text],
);

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

0 comments on commit 71821f6

Please sign in to comment.