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:
parent
a0d18076ad
commit
4c4a33a819
5 changed files with 67 additions and 28 deletions
|
@ -42,6 +42,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 6;
|
||||
white-space: nowrap;
|
||||
|
||||
animation: appear 0.25s forwards;
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue