|
|
|
@ -1,4 +1,13 @@ |
|
|
|
|
import { Box, Button, ButtonGroup, Margins, TextInput, Field, Icon } from '@rocket.chat/fuselage'; |
|
|
|
|
import { |
|
|
|
|
Box, |
|
|
|
|
Button, |
|
|
|
|
ButtonGroup, |
|
|
|
|
Margins, |
|
|
|
|
TextInput, |
|
|
|
|
Field, |
|
|
|
|
Icon, |
|
|
|
|
FieldGroup, |
|
|
|
|
} from '@rocket.chat/fuselage'; |
|
|
|
|
import React, { useCallback, useState, useMemo, useEffect, FC, ChangeEvent } from 'react'; |
|
|
|
|
|
|
|
|
|
import GenericModal from '../../../components/GenericModal'; |
|
|
|
@ -27,6 +36,7 @@ const EditCustomEmoji: FC<EditCustomEmojiProps> = ({ close, onChange, data, ...p |
|
|
|
|
const dispatchToastMessage = useToastMessageDispatch(); |
|
|
|
|
const setModal = useSetModal(); |
|
|
|
|
const absoluteUrl = useAbsoluteUrl(); |
|
|
|
|
const [errors, setErrors] = useState({ name: false, aliases: false }); |
|
|
|
|
|
|
|
|
|
const { _id, name: previousName, aliases: previousAliases } = data || {}; |
|
|
|
|
|
|
|
|
@ -62,20 +72,29 @@ const EditCustomEmoji: FC<EditCustomEmojiProps> = ({ close, onChange, data, ...p |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const handleSave = useCallback(async () => { |
|
|
|
|
if (!emojiFile) { |
|
|
|
|
if (!name) { |
|
|
|
|
return setErrors((prevState) => ({ ...prevState, name: true })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (name === aliases) { |
|
|
|
|
return setErrors((prevState) => ({ ...prevState, aliases: true })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!emojiFile && !newEmojiPreview) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const formData = new FormData(); |
|
|
|
|
formData.append('emoji', emojiFile); |
|
|
|
|
emojiFile && formData.append('emoji', emojiFile); |
|
|
|
|
formData.append('_id', _id); |
|
|
|
|
formData.append('name', name); |
|
|
|
|
formData.append('aliases', aliases); |
|
|
|
|
const result = (await saveAction(formData)) as { success: boolean }; |
|
|
|
|
if (result.success) { |
|
|
|
|
onChange(); |
|
|
|
|
close(); |
|
|
|
|
} |
|
|
|
|
}, [emojiFile, _id, name, aliases, saveAction, onChange]); |
|
|
|
|
}, [emojiFile, _id, name, aliases, saveAction, onChange, close, newEmojiPreview]); |
|
|
|
|
|
|
|
|
|
const deleteAction = useEndpointAction( |
|
|
|
|
'POST', |
|
|
|
@ -84,23 +103,16 @@ const EditCustomEmoji: FC<EditCustomEmojiProps> = ({ close, onChange, data, ...p |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const handleDeleteButtonClick = useCallback(() => { |
|
|
|
|
const handleClose = (): void => { |
|
|
|
|
setModal(null); |
|
|
|
|
close(); |
|
|
|
|
onChange(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handleDelete = async (): Promise<void> => { |
|
|
|
|
try { |
|
|
|
|
await deleteAction(); |
|
|
|
|
setModal(() => ( |
|
|
|
|
<GenericModal variant='success' onClose={handleClose} onConfirm={handleClose}> |
|
|
|
|
{t('Custom_Emoji_Has_Been_Deleted')} |
|
|
|
|
</GenericModal> |
|
|
|
|
)); |
|
|
|
|
dispatchToastMessage({ type: 'success', message: t('Custom_Emoji_Has_Been_Deleted') }); |
|
|
|
|
} catch (error) { |
|
|
|
|
dispatchToastMessage({ type: 'error', message: error }); |
|
|
|
|
} finally { |
|
|
|
|
onChange(); |
|
|
|
|
setModal(null); |
|
|
|
|
close(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -119,76 +131,90 @@ const EditCustomEmoji: FC<EditCustomEmojiProps> = ({ close, onChange, data, ...p |
|
|
|
|
{t('Custom_Emoji_Delete_Warning')} |
|
|
|
|
</GenericModal> |
|
|
|
|
)); |
|
|
|
|
}, [close, deleteAction, dispatchToastMessage, onChange, setModal, t]); |
|
|
|
|
}, [deleteAction, close, dispatchToastMessage, onChange, setModal, t]); |
|
|
|
|
|
|
|
|
|
const handleAliasesChange = useCallback((e) => setAliases(e.currentTarget.value), [setAliases]); |
|
|
|
|
const handleChangeAliases = useCallback( |
|
|
|
|
(e) => { |
|
|
|
|
if (e.currentTarget.value !== name) { |
|
|
|
|
setErrors((prevState) => ({ ...prevState, aliases: false })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return setAliases(e.currentTarget.value); |
|
|
|
|
}, |
|
|
|
|
[setAliases, name], |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const [clickUpload] = useFileInput(setEmojiFile, 'emoji'); |
|
|
|
|
|
|
|
|
|
const handleChangeName = (e: ChangeEvent<HTMLInputElement>): void => { |
|
|
|
|
if (e.currentTarget.value !== '') { |
|
|
|
|
setErrors((prevState) => ({ ...prevState, name: false })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return setName(e.currentTarget.value); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<VerticalBar.ScrollableContent {...(props as any)}> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label>{t('Name')}</Field.Label> |
|
|
|
|
<Field.Row> |
|
|
|
|
<TextInput |
|
|
|
|
value={name} |
|
|
|
|
onChange={(e: ChangeEvent<HTMLInputElement>): void => setName(e.currentTarget.value)} |
|
|
|
|
placeholder={t('Name')} |
|
|
|
|
/> |
|
|
|
|
</Field.Row> |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label>{t('Aliases')}</Field.Label> |
|
|
|
|
<Field.Row> |
|
|
|
|
<TextInput value={aliases} onChange={handleAliasesChange} placeholder={t('Aliases')} /> |
|
|
|
|
</Field.Row> |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label |
|
|
|
|
alignSelf='stretch' |
|
|
|
|
display='flex' |
|
|
|
|
justifyContent='space-between' |
|
|
|
|
alignItems='center' |
|
|
|
|
> |
|
|
|
|
{t('Custom_Emoji')} |
|
|
|
|
<Button square onClick={clickUpload}> |
|
|
|
|
<Icon name='upload' size='x20' /> |
|
|
|
|
</Button> |
|
|
|
|
</Field.Label> |
|
|
|
|
{newEmojiPreview && ( |
|
|
|
|
<Box display='flex' flexDirection='row' mbs='none' justifyContent='center'> |
|
|
|
|
<Margins inline='x4'> |
|
|
|
|
<Box |
|
|
|
|
is='img' |
|
|
|
|
style={{ objectFit: 'contain' }} |
|
|
|
|
w='x120' |
|
|
|
|
h='x120' |
|
|
|
|
src={newEmojiPreview} |
|
|
|
|
/> |
|
|
|
|
</Margins> |
|
|
|
|
</Box> |
|
|
|
|
)} |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Row> |
|
|
|
|
<ButtonGroup stretch w='full'> |
|
|
|
|
<Button onClick={close}>{t('Cancel')}</Button> |
|
|
|
|
<Button primary onClick={handleSave} disabled={!hasUnsavedChanges}> |
|
|
|
|
{t('Save')} |
|
|
|
|
</Button> |
|
|
|
|
</ButtonGroup> |
|
|
|
|
</Field.Row> |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Row> |
|
|
|
|
<ButtonGroup stretch w='full'> |
|
|
|
|
<Button primary danger onClick={handleDeleteButtonClick}> |
|
|
|
|
<Icon name='trash' mie='x4' /> |
|
|
|
|
{t('Delete')} |
|
|
|
|
<FieldGroup> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label>{t('Name')}</Field.Label> |
|
|
|
|
<Field.Row> |
|
|
|
|
<TextInput value={name} onChange={handleChangeName} placeholder={t('Name')} /> |
|
|
|
|
</Field.Row> |
|
|
|
|
{errors.name && ( |
|
|
|
|
<Field.Error>{t('error-the-field-is-required', { field: t('Name') })}</Field.Error> |
|
|
|
|
)} |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label>{t('Aliases')}</Field.Label> |
|
|
|
|
<Field.Row> |
|
|
|
|
<TextInput value={aliases} onChange={handleChangeAliases} placeholder={t('Aliases')} /> |
|
|
|
|
</Field.Row> |
|
|
|
|
{errors.aliases && ( |
|
|
|
|
<Field.Error>{t('Custom_Emoji_Error_Same_Name_And_Alias')}</Field.Error> |
|
|
|
|
)} |
|
|
|
|
</Field> |
|
|
|
|
<Field> |
|
|
|
|
<Field.Label |
|
|
|
|
alignSelf='stretch' |
|
|
|
|
display='flex' |
|
|
|
|
justifyContent='space-between' |
|
|
|
|
alignItems='center' |
|
|
|
|
> |
|
|
|
|
{t('Custom_Emoji')} |
|
|
|
|
<Button square onClick={clickUpload}> |
|
|
|
|
<Icon name='upload' size='x20' /> |
|
|
|
|
</Button> |
|
|
|
|
</ButtonGroup> |
|
|
|
|
</Field.Row> |
|
|
|
|
</Field> |
|
|
|
|
</Field.Label> |
|
|
|
|
{newEmojiPreview && ( |
|
|
|
|
<Box display='flex' flexDirection='row' mbs='none' justifyContent='center'> |
|
|
|
|
<Margins inline='x4'> |
|
|
|
|
<Box |
|
|
|
|
is='img' |
|
|
|
|
style={{ objectFit: 'contain' }} |
|
|
|
|
w='x120' |
|
|
|
|
h='x120' |
|
|
|
|
src={newEmojiPreview} |
|
|
|
|
/> |
|
|
|
|
</Margins> |
|
|
|
|
</Box> |
|
|
|
|
)} |
|
|
|
|
</Field> |
|
|
|
|
</FieldGroup> |
|
|
|
|
<ButtonGroup stretch w='full'> |
|
|
|
|
<Button onClick={close}>{t('Cancel')}</Button> |
|
|
|
|
<Button primary onClick={handleSave} disabled={!hasUnsavedChanges}> |
|
|
|
|
{t('Save')} |
|
|
|
|
</Button> |
|
|
|
|
</ButtonGroup> |
|
|
|
|
|
|
|
|
|
<ButtonGroup stretch w='full'> |
|
|
|
|
<Button primary danger onClick={handleDeleteButtonClick}> |
|
|
|
|
<Icon name='trash' mie='x4' /> |
|
|
|
|
{t('Delete')} |
|
|
|
|
</Button> |
|
|
|
|
</ButtonGroup> |
|
|
|
|
</VerticalBar.ScrollableContent> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|