Skip to content

Commit

Permalink
[FIX] Rewrite CurrentChats to TS (#22424)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagoevanp authored and MartinSchoeler committed Jun 25, 2021
1 parent 67f485f commit 2412461
Show file tree
Hide file tree
Showing 27 changed files with 420 additions and 165 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
path: |
./node_modules
./ee/server/services/node_modules
key: ${{ runner.OS }}-node_modules-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}
key: ${{ runner.OS }}-node_modules-2-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}

- name: Cache meteor local
uses: actions/cache@v2
Expand Down Expand Up @@ -246,7 +246,7 @@ jobs:
path: |
./node_modules
./ee/server/services/node_modules
key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}
key: ${{ runner.OS }}-node_modules-2-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}

- name: NPM install
if: steps.cache-nodemodules.outputs.cache-hit != 'true' || steps.cache-cypress.outputs.cache-hit != 'true'
Expand Down Expand Up @@ -310,7 +310,7 @@ jobs:
path: |
./node_modules
./ee/server/services/node_modules
key: ${{ runner.OS }}-node_modules-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}
key: ${{ runner.OS }}-node_modules-2-${{ hashFiles('**/package-lock.json', '.github/workflows/build_and_test.yml') }}

- name: Cache meteor local
uses: actions/cache@v2
Expand Down
63 changes: 38 additions & 25 deletions client/components/AutoCompleteAgent.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
import { AutoComplete, Option } from '@rocket.chat/fuselage';
import { PaginatedSelectFiltered } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import React, { memo, useMemo, useState } from 'react';

import { useTranslation } from '../contexts/TranslationContext';
import { useEndpointData } from '../hooks/useEndpointData';
import { useRecordList } from '../hooks/lists/useRecordList';
import { AsyncStatePhase } from '../lib/asyncState';
import { useAgentsList } from './Omnichannel/hooks/useAgentsList';

