[IMPROVE][ENTERPRISE] UI/UX enhancements in Omnichannel Priorities page (#19512)

* [IMPROVE] Search filter on REST API and design system

* [IMPROVE] Close contextual bar when user remove an item from grid.

* [IMPROVE] Removing fixed width from Header table columns.

Co-authored-by: Renato Becker <renato.augusto.becker@gmail.com>
pull/19601/head^2
Rafael Ferreira 5 years ago committed by GitHub
parent 90e30cf4f7
commit a3fd95a82d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      ee/app/livechat-enterprise/server/api/lib/priorities.js
  2. 2
      ee/app/livechat-enterprise/server/api/priorities.js
  3. 14
      ee/client/omnichannel/priorities/EditPriority.js
  4. 4
      ee/client/omnichannel/priorities/PrioritiesPage.js
  5. 13
      ee/client/omnichannel/priorities/PrioritiesRoute.js

@ -1,11 +1,19 @@
import s from 'underscore.string';
import { hasPermissionAsync } from '../../../../../../app/authorization/server/functions/hasPermission';
import LivechatPriority from '../../../../models/server/raw/LivechatPriority';
export async function findPriorities({ userId, pagination: { offset, count, sort } }) {
export async function findPriorities({ userId, text, pagination: { offset, count, sort } }) {
if (!await hasPermissionAsync(userId, 'manage-livechat-priorities') && !await hasPermissionAsync(userId, 'view-l-room')) {
throw new Error('error-not-authorized');
}
const cursor = LivechatPriority.find({}, {
const filterReg = new RegExp(s.escapeRegExp(text), 'i');
const query = { ...text && { $or: [{ name: filterReg }, { description: filterReg }] } };
const cursor = LivechatPriority.find(query, {
sort: sort || { name: 1 },
skip: offset,
limit: count,

@ -5,9 +5,11 @@ API.v1.addRoute('livechat/priorities.list', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
const { sort } = this.parseJsonQuery();
const { text } = this.queryParams;
return API.v1.success(Promise.await(findPriorities({
userId: this.userId,
text,
pagination: {
offset,
count,

@ -74,7 +74,7 @@ export function PriorityEdit({ data, isNew, priorityId, reload, ...props }) {
try {
await savePriority(priorityId, payload);
dispatchToastMessage({ type: 'success', message: t('saved') });
dispatchToastMessage({ type: 'success', message: t('Saved') });
reload();
prioritiesRoute.push({});
} catch (error) {
@ -84,21 +84,21 @@ export function PriorityEdit({ data, isNew, priorityId, reload, ...props }) {
return <VerticalBar.ScrollableContent is='form' { ...props }>
<Field>
<Field.Label>{t('Name')}</Field.Label>
<Field.Label>{t('Name')}*</Field.Label>
<Field.Row>
<TextInput flexGrow={1} value={name} onChange={handleName} error={hasUnsavedChanges && nameError}/>
<TextInput placeholder={t('Name')} flexGrow={1} value={name} onChange={handleName} error={hasUnsavedChanges && nameError}/>
</Field.Row>
</Field>
<Field>
<Field.Label>{t('Description')}</Field.Label>
<Field.Row>
<TextInput flexGrow={1} value={description} onChange={handleDescription} />
<TextInput placeholder={t('Description')} flexGrow={1} value={description} onChange={handleDescription} />
</Field.Row>
</Field>
<Field>
<Field.Label>{t('Estimated_due_time_in_minutes')}</Field.Label>
<Field.Label>{t('Estimated_due_time_in_minutes')}*</Field.Label>
<Field.Row>
<NumberInput value={dueTimeInMinutes} onChange={handleDueTimeInMinutes} flexGrow={1} error={hasUnsavedChanges && dueTimeInMinutesError}/>
<NumberInput placeholder={t('Estimated_due_time_in_minutes')} value={dueTimeInMinutes} onChange={handleDueTimeInMinutes} flexGrow={1} error={hasUnsavedChanges && dueTimeInMinutesError}/>
</Field.Row>
</Field>
@ -106,7 +106,7 @@ export function PriorityEdit({ data, isNew, priorityId, reload, ...props }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' w='full'>
<Margins inlineEnd='x4'>
{ !isNew && <Button flexGrow={1} type='reset' disabled={!hasUnsavedChanges} onClick={handleReset}>{t('Reset')}</Button> }
<Button mie='none' flexGrow={1} disabled={!hasUnsavedChanges && !canSave} onClick={handleSave}>{t('Save')}</Button>
<Button primary mie='none' flexGrow={1} disabled={!hasUnsavedChanges || !canSave} onClick={handleSave}>{t('Save')}</Button>
</Margins>
</Box>
</Field.Row>

@ -29,7 +29,9 @@ function PrioritiesPage({
<Page>
<Page.Header title={title}>
<ButtonGroup>
<Button small onClick={handleClick} title={t('New_Priority')}><Icon name='plus'/></Button>
<Button onClick={handleClick} title={t('New_Priority')}>
<Icon name='plus'/> {t('New')}
</Button>
</ButtonGroup>
</Page.Header>
<Page.Content>

@ -23,7 +23,7 @@ export function RemovePriorityButton({ _id, reload }) {
const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();
const t = useTranslation();
const prioritiesRoute = useRoute('omnichannel-priorities');
const handleRemoveClick = useMutableCallback(async () => {
try {
@ -40,6 +40,7 @@ export function RemovePriorityButton({ _id, reload }) {
try {
await handleRemoveClick();
dispatchToastMessage({ type: 'success', message: t('Priority_removed') });
prioritiesRoute.push({});
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
@ -98,10 +99,10 @@ function PrioritiesRoute() {
const { data, reload } = useEndpointDataExperimental('livechat/priorities.list', query) || {};
const header = useMemo(() => [
<GenericTable.HeaderCell key={'name'} direction={sort[1]} active={sort[0] === 'name'} onClick={onHeaderClick} sort='name' w='x120'>{t('Name')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'description'} direction={sort[1]} active={sort[0] === 'description'} onClick={onHeaderClick} sort='description' w='x200'>{t('Description')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'dueTimeInMinutes'} direction={sort[1]} active={sort[0] === 'dueTimeInMinutes'} onClick={onHeaderClick} sort='dueTimeInMinutes' w='x120'>{t('Estimated_due_time')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'remove'} w='x40'>{t('Remove')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'name'} direction={sort[1]} active={sort[0] === 'name'} onClick={onHeaderClick} sort='name'>{t('Name')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'description'} direction={sort[1]} active={sort[0] === 'description'} onClick={onHeaderClick} sort='description'>{t('Description')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'dueTimeInMinutes'} direction={sort[1]} active={sort[0] === 'dueTimeInMinutes'} onClick={onHeaderClick} sort='dueTimeInMinutes'>{t('Estimated_due_time')}</GenericTable.HeaderCell>,
<GenericTable.HeaderCell key={'remove'} w='x60'>{t('Remove')}</GenericTable.HeaderCell>,
].filter(Boolean), [sort, onHeaderClick, t]);
const renderRow = useCallback(({ _id, name, description, dueTimeInMinutes }) => <Table.Row key={_id} tabIndex={0} role='link' onClick={onRowClick(_id)} action qa-user-id={_id}>
@ -146,7 +147,7 @@ function PrioritiesRoute() {
reload={reload}
header={header}
renderRow={renderRow}
title={'Priorities'}>
title={t('Priorities')}>
<EditPrioritiesTab />
</PrioritiesPage>;
}

Loading…
Cancel
Save