[Improve] Do not require pre-configured tags in Omnichannel chats (#21488)
* create tags community component
* create new tags manual component to community version and with no tags.
* translate missing "Tag_already_exists".
* eslint fixes
* Refactoring Tags component, placeholder and better UI
* missed translation
* refactoring CloseChatModal to accept department data to check "requestTagBeforeClosingChat".
* variable names refactor
* bring tags sorted on rooms endpoints
* Revert "bring tags sorted on rooms endpoints"
This reverts commit e2555c05e4.
* save tags as sorted list.
* Rename Component name.
Co-authored-by: Renato Becker <renato.augusto.becker@gmail.com>
pull/21682/head^2
parent
18c01bdfd6
commit
509b4dc239
@ -0,0 +1,9 @@ |
||||
import { Box, Skeleton } from '@rocket.chat/fuselage'; |
||||
import React from 'react'; |
||||
|
||||
export const FormSkeleton = (props) => ( |
||||
<Box w='full' pb='x24' {...props}> |
||||
<Skeleton mbe='x8' /> |
||||
<Skeleton mbe='x4' /> |
||||
</Box> |
||||
); |
||||
@ -0,0 +1,84 @@ |
||||
import { Field, TextInput, Chip, Button } from '@rocket.chat/fuselage'; |
||||
import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; |
||||
import React, { useState } from 'react'; |
||||
import { useSubscription } from 'use-subscription'; |
||||
|
||||
import { useToastMessageDispatch } from '../../contexts/ToastMessagesContext'; |
||||
import { useTranslation } from '../../contexts/TranslationContext'; |
||||
import { AsyncStatePhase } from '../../hooks/useAsyncState'; |
||||
import { useEndpointData } from '../../hooks/useEndpointData'; |
||||
import { formsSubscription } from '../../views/omnichannel/additionalForms'; |
||||
import { FormSkeleton } from './Skeleton'; |
||||
|
||||
const Tags = ({ tags = [], handler = () => {}, error = '' }) => { |
||||
const { value: tagsResult = [], phase: stateTags } = useEndpointData('livechat/tags.list'); |
||||
const t = useTranslation(); |
||||
const forms = useSubscription(formsSubscription); |
||||
|
||||
const { useCurrentChatTags = () => {} } = forms; |
||||
const Tags = useCurrentChatTags(); |
||||
|
||||
const dispatchToastMessage = useToastMessageDispatch(); |
||||
|
||||
const [tagValue, handleTagValue] = useState(''); |
||||
|
||||
const removeTag = (tag) => { |
||||
const tagsFiltered = tags.filter((tagArray) => tagArray !== tag); |
||||
handler(tagsFiltered); |
||||
}; |
||||
|
||||
const handleTagTextSubmit = useMutableCallback(() => { |
||||
if (!tagValue || tagValue.trim() === '') { |
||||
dispatchToastMessage({ type: 'error', message: t('Enter_a_tag') }); |
||||
handleTagValue(''); |
||||
return; |
||||
} |
||||
if (tags.includes(tagValue)) { |
||||
dispatchToastMessage({ type: 'error', message: t('Tag_already_exists') }); |
||||
return; |
||||
} |
||||
handler([...tags, tagValue]); |
||||
handleTagValue(''); |
||||
}); |
||||
|
||||
if ([stateTags].includes(AsyncStatePhase.LOADING)) { |
||||
return <FormSkeleton />; |
||||
} |
||||
|
||||
const { tags: tagsList } = tagsResult; |
||||
|
||||
return ( |
||||
<> |
||||
<Field.Label mb='x4'>{t('Tags')}</Field.Label> |
||||
{Tags && tagsList && tagsList.length > 0 ? ( |
||||
<Field.Row> |
||||
<Tags value={tags} handler={handler} /> |
||||
</Field.Row> |
||||
) : ( |
||||
<> |
||||
<Field.Row> |
||||
<TextInput |
||||
error={error} |
||||
value={tagValue} |
||||
onChange={(event) => handleTagValue(event.target.value)} |
||||
flexGrow={1} |
||||
placeholder={t('Enter_a_tag')} |
||||
/> |
||||
<Button disabled={!tagValue} mis='x8' title={t('add')} onClick={handleTagTextSubmit}> |
||||
{t('Add')} |
||||
</Button> |
||||
</Field.Row> |
||||
<Field.Row justifyContent='flex-start'> |
||||
{tags.map((tag, i) => ( |
||||
<Chip key={i} onClick={() => removeTag(tag)} mie='x8'> |
||||
{tag} |
||||
</Chip> |
||||
))} |
||||
</Field.Row> |
||||
</> |
||||
)} |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default Tags; |
||||
@ -0,0 +1,19 @@ |
||||
import React from 'react'; |
||||
|
||||
import { AsyncStatePhase } from '../../../hooks/useAsyncState'; |
||||
import { useEndpointData } from '../../../hooks/useEndpointData'; |
||||
import { FormSkeleton } from '../Skeleton'; |
||||
import CloseChatModal from './CloseChatModal'; |
||||
|
||||
const CloseChatModalData = ({ departmentId, onCancel, onConfirm }) => { |
||||
const { value: data, phase: state } = useEndpointData( |
||||
`livechat/department/${departmentId}?includeAgents=false`, |
||||
); |
||||
if ([state].includes(AsyncStatePhase.LOADING)) { |
||||
return <FormSkeleton />; |
||||
} |
||||
const { department } = data || {}; |
||||
return <CloseChatModal onCancel={onCancel} onConfirm={onConfirm} department={department} />; |
||||
}; |
||||
|
||||
export default CloseChatModalData; |
||||
Loading…
Reference in new issue