From 3f3c1516c8f4579c910d746d8c50e3e9eb07a022 Mon Sep 17 00:00:00 2001 From: Fedor Katurov <gotham48@gmail.com> Date: Tue, 8 Sep 2020 13:27:00 +0700 Subject: [PATCH] fixed message delete appearance --- src/components/profile/Message/index.tsx | 44 +++++++++++++++++-- src/components/profile/Message/styles.scss | 12 +++++ src/constants/errors.ts | 2 + .../profile/ProfileMessages/index.tsx | 6 ++- src/redux/messages/actions.ts | 3 +- src/redux/messages/api.ts | 7 ++- src/redux/messages/sagas.ts | 3 +- 7 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/components/profile/Message/index.tsx b/src/components/profile/Message/index.tsx index b1415fa7..c543f264 100644 --- a/src/components/profile/Message/index.tsx +++ b/src/components/profile/Message/index.tsx @@ -1,25 +1,61 @@ import React, { FC, useCallback } from 'react'; import { IMessage } from '~/redux/types'; import styles from './styles.scss'; -import { formatText, getURL, getPrettyDate } from '~/utils/dom'; +import { formatText, getPrettyDate, getURL } from '~/utils/dom'; import { PRESETS } from '~/constants/urls'; import classNames from 'classnames'; import { Group } from '~/components/containers/Group'; import { CommentMenu } from '~/components/node/CommentMenu'; import { MessageForm } from '~/components/profile/MessageForm'; +import { Filler } from '~/components/containers/Filler'; +import { Button } from '~/components/input/Button'; interface IProps { message: IMessage; incoming: boolean; onEdit: (id: number) => void; onDelete: (id: number) => void; + onRestore: (id: number) => void; onCancelEdit: () => void; isEditing: boolean; } -const Message: FC<IProps> = ({ message, incoming, onEdit, onDelete, isEditing, onCancelEdit }) => { - const onEditClicked = useCallback(() => onEdit(message.id), [message.id]); - const onDeleteClicked = useCallback(() => onDelete(message.id), [message.id]); +const Message: FC<IProps> = ({ + message, + incoming, + onEdit, + onDelete, + isEditing, + onCancelEdit, + onRestore, +}) => { + const onEditClicked = useCallback(() => onEdit(message.id), [onEdit, message.id]); + const onDeleteClicked = useCallback(() => onDelete(message.id), [onDelete, message.id]); + const onRestoreClicked = useCallback(() => onRestore(message.id), [onRestore, message.id]); + + if (message.deleted_at) { + return ( + <div className={classNames(styles.message)}> + <Group className={styles.deleted} horizontal> + <Filler>Сообщение удалено</Filler> + <Button + size="mini" + onClick={onRestoreClicked} + color="link" + iconLeft="restore" + className={styles.restore} + > + Восстановить + </Button> + </Group> + + <div + className={styles.avatar} + style={{ backgroundImage: `url("${getURL(message.from.photo, PRESETS.avatar)}")` }} + /> + </div> + ); + } return ( <div className={classNames(styles.message, { [styles.incoming]: incoming })}> diff --git a/src/components/profile/Message/styles.scss b/src/components/profile/Message/styles.scss index 19b11bb2..1f20ef35 100644 --- a/src/components/profile/Message/styles.scss +++ b/src/components/profile/Message/styles.scss @@ -87,3 +87,15 @@ $outgoing_color: $comment_bg; padding: 2px $gap; border-radius: $radius; } + +.restore { + color: $red; + fill: $red; +} + +.deleted { + background: mix($red, $content_bg, 50%); + border-radius: $radius $radius $radius 0; + padding: $gap / 2; + z-index: 2; +} diff --git a/src/constants/errors.ts b/src/constants/errors.ts index 70dd4a27..1aac68d2 100644 --- a/src/constants/errors.ts +++ b/src/constants/errors.ts @@ -40,6 +40,7 @@ export const ERRORS = { CANT_SAVE_USER: 'CantSaveUser', CANT_DELETE_COMMENT: 'CantDeleteComment', CANT_RESTORE_COMMENT: 'CantRestoreComment', + MESSAGE_NOT_FOUND: 'MessageNotFound', }; export const ERROR_LITERAL = { @@ -85,4 +86,5 @@ export const ERROR_LITERAL = { [ERRORS.CANT_SAVE_USER]: 'Не удалось сохранить пользователя', [ERRORS.CANT_DELETE_COMMENT]: 'Не удалось удалить комментарий', [ERRORS.CANT_RESTORE_COMMENT]: 'Не удалось восстановить комментарий', + [ERRORS.MESSAGE_NOT_FOUND]: 'Сообщение не найдено', }; diff --git a/src/containers/profile/ProfileMessages/index.tsx b/src/containers/profile/ProfileMessages/index.tsx index b91bc89b..7700f048 100644 --- a/src/containers/profile/ProfileMessages/index.tsx +++ b/src/containers/profile/ProfileMessages/index.tsx @@ -33,7 +33,10 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ const onEditMessage = useCallback((id: number) => setEditingMessageId(id), [setEditingMessageId]); const onCancelEdit = useCallback(() => setEditingMessageId(0), [setEditingMessageId]); - const onDeleteMessage = useCallback((id: number) => messagesDeleteMessage(id), [ + const onDeleteMessage = useCallback((id: number) => messagesDeleteMessage(id, true), [ + messagesDeleteMessage, + ]); + const onRestoreMessage = useCallback((id: number) => messagesDeleteMessage(id, false), [ messagesDeleteMessage, ]); @@ -70,6 +73,7 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ onDelete={onDeleteMessage} isEditing={editingMessageId === message.id} onCancelEdit={onCancelEdit} + onRestore={onRestoreMessage} /> ))} diff --git a/src/redux/messages/actions.ts b/src/redux/messages/actions.ts index 1679d571..ce563b68 100644 --- a/src/redux/messages/actions.ts +++ b/src/redux/messages/actions.ts @@ -13,9 +13,10 @@ export const messagesSendMessage = (message: Partial<IMessage>, onSuccess) => ({ onSuccess, }); -export const messagesDeleteMessage = (id: IMessage['id']) => ({ +export const messagesDeleteMessage = (id: IMessage['id'], is_locked: boolean) => ({ type: MESSAGES_ACTIONS.DELETE_MESSAGE, id, + is_locked, }); export const messagesSet = (messages: Partial<IMessagesState>) => ({ diff --git a/src/redux/messages/api.ts b/src/redux/messages/api.ts index a5252022..d485d2f4 100644 --- a/src/redux/messages/api.ts +++ b/src/redux/messages/api.ts @@ -25,12 +25,17 @@ export const apiMessagesDeleteMessage = ({ access, username, id, + is_locked, }: { access: string; username: string; id: number; + is_locked: boolean; }): Promise<IResultWithStatus<{ message: IMessage }>> => api - .delete(API.USER.MESSAGE_DELETE(username, id), configWithToken(access)) + .delete( + API.USER.MESSAGE_DELETE(username, id), + configWithToken(access, { params: { is_locked } }) + ) .then(resultMiddleware) .catch(errorMiddleware); diff --git a/src/redux/messages/sagas.ts b/src/redux/messages/sagas.ts index f59b6e66..c2609a28 100644 --- a/src/redux/messages/sagas.ts +++ b/src/redux/messages/sagas.ts @@ -120,7 +120,7 @@ function* sendMessage({ message, onSuccess }: ReturnType<typeof messagesSendMess onSuccess(); } -function* deleteMessage({ id }: ReturnType<typeof messagesDeleteMessage>) { +function* deleteMessage({ id, is_locked }: ReturnType<typeof messagesDeleteMessage>) { const username: ReturnType<typeof selectAuthProfileUsername> = yield select( selectAuthProfileUsername ); @@ -135,6 +135,7 @@ function* deleteMessage({ id }: ReturnType<typeof messagesDeleteMessage>) { { username, id, + is_locked, } );