1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36: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;
flex-direction: column;
z-index: 6;
white-space: nowrap;
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 styles from './styles.scss';
import { formatText, getURL, getPrettyDate } 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';
interface IProps {
message: IMessage;
incoming: boolean;
onEdit: (id: number) => void;
onDelete: (id: number) => void;
isEditing: boolean;
}
const Message: FC<IProps> = ({ message, incoming }) => (
<div className={classNames(styles.message, { [styles.incoming]: incoming })}>
<Group className={styles.text} dangerouslySetInnerHTML={{ __html: formatText(message.text) }} />
const Message: FC<IProps> = ({ message, incoming, onEdit, onDelete, isEditing }) => {
const onEditClicked = useCallback(() => onEdit(message.id), [message.id]);
const onDeleteClicked = useCallback(() => onDelete(message.id), [message.id]);
<div
className={styles.avatar}
style={{ backgroundImage: `url("${getURL(message.from.photo, PRESETS.avatar)}")` }}
/>
return (
<div className={classNames(styles.message, { [styles.incoming]: incoming })}>
{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 };

View file

@ -57,7 +57,6 @@ $outgoing_color: $comment_bg;
background: 50% 50% no-repeat;
background-size: cover;
// display: none;
}
.text {
@ -65,8 +64,17 @@ $outgoing_color: $comment_bg;
background: $outgoing_color;
word-wrap: break-word;
word-break: break-word;
width: 90%;
width: 100%;
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 {

View file

@ -18,21 +18,27 @@ const mapDispatchToProps = {
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> = ({
id = 0,
text: initialText = '',
profile: { is_sending_messages, is_loading_messages, messages_error },
authSendMessage,
}) => {
const [text, setText] = useState('');
const [text, setText] = useState(initialText);
const onSuccess = useCallback(() => {
setText('');
}, [setText]);
const onSubmit = useCallback(() => {
authSendMessage({ text }, onSuccess);
}, [authSendMessage, text, onSuccess]);
authSendMessage({ text, id }, onSuccess);
}, [authSendMessage, text, id, onSuccess]);
const onKeyDown = useCallback<KeyboardEventHandler<HTMLTextAreaElement>>(
({ ctrlKey, key }) => {
@ -82,9 +88,6 @@ const MessageFormUnconnected: FC<IProps> = ({
);
};
const MessageForm = connect(
mapStateToProps,
mapDispatchToProps
)(MessageFormUnconnected);
const MessageForm = connect(mapStateToProps, mapDispatchToProps)(MessageFormUnconnected);
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 { selectAuthProfile, selectAuth, selectAuthUser } from '~/redux/auth/selectors';
import { selectAuthProfile, selectAuthUser } from '~/redux/auth/selectors';
import styles from './styles.scss';
import * as AUTH_ACTIONS from '~/redux/auth/actions';
import { Message } from '~/components/profile/Message';
@ -20,6 +20,11 @@ const mapDispatchToProps = {
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
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(() => {
if (profile.is_loading || !profile.user || !profile.user.username) return;
@ -45,7 +50,14 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGet
.map((
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 && (
@ -55,9 +67,6 @@ const ProfileMessagesUnconnected: FC<IProps> = ({ profile, user: { id }, authGet
);
};
const ProfileMessages = connect(
mapStateToProps,
mapDispatchToProps
)(ProfileMessagesUnconnected);
const ProfileMessages = connect(mapStateToProps, mapDispatchToProps)(ProfileMessagesUnconnected);
export { ProfileMessages };