1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

added message editing button

This commit is contained in:
Fedor Katurov 2020-09-07 15:22:27 +07:00
parent a0d18076ad
commit 4c4a33a819
5 changed files with 67 additions and 28 deletions

View file

@ -42,6 +42,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
z-index: 6; z-index: 6;
white-space: nowrap;
animation: appear 0.25s forwards; animation: appear 0.25s forwards;
} }

View file

@ -1,27 +1,45 @@
import React, { FC } from 'react'; import React, { FC, useCallback } from 'react';
import { IMessage } from '~/redux/types'; import { IMessage } from '~/redux/types';
import styles from './styles.scss'; import styles from './styles.scss';
import { formatText, getURL, getPrettyDate } from '~/utils/dom'; import { formatText, getURL, getPrettyDate } from '~/utils/dom';
import { PRESETS } from '~/constants/urls'; import { PRESETS } from '~/constants/urls';
import classNames from 'classnames'; import classNames from 'classnames';
import { Group } from '~/components/containers/Group'; import { Group } from '~/components/containers/Group';
import { CommentMenu } from '~/components/node/CommentMenu';
import { MessageForm } from '~/components/profile/MessageForm';
interface IProps { interface IProps {
message: IMessage; message: IMessage;
incoming: boolean; incoming: boolean;
onEdit: (id: number) => void;
onDelete: (id: number) => void;
isEditing: boolean;
} }
const Message: FC<IProps> = ({ message, incoming }) => ( const Message: FC<IProps> = ({ message, incoming, onEdit, onDelete, isEditing }) => {
<div className={classNames(styles.message, { [styles.incoming]: incoming })}> const onEditClicked = useCallback(() => onEdit(message.id), [message.id]);
<Group className={styles.text} dangerouslySetInnerHTML={{ __html: formatText(message.text) }} /> const onDeleteClicked = useCallback(() => onDelete(message.id), [message.id]);
<div return (
className={styles.avatar} <div className={classNames(styles.message, { [styles.incoming]: incoming })}>
style={{ backgroundImage: `url("${getURL(message.from.photo, PRESETS.avatar)}")` }} {isEditing ? (
/> <div className={styles.form}>
<MessageForm id={message.id} text={message.text} />
</div>
) : (
<div className={styles.text}>
{!incoming && <CommentMenu onEdit={onEditClicked} onDelete={onDeleteClicked} />}
<Group dangerouslySetInnerHTML={{ __html: formatText(message.text) }} />
</div>
)}
<div className={styles.stamp}>{getPrettyDate(message.created_at)}</div> <div
</div> className={styles.avatar}
); style={{ backgroundImage: `url("${getURL(message.from.photo, PRESETS.avatar)}")` }}
/>
<div className={styles.stamp}>{getPrettyDate(message.created_at)}</div>
</div>
);
};
export { Message }; export { Message };

View file

@ -57,7 +57,6 @@ $outgoing_color: $comment_bg;
background: 50% 50% no-repeat; background: 50% 50% no-repeat;
background-size: cover; background-size: cover;
// display: none;
} }
.text { .text {
@ -65,8 +64,17 @@ $outgoing_color: $comment_bg;
background: $outgoing_color; background: $outgoing_color;
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
width: 90%; width: 100%;
border-radius: $radius $radius 0 $radius; border-radius: $radius $radius 0 $radius;
position: relative;
box-sizing: border-box;
}
.form {
width: 100%;
border-radius: $radius $radius 0 $radius;
background: $outgoing_color;
box-sizing: border-box;
} }
.stamp { .stamp {

View file

@ -18,21 +18,27 @@ const mapDispatchToProps = {
authSendMessage: AUTH_ACTIONS.authSendMessage, authSendMessage: AUTH_ACTIONS.authSendMessage,
}; };
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}; type IProps = ReturnType<typeof mapStateToProps> &
typeof mapDispatchToProps & {
id?: number;
text?: string;
};
const MessageFormUnconnected: FC<IProps> = ({ const MessageFormUnconnected: FC<IProps> = ({
id = 0,
text: initialText = '',
profile: { is_sending_messages, is_loading_messages, messages_error }, profile: { is_sending_messages, is_loading_messages, messages_error },
authSendMessage, authSendMessage,
}) => { }) => {
const [text, setText] = useState(''); const [text, setText] = useState(initialText);
const onSuccess = useCallback(() => { const onSuccess = useCallback(() => {
setText(''); setText('');
}, [setText]); }, [setText]);
const onSubmit = useCallback(() => { const onSubmit = useCallback(() => {
authSendMessage({ text }, onSuccess); authSendMessage({ text, id }, onSuccess);
}, [authSendMessage, text, onSuccess]); }, [authSendMessage, text, id, onSuccess]);
const onKeyDown = useCallback<KeyboardEventHandler<HTMLTextAreaElement>>( const onKeyDown = useCallback<KeyboardEventHandler<HTMLTextAreaElement>>(
({ ctrlKey, key }) => { ({ ctrlKey, key }) => {
@ -82,9 +88,6 @@ const MessageFormUnconnected: FC<IProps> = ({
); );
}; };
const MessageForm = connect( const MessageForm = connect(mapStateToProps, mapDispatchToProps)(MessageFormUnconnected);
mapStateToProps,
mapDispatchToProps
)(MessageFormUnconnected);
export { MessageForm }; export { MessageForm };

View file

@ -1,6 +1,6 @@
import React, { FC, useEffect } from 'react'; import React, { FC, useCallback, useEffect, useState } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectAuthProfile, selectAuth, selectAuthUser } from '~/redux/auth/selectors'; import { selectAuthProfile, selectAuthUser } from '~/redux/auth/selectors';
import styles from './styles.scss'; import styles from './styles.scss';
import * as AUTH_ACTIONS from '~/redux/auth/actions'; import * as AUTH_ACTIONS from '~/redux/auth/actions';
import { Message } from '~/components/profile/Message'; import { Message } from '~/components/profile/Message';
@ -20,6 +20,11 @@ const mapDispatchToProps = {
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}; type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGetMessages }) => { const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGetMessages }) => {
const [editingMessageId, setEditingMessageId] = useState(0);
const onEditMessage = useCallback((id: number) => setEditingMessageId(id), [setEditingMessageId]);
const onDeleteMessage = useCallback((id: number) => console.log({ id }), []);
useEffect(() => { useEffect(() => {
if (profile.is_loading || !profile.user || !profile.user.username) return; if (profile.is_loading || !profile.user || !profile.user.username) return;
@ -45,7 +50,14 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGet
.map(( .map((
message // TODO: show files / memo message // TODO: show files / memo
) => ( ) => (
<Message message={message} incoming={id !== message.from.id} key={message.id} /> <Message
message={message}
incoming={id !== message.from.id}
key={message.id}
onEdit={onEditMessage}
onDelete={onDeleteMessage}
isEditing={editingMessageId === message.id}
/>
))} ))}
{!profile.is_loading_messages && profile.messages.length > 0 && ( {!profile.is_loading_messages && profile.messages.length > 0 && (
@ -55,9 +67,6 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGet
); );
}; };
const ProfileMessages = connect( const ProfileMessages = connect(mapStateToProps, mapDispatchToProps)(ProfileMessagesUnconnected);
mapStateToProps,
mapDispatchToProps
)(ProfileMessagesUnconnected);
export { ProfileMessages }; export { ProfileMessages };