mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
added months passed to comments
This commit is contained in:
parent
e9a1a624fd
commit
3dfd886570
7 changed files with 111 additions and 9 deletions
|
@ -1,8 +1,10 @@
|
||||||
import React, { FC, HTMLAttributes, memo } from 'react';
|
import React, { FC, HTMLAttributes, memo } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { parseISO } from 'date-fns';
|
||||||
|
|
||||||
import { CommentContent } from '~/components/comment/CommentContent';
|
import { CommentContent } from '~/components/comment/CommentContent';
|
||||||
|
import { CommentDistance } from '~/components/comment/CommentDistance';
|
||||||
import { CommentWrapper } from '~/components/containers/CommentWrapper';
|
import { CommentWrapper } from '~/components/containers/CommentWrapper';
|
||||||
import { NEW_COMMENT_CLASSNAME } from '~/constants/comment';
|
import { NEW_COMMENT_CLASSNAME } from '~/constants/comment';
|
||||||
import { IComment, ICommentGroup, IFile } from '~/types';
|
import { IComment, ICommentGroup, IFile } from '~/types';
|
||||||
|
@ -11,7 +13,6 @@ import { CommendDeleted } from '../../node/CommendDeleted';
|
||||||
|
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
|
|
||||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
nodeId: number;
|
nodeId: number;
|
||||||
isEmpty?: boolean;
|
isEmpty?: boolean;
|
||||||
|
@ -50,13 +51,25 @@ const Comment: FC<IProps> = memo(
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<div className={styles.wrap}>
|
<div className={styles.wrap}>
|
||||||
{group.comments.map(comment => {
|
{group.comments.map((comment, index) => {
|
||||||
if (comment.deleted_at) {
|
if (comment.deleted_at) {
|
||||||
return <CommendDeleted id={comment.id} onDelete={onDelete} key={comment.id} />;
|
return <CommendDeleted id={comment.id} onDelete={onDelete} key={comment.id} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommentContent
|
<CommentContent
|
||||||
|
prefix={
|
||||||
|
group.distancesInDays[index] > 9 && (
|
||||||
|
<CommentDistance
|
||||||
|
firstDate={comment?.created_at ? parseISO(comment.created_at) : undefined}
|
||||||
|
secondDate={
|
||||||
|
index > 0 && group.comments[index - 1]?.created_at
|
||||||
|
? parseISO(group.comments[index - 1].created_at!)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
saveComment={saveComment}
|
saveComment={saveComment}
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
comment={comment}
|
comment={comment}
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
import React, { createElement, FC, Fragment, memo, useCallback, useMemo, useState } from 'react';
|
import React, {
|
||||||
|
createElement,
|
||||||
|
FC,
|
||||||
|
Fragment,
|
||||||
|
memo,
|
||||||
|
ReactNode,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -18,6 +27,7 @@ import { CommentMenu } from '../CommentMenu';
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
prefix?: ReactNode;
|
||||||
nodeId: number;
|
nodeId: number;
|
||||||
comment: IComment;
|
comment: IComment;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
|
@ -27,7 +37,7 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommentContent: FC<IProps> = memo(
|
const CommentContent: FC<IProps> = memo(
|
||||||
({ comment, canEdit, nodeId, saveComment, onDelete, onShowImageModal }) => {
|
({ comment, canEdit, nodeId, saveComment, onDelete, onShowImageModal, prefix }) => {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
|
||||||
const startEditing = useCallback(() => setIsEditing(true), [setIsEditing]);
|
const startEditing = useCallback(() => setIsEditing(true), [setIsEditing]);
|
||||||
|
@ -74,8 +84,10 @@ const CommentContent: FC<IProps> = memo(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrap}>
|
<div className={styles.wrap}>
|
||||||
{comment.text && (
|
{comment.text.trim() && (
|
||||||
<Group className={classnames(styles.block, styles.block_text)}>
|
<Group className={classnames(styles.block, styles.block_text)}>
|
||||||
|
{!!prefix && <div className={styles.prefix}>{prefix}</div>}
|
||||||
|
|
||||||
{menu}
|
{menu}
|
||||||
|
|
||||||
<Group className={styles.renderers}>
|
<Group className={styles.renderers}>
|
||||||
|
|
|
@ -63,7 +63,6 @@
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
// padding: $gap 0;
|
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
border-top-right-radius: $radius;
|
border-top-right-radius: $radius;
|
||||||
|
@ -162,3 +161,11 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prefix {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
}
|
||||||
|
|
36
src/components/comment/CommentDistance/index.tsx
Normal file
36
src/components/comment/CommentDistance/index.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import React, { FC, memo, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { differenceInDays, formatDistance } from 'date-fns';
|
||||||
|
import ru from 'date-fns/locale/ru';
|
||||||
|
|
||||||
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
|
interface CommentDistanceProps {
|
||||||
|
firstDate?: Date;
|
||||||
|
secondDate?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommentDistance: FC<CommentDistanceProps> = memo(({ firstDate, secondDate }) => {
|
||||||
|
const distance = useMemo(() => {
|
||||||
|
if (!firstDate || !secondDate) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (differenceInDays(secondDate, firstDate) < 30) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatDistance(secondDate, firstDate, {
|
||||||
|
locale: ru,
|
||||||
|
addSuffix: false,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!distance) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={styles.bar}>прошло {distance}</div>;
|
||||||
|
});
|
||||||
|
|
||||||
|
export { CommentDistance };
|
12
src/components/comment/CommentDistance/styles.module.scss
Normal file
12
src/components/comment/CommentDistance/styles.module.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
@import "src/styles/variables";
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
@include inner_shadow;
|
||||||
|
|
||||||
|
font: $font_12_regular;
|
||||||
|
color: darken(white, 50%);
|
||||||
|
background: $content_bg;
|
||||||
|
display: inline-flex;
|
||||||
|
padding: 1px 10px 3px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
import { DetailedHTMLProps, InputHTMLAttributes, ReactElement } from 'react';
|
|
||||||
|
|
||||||
import { ERRORS } from '~/constants/errors';
|
import { ERRORS } from '~/constants/errors';
|
||||||
import { IUser } from '~/types/auth';
|
import { IUser } from '~/types/auth';
|
||||||
|
|
||||||
|
@ -126,6 +124,7 @@ export type IMessage = Omit<IComment, 'user' | 'node'> & {
|
||||||
export interface ICommentGroup {
|
export interface ICommentGroup {
|
||||||
user: IUser;
|
user: IUser;
|
||||||
comments: IComment[];
|
comments: IComment[];
|
||||||
|
distancesInDays: number[];
|
||||||
ids: IComment['id'][];
|
ids: IComment['id'][];
|
||||||
hasNew: boolean;
|
hasNew: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isAfter, isValid, parseISO } from 'date-fns';
|
import { differenceInDays, isAfter, isValid, parseISO } from 'date-fns';
|
||||||
|
|
||||||
import { IComment, ICommentGroup } from '~/types';
|
import { IComment, ICommentGroup } from '~/types';
|
||||||
import { curry, insert, nth, path, remove } from '~/utils/ramda';
|
import { curry, insert, nth, path, remove } from '~/utils/ramda';
|
||||||
|
@ -22,6 +22,21 @@ const compareCommentDates = (commentDateValue?: string, lastSeenDateValue?: stri
|
||||||
return isAfter(commentDate, lastSeenDate);
|
return isAfter(commentDate, lastSeenDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getCommentDistance = (firstDate?: string, secondDate?: string) => {
|
||||||
|
try {
|
||||||
|
if (!firstDate || !secondDate) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const first = parseISO(firstDate);
|
||||||
|
const second = parseISO(secondDate);
|
||||||
|
|
||||||
|
return differenceInDays(second, first);
|
||||||
|
} catch (e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const groupCommentsByUser = (lastSeen?: string) => (
|
export const groupCommentsByUser = (lastSeen?: string) => (
|
||||||
grouppedComments: ICommentGroup[],
|
grouppedComments: ICommentGroup[],
|
||||||
comment: IComment
|
comment: IComment
|
||||||
|
@ -40,6 +55,7 @@ export const groupCommentsByUser = (lastSeen?: string) => (
|
||||||
{
|
{
|
||||||
user: comment.user,
|
user: comment.user,
|
||||||
comments: [comment],
|
comments: [comment],
|
||||||
|
distancesInDays: [0],
|
||||||
ids: [comment.id],
|
ids: [comment.id],
|
||||||
hasNew: compareCommentDates(comment.created_at, lastSeen),
|
hasNew: compareCommentDates(comment.created_at, lastSeen),
|
||||||
},
|
},
|
||||||
|
@ -49,6 +65,13 @@ export const groupCommentsByUser = (lastSeen?: string) => (
|
||||||
...grouppedComments.slice(0, grouppedComments.length - 1),
|
...grouppedComments.slice(0, grouppedComments.length - 1),
|
||||||
{
|
{
|
||||||
...last,
|
...last,
|
||||||
|
distancesInDays: [
|
||||||
|
...last.distancesInDays,
|
||||||
|
getCommentDistance(
|
||||||
|
comment?.created_at,
|
||||||
|
last.comments[last.comments.length - 1]?.created_at
|
||||||
|
),
|
||||||
|
],
|
||||||
comments: [...last.comments, comment],
|
comments: [...last.comments, comment],
|
||||||
ids: [...last.ids, comment.id],
|
ids: [...last.ids, comment.id],
|
||||||
hasNew: last.hasNew || compareCommentDates(comment.created_at, lastSeen),
|
hasNew: last.hasNew || compareCommentDates(comment.created_at, lastSeen),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue