Regression: Omnichannel Current Chat issues (#18718)

Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
pull/18051/head^2
Martin Schoeler 5 years ago committed by GitHub
parent bc7a1b1251
commit a5118fa00f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      client/components/basic/AutoCompleteAgent.js
  2. 22
      client/components/basic/AutoCompleteDepartment.js
  3. 8
      client/omnichannel/agents/AgentsRoute.js
  4. 109
      client/omnichannel/currentChats/CurrentChatsPage.js
  5. 84
      client/omnichannel/currentChats/CurrentChatsRoute.js
  6. 8
      client/omnichannel/customFields/CustomFieldsTable.js
  7. 9
      client/omnichannel/managers/ManagersRoute.js
  8. 13
      client/omnichannel/triggers/TriggersTable.js
  9. 8
      ee/client/omnichannel/BusinessHoursTable.js
  10. 8
      ee/client/omnichannel/priorities/PrioritiesRoute.js
  11. 8
      ee/client/omnichannel/tags/TagsRoute.js
  12. 8
      ee/client/omnichannel/units/UnitsRoute.js
  13. 2
      packages/rocketchat-i18n/i18n/en.i18n.json

@ -0,0 +1,22 @@
import React, { useMemo, useState } from 'react';
import { AutoComplete, Option } from '@rocket.chat/fuselage';
import { useEndpointDataExperimental } from '../../hooks/useEndpointDataExperimental';
import { useTranslation } from '../../contexts/TranslationContext';
export const AutoCompleteAgent = React.memo((props) => {
const t = useTranslation();
const [filter, setFilter] = useState('');
const { data } = useEndpointDataExperimental('livechat/users/agent', useMemo(() => ({ text: filter }), [filter]));
const options = useMemo(() => (data && [{ value: 'all', label: t('All') }, ...data.users.map((user) => ({ value: user._id, label: user.name }))]) || [{ value: 'all', label: t('All') }], [data, t]);
return <AutoComplete
{...props}
filter={filter}
setFilter={setFilter}
renderSelected={({ label }) => <>{label}</>}
renderItem={({ value, ...props }) => <Option key={value} {...props} />}
options={ options }
/>;
});

@ -0,0 +1,22 @@
import React, { useMemo, useState } from 'react';
import { AutoComplete, Option } from '@rocket.chat/fuselage';
import { useEndpointDataExperimental } from '../../hooks/useEndpointDataExperimental';
import { useTranslation } from '../../contexts/TranslationContext';
export const AutoCompleteDepartment = React.memo((props) => {
const t = useTranslation();
const [filter, setFilter] = useState('');
const { data } = useEndpointDataExperimental('livechat/department', useMemo(() => ({ text: filter }), [filter]));
const options = useMemo(() => (data && [{ value: 'all', label: t('All') }, ...data.departments.map((department) => ({ value: department._id, label: department.name }))]) || [{ value: 'all', label: t('All') }], [data, t]);
return <AutoComplete
{...props}
filter={filter}
setFilter={setFilter}
renderSelected={({ label }) => <>{label}</>}
renderItem={({ value, ...props }) => <Option key={value} {...props} />}
options={ options }
/>;
});

@ -1,7 +1,7 @@
import { useDebouncedValue, useMediaQuery, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Box, Table, Icon } from '@rocket.chat/fuselage';
import { Box, Table, Icon, Button } from '@rocket.chat/fuselage';
import { Th } from '../../components/GenericTable';
import { useTranslation } from '../../contexts/TranslationContext';
@ -49,7 +49,11 @@ export function RemoveAgentButton({ _id, reload }) {
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
export function AgentInfoActions({ reload }) {

@ -1,6 +1,6 @@
import React, { useEffect, useMemo } from 'react';
import { TextInput, Box, Icon, MultiSelect, Select, InputBox, Menu } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useMutableCallback, useLocalStorage } from '@rocket.chat/fuselage-hooks';
import moment from 'moment';
import { useSubscription } from 'use-subscription';
@ -10,12 +10,13 @@ import { useTranslation } from '../../contexts/TranslationContext';
import { useEndpointDataExperimental } from '../../hooks/useEndpointDataExperimental';
import { usePermission } from '../../contexts/AuthorizationContext';
import { GenericTable } from '../../components/GenericTable';
import { useForm } from '../../hooks/useForm';
import { useMethod } from '../../contexts/ServerContext';
import DeleteWarningModal from '../DeleteWarningModal';
import { useSetModal } from '../../contexts/ModalContext';
import { useToastMessageDispatch } from '../../contexts/ToastMessagesContext';
import { AutoCompleteDepartment } from '../../components/basic/AutoCompleteDepartment';
import { AutoCompleteAgent } from '../../components/basic/AutoCompleteAgent';
// moment(new Date(from)).utc().format('YYYY-MM-DDTHH:mm:ss')
// guest: '', servedBy: '', status: '', department: '', from: '', to: ''
const Label = (props) => <Box fontScale='p2' color='default' {...props} />;
const RemoveAllClosed = ({ handleClearFilters, handleRemoveClosed, ...props }) => {
@ -43,38 +44,42 @@ const RemoveAllClosed = ({ handleClearFilters, handleRemoveClosed, ...props }) =
const FilterByText = ({ setFilter, reload, ...props }) => {
const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();
const t = useTranslation();
const { data: departments } = useEndpointDataExperimental('livechat/department') || {};
const { data: agents } = useEndpointDataExperimental('livechat/users/agent');
const depOptions = useMemo(() => (departments && departments.departments ? departments.departments.map(({ _id, name }) => [_id, name || _id]) : []), [departments]);
const agentOptions = useMemo(() => (agents && agents.users ? agents.users.map(({ _id, username }) => [_id, username || _id]) : []), [agents]);
const { data: allCustomFields } = useEndpointDataExperimental('livechat/custom-fields');
const statusOptions = [['all', t('All')], ['closed', t('Closed')], ['opened', t('Open')]];
useEffect(() => {
!depOptions.find((dep) => dep[0] === 'all') && depOptions.unshift(['all', t('All')]);
}, [depOptions, t]);
const { values, handlers, reset } = useForm({ guest: '', servedBy: [], status: 'all', department: 'all', from: '', to: '', tags: [] });
const {
handleGuest,
handleServedBy,
handleStatus,
handleDepartment,
handleFrom,
handleTo,
handleTags,
} = handlers;
const {
guest,
servedBy,
status,
department,
from,
to,
tags,
} = values;
const customFieldsOptions = useMemo(() => (allCustomFields && allCustomFields.customFields ? allCustomFields.customFields.map(({ _id, label }) => [_id, label]) : []), [allCustomFields]);
const [guest, setGuest] = useLocalStorage('guest', '');
const [servedBy, setServedBy] = useLocalStorage('servedBy', 'all');
const [status, setStatus] = useLocalStorage('status', 'all');
const [department, setDepartment] = useLocalStorage('department', 'all');
const [from, setFrom] = useLocalStorage('from', '');
const [to, setTo] = useLocalStorage('to', '');
const [tags, setTags] = useLocalStorage('tags', []);
const [customFields, setCustomFields] = useLocalStorage('tags', []);
const handleGuest = useMutableCallback((e) => setGuest(e.target.value));
const handleServedBy = useMutableCallback((e) => setServedBy(e));
const handleStatus = useMutableCallback((e) => setStatus(e));
const handleDepartment = useMutableCallback((e) => setDepartment(e));
const handleFrom = useMutableCallback((e) => setFrom(e.target.value));
const handleTo = useMutableCallback((e) => setTo(e.target.value));
const handleTags = useMutableCallback((e) => setTags(e));
const handleCustomFields = useMutableCallback((e) => setCustomFields(e));
const reset = useMutableCallback(() => {
setGuest('');
setServedBy('all');
setStatus('all');
setDepartment('all');
setFrom('');
setTo('');
setTags([]);
setCustomFields([]);
});
const forms = useSubscription(formsSubscription);
@ -84,8 +89,11 @@ const FilterByText = ({ setFilter, reload, ...props }) => {
const Tags = useCurrentChatTags();
const onSubmit = useMutableCallback((e) => e.preventDefault());
const reducer = function(acc, curr) {
acc[curr] = '';
return acc;
};
useEffect(() => {
setFilter({
@ -96,8 +104,9 @@ const FilterByText = ({ setFilter, reload, ...props }) => {
from: from && moment(new Date(from)).utc().format('YYYY-MM-DDTHH:mm:ss'),
to: to && moment(new Date(to)).utc().format('YYYY-MM-DDTHH:mm:ss'),
tags,
customFields: customFields.reduce(reducer, {}),
});
}, [setFilter, guest, servedBy, status, department, from, to, tags]);
}, [setFilter, guest, servedBy, status, department, from, to, tags, customFields]);
const handleClearFilters = useMutableCallback(() => {
reset();
@ -106,10 +115,21 @@ const FilterByText = ({ setFilter, reload, ...props }) => {
const removeClosedChats = useMethod('livechat:removeAllClosedRooms');
const handleRemoveClosed = useMutableCallback(async () => {
await removeClosedChats();
reload();
const onDeleteAll = async () => {
try {
await removeClosedChats();
reload();
dispatchToastMessage({ type: 'success', message: t('Chat_removed') });
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
setModal();
};
setModal(<DeleteWarningModal onDelete={onDeleteAll} onCancel={() => setModal()}/>);
});
return <Box mb='x16' is='form' onSubmit={onSubmit} display='flex' flexDirection='column' {...props}>
<Box display='flex' flexDirection='row' flexWrap='wrap' {...props}>
<Box display='flex' mie='x8' flexGrow={1} flexDirection='column'>
@ -118,11 +138,11 @@ const FilterByText = ({ setFilter, reload, ...props }) => {
</Box>
<Box display='flex' mie='x8' flexGrow={1} flexDirection='column'>
<Label mb='x4'>{t('Served_By')}:</Label>
<MultiSelect flexShrink={0} options={agentOptions} value={servedBy} onChange={handleServedBy} placeholder={t('Served_By')}/>
<AutoCompleteAgent value={servedBy} onChange={handleServedBy}/>
</Box>
<Box display='flex' mie='x8' flexGrow={1} flexDirection='column'>
<Label mb='x4'>{t('Department')}:</Label>
<Select flexShrink={0} options={depOptions} value={department} onChange={handleDepartment} placeholder={t('Department')}/>
<AutoCompleteDepartment value={department} onChange={handleDepartment}/>
</Box>
<Box display='flex' mie='x8' flexGrow={1} flexDirection='column'>
<Label mb='x4'>{t('Status')}:</Label>
@ -145,6 +165,12 @@ const FilterByText = ({ setFilter, reload, ...props }) => {
<Tags value={tags} handler={handleTags} />
</Box>
</Box>}
{allCustomFields && <Box display='flex' flexDirection='row' marginBlockStart='x8' {...props}>
<Box display='flex' mie='x8' flexGrow={1} flexDirection='column'>
<Label mb='x4'>{t('Custom_fields')}:</Label>
<MultiSelect options={customFieldsOptions} value={customFields} onChange={handleCustomFields} flexGrow={1} {...props}/>
</Box>
</Box>}
</Box>;
};
@ -156,7 +182,6 @@ function CurrentChatsPage({
params,
title,
renderRow,
departments,
reload,
children,
}) {
@ -164,7 +189,7 @@ function CurrentChatsPage({
<Page>
<Page.Header title={title} />
<Page.Content>
<GenericTable FilterComponent={FilterByText} header={header} renderRow={renderRow} results={data && data.rooms} departments={departments} total={data && data.total} setParams={setParams} params={params} reload={reload}/>
<GenericTable FilterComponent={FilterByText} header={header} renderRow={renderRow} results={data && data.rooms} total={data && data.total} setParams={setParams} params={params} reload={reload}/>
</Page.Content>
</Page>
{children}

@ -2,7 +2,7 @@
import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Table, Icon } from '@rocket.chat/fuselage';
import { Table, Icon, Button } from '@rocket.chat/fuselage';
import moment from 'moment';
import { FlowRouter } from 'meteor/kadira:flow-router';
@ -13,35 +13,54 @@ import { useEndpointDataExperimental } from '../../hooks/useEndpointDataExperime
import { useMethod } from '../../contexts/ServerContext';
import { usePermission } from '../../contexts/AuthorizationContext';
import NotAuthorizedPage from '../../components/NotAuthorizedPage';
import { useRoute } from '../../contexts/RouterContext';
import CurrentChatsPage from './CurrentChatsPage';
import DeleteWarningModal from '../DeleteWarningModal';
import { useSetModal } from '../../contexts/ModalContext';
import { useToastMessageDispatch } from '../../contexts/ToastMessagesContext';
export function RemoveChatButton({ _id, reload }) {
const removeChat = useMethod('livechat:removeRoom');
const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();
const t = useTranslation();
export function RemoveCurrentChatButton({ _id, reload }) {
const removeCurrentChat = useMethod('livechat:removeCurrentChat');
const currentChatsRoute = useRoute('omnichannel-currentChats');
const handleRemoveClick = useMutableCallback(async (e) => {
e.preventDefault();
e.stopPropagation();
const handleRemoveClick = useMutableCallback(async () => {
try {
await removeCurrentChat(_id);
await removeChat(_id);
} catch (error) {
console.log(error);
}
currentChatsRoute.push({});
reload();
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleRemoveClick} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
const handleDelete = useMutableCallback((e) => {
e.stopPropagation();
const onDeleteAgent = async () => {
try {
await handleRemoveClick();
dispatchToastMessage({ type: 'success', message: t('Chat_removed') });
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
setModal();
};
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint'withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const sortDir = (sortDir) => (sortDir === 'asc' ? 1 : -1);
const useQuery = ({ guest, servedBy, department, status, from, to, tags, itemsPerPage, current }, [column, direction]) => useMemo(() => {
const useQuery = ({ guest, servedBy, department, status, from, to, tags, customFields, itemsPerPage, current }, [column, direction]) => useMemo(() => {
const query = {
roomName: guest,
sort: JSON.stringify({ [column]: sortDir(direction), usernames: column === 'name' ? sortDir(direction) : undefined }),
...guest && { roomName: guest },
sort: JSON.stringify({ [column]: sortDir(direction), ts: column === 'ts' ? sortDir(direction) : undefined }),
...itemsPerPage && { count: itemsPerPage },
...current && { offset: current },
};
@ -52,27 +71,30 @@ const useQuery = ({ guest, servedBy, department, status, from, to, tags, itemsPe
if (status !== 'all') {
query.open = status === 'open';
}
if (servedBy && servedBy.length > 0) {
query.agents = servedBy;
if (servedBy && servedBy !== 'all') {
query.agents = [servedBy];
}
if (department && department.length > 0) {
if (department !== 'all') {
query.departmentId = department;
}
if (department && department !== 'all') {
query.departmentId = department;
}
if (tags && tags.length > 0) {
query.tags = tags;
}
if (customFields && Object.keys(customFields).length > 0) {
query.customFields = JSON.stringify(customFields);
}
return query;
}, [guest, column, direction, itemsPerPage, current, from, to, status, servedBy, department, tags]);
}, [guest, column, direction, itemsPerPage, current, from, to, status, servedBy, department, tags, customFields]);
function CurrentChatsRoute() {
const t = useTranslation();
const canViewCurrentChats = usePermission('view-livechat-current-chats');
const [params, setParams] = useState({ fname: '', servedBy: [], status: '', department: '', from: '', to: '', current: 0, itemsPerPage: 25 });
const [sort, setSort] = useState(['name', 'asc']);
const [params, setParams] = useState({ fname: '', servedBy: [], status: '', department: '', from: '', to: '', customFields: {}, current: 0, itemsPerPage: 25 });
const [sort, setSort] = useState(['ts', 'desc']);
const debouncedParams = useDebouncedValue(params, 500);
const debouncedSort = useDebouncedValue(sort, 500);
@ -96,15 +118,15 @@ function CurrentChatsRoute() {
});
const { data, reload } = useEndpointDataExperimental('livechat/rooms', query) || {};
const { data: departments } = useEndpointDataExperimental('livechat/department', query) || {};
const header = useMemo(() => [
<Th key={'name'} direction={sort[1]} active={sort[0] === 'name'} onClick={onHeaderClick} sort='name' w='x120'>{t('Name')}</Th>,
<Th key={'departmentId'} direction={sort[1]} active={sort[0] === 'departmentId'} onClick={onHeaderClick} sort='departmentId' w='x200'>{t('Department')}</Th>,
<Th key={'servedBy'} direction={sort[1]} active={sort[0] === 'servedBy'} onClick={onHeaderClick} sort='servedBy' w='x120'>{t('Served_by')}</Th>,
<Th key={'ts'} direction={sort[1]} active={sort[0] === 'ts'} onClick={onHeaderClick} sort='ts' w='x120'>{t('Started_at')}</Th>,
<Th key={'lm'} direction={sort[1]} active={sort[0] === 'lm'} onClick={onHeaderClick} sort='visibility' w='x120'>{t('Last_message')}</Th>,
<Th key={'servedBy'} direction={sort[1]} active={sort[0] === 'servedBy'} onClick={onHeaderClick} sort='servedBy' w='x120'>{t('Served_By')}</Th>,
<Th key={'ts'} direction={sort[1]} active={sort[0] === 'ts'} onClick={onHeaderClick} sort='ts' w='x120'>{t('Started_At')}</Th>,
<Th key={'lm'} direction={sort[1]} active={sort[0] === 'lm'} onClick={onHeaderClick} sort='visibility' w='x120'>{t('Last_Message')}</Th>,
<Th key={'status'} direction={sort[1]} active={sort[0] === 'status'} onClick={onHeaderClick} sort='status' w='x120'>{t('Status')}</Th>,
<Th key={'remove'} w='x40'>{t('Remove')}</Th>,
].filter(Boolean), [sort, onHeaderClick, t]);
const renderRow = useCallback(({ _id, fname, servedBy, ts, lm, department, open }) => <Table.Row key={_id} tabIndex={0} role='link' onClick={() => onRowClick(_id)} action qa-user-id={_id}>
@ -114,7 +136,8 @@ function CurrentChatsRoute() {
<Table.Cell withTruncatedText>{moment(ts).format('L LTS')}</Table.Cell>
<Table.Cell withTruncatedText>{moment(lm).format('L LTS')}</Table.Cell>
<Table.Cell withTruncatedText>{open ? t('Open') : t('Closed')}</Table.Cell>
</Table.Row>, [onRowClick, t]);
{!open && <RemoveChatButton _id={_id} reload={reload}/>}
</Table.Row>, [onRowClick, reload, t]);
if (!canViewCurrentChats) {
return <NotAuthorizedPage />;
@ -129,7 +152,6 @@ function CurrentChatsRoute() {
reload={reload}
header={header}
renderRow={renderRow}
departments={departments}
title={'Current Chats'}>
</CurrentChatsPage>;
}

@ -1,4 +1,4 @@
import { Icon, Table, Callout } from '@rocket.chat/fuselage';
import { Icon, Table, Callout, Button } from '@rocket.chat/fuselage';
import React, { useState, memo } from 'react';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
@ -43,7 +43,11 @@ export function RemoveCustomFieldButton({ _id, reload }) {
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}

@ -1,7 +1,7 @@
import { useDebouncedValue, useMediaQuery, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Box, Table, Icon } from '@rocket.chat/fuselage';
import { Box, Table, Icon, Button } from '@rocket.chat/fuselage';
import { Th } from '../../components/GenericTable';
import { useTranslation } from '../../contexts/TranslationContext';
@ -13,6 +13,7 @@ import ManagersPage from './ManagersPage';
import UserAvatar from '../../components/basic/avatar/UserAvatar';
export function RemoveManagerButton({ _id, reload }) {
const t = useTranslation();
const deleteAction = useEndpointAction('DELETE', `livechat/users/manager/${ _id }`);
const handleRemoveClick = useMutableCallback(async () => {
@ -21,7 +22,11 @@ export function RemoveManagerButton({ _id, reload }) {
reload();
}
});
return <Table.Cell fontScale='p1' clickable={true} color='hint' onClick={handleRemoveClick} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' clickable={true} color='hint' onClick={handleRemoveClick} withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleRemoveClick}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const sortDir = (sortDir) => (sortDir === 'asc' ? 1 : -1);

@ -1,5 +1,5 @@
import { Table, Callout, Icon, Button } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { Table, Callout, Icon } from '@rocket.chat/fuselage';
import { useMutableCallback, Button } from '@rocket.chat/fuselage-hooks';
import React, { useState, memo, useMemo } from 'react';
import GenericTable from '../../components/GenericTable';
@ -79,8 +79,8 @@ const TriggersRow = memo(function TriggersRow(props) {
{enabled ? t('Yes') : t('No')}
</Table.Cell>
<Table.Cell withTruncatedText>
<Button onClick={handleDelete} small>
<Icon name='trash' size='x16' />
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>
</Table.Row>;
@ -131,7 +131,10 @@ export function TriggersTable({ triggers, totalTriggers, params, onChangeParams,
<GenericTable.HeaderCell>
{t('Enabled')}
</GenericTable.HeaderCell>
<GenericTable.HeaderCell width='x60'/>
<GenericTable.HeaderCell width='x60'>
{t('Remove')}
</GenericTable.HeaderCell>
</>}
results={triggers}
total={totalTriggers}

@ -1,4 +1,4 @@
import { Table, Callout, Box, TextInput, Icon } from '@rocket.chat/fuselage';
import { Table, Callout, Box, TextInput, Icon, Button } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useState, memo, useMemo, useEffect } from 'react';
@ -43,7 +43,11 @@ export function RemoveBusinessHourButton({ _id, type, reload }) {
setModal(<DeleteWarningModal onDelete={onBusinessHour} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const FilterByText = memo(({ setFilter, ...props }) => {

@ -2,7 +2,7 @@
import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Table, Icon } from '@rocket.chat/fuselage';
import { Table, Icon, Button } from '@rocket.chat/fuselage';
import { Th } from '../../../../client/components/GenericTable';
import { useTranslation } from '../../../../client/contexts/TranslationContext';
@ -49,7 +49,11 @@ export function RemovePriorityButton({ _id, reload }) {
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const sortDir = (sortDir) => (sortDir === 'asc' ? 1 : -1);

@ -2,7 +2,7 @@
import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Table, Icon } from '@rocket.chat/fuselage';
import { Table, Icon, Button } from '@rocket.chat/fuselage';
import { Th } from '../../../../client/components/GenericTable';
import { useTranslation } from '../../../../client/contexts/TranslationContext';
@ -50,7 +50,11 @@ export function RemoveTagButton({ _id, reload }) {
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const sortDir = (sortDir) => (sortDir === 'asc' ? 1 : -1);

@ -2,7 +2,7 @@
import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useMemo, useCallback, useState } from 'react';
import { Table, Icon } from '@rocket.chat/fuselage';
import { Table, Icon, Button } from '@rocket.chat/fuselage';
import { Th } from '../../../../client/components/GenericTable';
import { useTranslation } from '../../../../client/contexts/TranslationContext';
@ -51,7 +51,11 @@ export function RemoveUnitButton({ _id, reload }) {
setModal(<DeleteWarningModal onDelete={onDeleteAgent} onCancel={() => setModal()}/>);
});
return <Table.Cell fontScale='p1' color='hint' onClick={handleDelete} withTruncatedText><Icon name='trash' size='x20'/></Table.Cell>;
return <Table.Cell fontScale='p1' color='hint' withTruncatedText>
<Button small ghost title={t('Remove')} onClick={handleDelete}>
<Icon name='trash' size='x16'/>
</Button>
</Table.Cell>;
}
const sortDir = (sortDir) => (sortDir === 'asc' ? 1 : -1);

@ -3215,6 +3215,8 @@
"Send_request_on": "Send Request on",
"Agent_messages": "Agent Messages",
"Chat_close": "Chat Close",
"Chats_removed": "Chats Removed",
"Chat_removed": "Chat Removed",
"Chat_queued": "Chat Queued",
"Chat_start": "Chat Start",
"Chat_taken": "Chat Taken",

Loading…
Cancel
Save