const AutoCompleteAgent = (props) => {
const t = useTranslation();
const [filter, setFilter] = useState('');
const { value: data } = useEndpointData(
'livechat/users/agent',
useMemo(() => ({ text: filter }), [filter]),
);
const [agentsFilter, setAgentsFilter] = useState('');

const debouncedAgentsFilter = useDebouncedValue(agentsFilter, 500);

const options = useMemo(
() => (data && [...data.users.map((user) => ({ value: user._id, label: user.name }))]) || [],
[data],
const { itemsList: AgentsList, loadMoreItems: loadMoreAgents } = useAgentsList(
useMemo(() => ({ text: debouncedAgentsFilter }), [debouncedAgentsFilter]),
);
const optionsWithAll = useMemo(
() =>
(data && [
{ value: 'all', label: t('All') },
...data.users.map((user) => ({ value: user._id, label: user.name })),
]) || [{ value: 'all', label: t('All') }],
[data, t],

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

const sortedByName = agentsItems.sort((a, b) => {
if (a.value === 'all') {
return -1;
}

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

return 0;
});

return (
<AutoComplete
<PaginatedSelectFiltered
{...props}
filter={filter}
setFilter={setFilter}
renderSelected={({ label }) => <>{label}</>}
renderItem={({ value, ...props }) => <Option key={value} {...props} />}
options={props.empty ? options : optionsWithAll}
flexShrink={0}
filter={agentsFilter}
setFilter={setAgentsFilter}
options={sortedByName}
endReached={
agentsPhase === AsyncStatePhase.LOADING
? () => {}
: (start) => loadMoreAgents(start, Math.min(50, agentsTotal))
}
/>
);
};
Expand Down
12 changes: 8 additions & 4 deletions client/components/AutoCompleteDepartment.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import { AsyncStatePhase } from '../hooks/useAsyncState';
import { useDepartmentsList } from './Omnichannel/hooks/useDepartmentsList';

const AutoCompleteDepartment = (props) => {
const { value, onlyMyDepartments = false, onChange = () => { } } = props;
const { value, onlyMyDepartments = false, onChange = () => {}, haveAll = false } = props;

const t = useTranslation();
const [departmentsFilter, setDepartmentsFilter] = useState('');

const debouncedDepartmentsFilter = useDebouncedValue(departmentsFilter, 500);

const { itemsList: departmentsList, loadMoreItems: loadMoreDepartments } = useDepartmentsList(
useMemo(() => ({ filter: debouncedDepartmentsFilter, onlyMyDepartments }), [
useMemo(() => ({ filter: debouncedDepartmentsFilter, onlyMyDepartments, haveAll }), [
debouncedDepartmentsFilter,
onlyMyDepartments,
haveAll,
]),
);

Expand All @@ -29,6 +30,10 @@ const AutoCompleteDepartment = (props) => {
} = useRecordList(departmentsList);

const sortedByName = departmentsItems.sort((a, b) => {
if (a.value.value === 'all') {
return -1;
}

if (a.name > b.name) {
return 1;
}
Expand All @@ -47,11 +52,10 @@ const AutoCompleteDepartment = (props) => {
filter={departmentsFilter}
setFilter={setDepartmentsFilter}
options={sortedByName}
maxWidth='100%'
placeholder={t('Select_an_option')}
endReached={
departmentsPhase === AsyncStatePhase.LOADING
? () => { }
? () => {}
: (start) => loadMoreDepartments(start, Math.min(50, departmentsTotal))
}
/>
Expand Down
4 changes: 2 additions & 2 deletions client/components/GenericTable/HeaderCell.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Table } from '@rocket.chat/fuselage';
import React, { FC, useCallback } from 'react';
import React, { ComponentProps, FC, useCallback } from 'react';

import SortIcon from './SortIcon';

Expand All @@ -8,7 +8,7 @@ type HeaderCellProps = {
direction?: 'asc' | 'desc';
sort?: string;
onClick?: (sort: string) => void;
};
} & ComponentProps<typeof Box>;

const HeaderCell: FC<HeaderCellProps> = ({
children,
Expand Down
70 changes: 70 additions & 0 deletions client/components/Omnichannel/hooks/useAgentsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useCallback, useState } from 'react';

import { ILivechatAgentRecord } from '../../../../definition/ILivechatAgentRecord';
import { useEndpoint } from '../../../contexts/ServerContext';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useScrollableRecordList } from '../../../hooks/lists/useScrollableRecordList';
import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate';
import { RecordList } from '../../../lib/lists/RecordList';

type AgentsListOptions = {
text: string;
};

export const useAgentsList = (
options: AgentsListOptions,
): {
itemsList: RecordList<ILivechatAgentRecord>;
initialItemCount: number;
reload: () => void;
loadMoreItems: (start: number, end: number) => void;
} => {
const t = useTranslation();
const [itemsList, setItemsList] = useState(() => new RecordList<ILivechatAgentRecord>());
const reload = useCallback(() => setItemsList(new RecordList<ILivechatAgentRecord>()), []);
const endpoint = 'livechat/users/agent';

const getAgents = useEndpoint('GET', endpoint);

useComponentDidUpdate(() => {
options && reload();
}, [options, reload]);

const fetchData = useCallback(
async (start, end) => {
const { users: agents, total } = await getAgents({
...(options.text && { text: options.text }),
offset: start,
count: end + start,
sort: JSON.stringify({ name: 1 }),
});

const items = agents.map((agent: any) => {
agent._updatedAt = new Date(agent._updatedAt);
agent.label = agent.username;
agent.value = agent._id;
return agent;
});
items.unshift({
label: t('All'),
value: 'all',
_updatedAt: new Date(),
});

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

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

return {
reload,
itemsList,
loadMoreItems,
initialItemCount,
};
};
47 changes: 33 additions & 14 deletions client/components/Omnichannel/hooks/useDepartmentsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useCallback, useState } from 'react';

import { ILivechatDepartmentRecord } from '../../../../definition/ILivechatDepartmentRecord';
import { useEndpoint } from '../../../contexts/ServerContext';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useScrollableRecordList } from '../../../hooks/lists/useScrollableRecordList';
import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate';
import { RecordList } from '../../../lib/lists/RecordList';
Expand All @@ -10,6 +11,7 @@ type DepartmentsListOptions = {
filter: string;
departmentId?: string;
onlyMyDepartments?: boolean;
haveAll?: boolean;
};

export const useDepartmentsList = (
Expand All @@ -20,6 +22,7 @@ export const useDepartmentsList = (
reload: () => void;
loadMoreItems: (start: number, end: number) => void;
} => {
const t = useTranslation();
const [itemsList, setItemsList] = useState(() => new RecordList<ILivechatDepartmentRecord>());
const reload = useCallback(() => setItemsList(new RecordList<ILivechatDepartmentRecord>()), []);
const endpoint = 'livechat/department' as 'livechat/department';
Expand All @@ -40,24 +43,40 @@ export const useDepartmentsList = (
sort: JSON.stringify({ name: 1 }),
});

const items = departments
.filter((department) => {
if (options.departmentId && department._id === options.departmentId) {
return false;
}
return true;
})
.map((department: any) => {
department._updatedAt = new Date(department._updatedAt);
department.label = department.name;
department.value = { value: department._id, label: department.name };
return department;
});

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

return {
items: departments
.filter((department) => {
if (options.departmentId && department._id === options.departmentId) {
return false;
}
return true;
})
.map((department: any) => {
department._updatedAt = new Date(department._updatedAt);
department.label = department.name;
department.value = { value: department._id, label: department.name };
return department;
}),
items,
itemCount: options.departmentId ? total - 1 : total,
};
},
[getDepartments, options],
[
getDepartments,
options.departmentId,
options.filter,
options.haveAll,
options.onlyMyDepartments,
t,
],
);

const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25);
Expand Down
1 change: 1 addition & 0 deletions client/components/Omnichannel/modals/ForwardChatModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const ForwardChatModal = ({ onForward, onCancel, room, ...props }) => {
<Field.Label>{t('Forward_to_department')}</Field.Label>
<Field.Row>
<PaginatedSelectFiltered
withTitle
filter={departmentsFilter}
setFilter={setDepartmentsFilter}
options={departmentsItems}
Expand Down
7 changes: 5 additions & 2 deletions client/components/Page/PageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Box } from '@rocket.chat/fuselage';
import React, { forwardRef } from 'react';
import React, { ComponentProps, forwardRef } from 'react';

const PageContent = forwardRef(function PageContent(props, ref) {
const PageContent = forwardRef<HTMLElement, ComponentProps<typeof Box>>(function PageContent(
props,
ref,
) {
return (
<Box
ref={ref}
Expand Down
6 changes: 6 additions & 0 deletions client/contexts/ServerContext/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ import { ListEndpoint as EmojiCustomListEndpoint } from './endpoints/v1/emoji-cu
import { FilesEndpoint as GroupsFilesEndpoint } from './endpoints/v1/groups/files';
import { FilesEndpoint as ImFilesEndpoint } from './endpoints/v1/im/files';
import { AppearanceEndpoint as LivechatAppearanceEndpoint } from './endpoints/v1/livechat/appearance';
import { LivechatCustomFieldsEndpoint } from './endpoints/v1/livechat/customFields';
import { LivechatDepartment } from './endpoints/v1/livechat/department';
import { LivechatDepartmentsByUnit } from './endpoints/v1/livechat/departmentsByUnit';
import { LivechatMonitorsList } from './endpoints/v1/livechat/monitorsList';
import { LivechatRoomOnHoldEndpoint } from './endpoints/v1/livechat/onHold';
import { LivechatRoomsEndpoint } from './endpoints/v1/livechat/rooms';
import { LivechatTagsList } from './endpoints/v1/livechat/tagsList';
import { LivechatUsersAgentEndpoint } from './endpoints/v1/livechat/usersAgent';
import { LivechatVisitorInfoEndpoint } from './endpoints/v1/livechat/visitorInfo';
import { AutocompleteAvailableForTeamsEndpoint as RoomsAutocompleteTeamsEndpoint } from './endpoints/v1/rooms/autocompleteAvailableForTeams';
import { AutocompleteChannelAndPrivateEndpoint as RoomsAutocompleteEndpoint } from './endpoints/v1/rooms/autocompleteChannelAndPrivate';
Expand Down Expand Up @@ -48,6 +51,9 @@ export type ServerEndpoints = {
'livechat/tags.list': LivechatTagsList;
'livechat/department': LivechatDepartment;
'livechat/departments.by-unit/': LivechatDepartmentsByUnit;
'livechat/custom-fields': LivechatCustomFieldsEndpoint;
'livechat/rooms': LivechatRoomsEndpoint;
'livechat/users/agent': LivechatUsersAgentEndpoint;
};

export type ServerEndpointPath = keyof ServerEndpoints;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type LivechatCustomFieldsEndpoint = {
GET: (params: {}) => {
customFields: [
{
_id: string;
label: string;
},
];
};
};
15 changes: 15 additions & 0 deletions client/contexts/ServerContext/endpoints/v1/livechat/rooms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type LivechatRoomsEndpoint = {
GET: (params: {
guest: string;
fname: string;
servedBy: string[];
status: string;
department: string;
from: string;
to: string;
customFields: any;
current: number;
itemsPerPage: number;
tags: string[];
}) => { value: any; reload: () => void };
};
Loading

0 comments on commit 2412461

Please sign in to comment.