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

made node use context providers

This commit is contained in:
Fedor Katurov 2021-11-19 16:18:51 +07:00
parent 15095b3116
commit f631f79654
8 changed files with 189 additions and 180 deletions

View file

@ -6,53 +6,19 @@ import { NodeCommentsBlock } from '~/components/node/NodeCommentsBlock';
import { NodeCommentForm } from '~/components/node/NodeCommentForm'; import { NodeCommentForm } from '~/components/node/NodeCommentForm';
import { NodeRelatedBlock } from '~/components/node/NodeRelatedBlock'; import { NodeRelatedBlock } from '~/components/node/NodeRelatedBlock';
import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks';
import { IComment, IFile, INode, ITag } from '~/redux/types';
import { NodeTagsBlock } from '~/components/node/NodeTagsBlock'; import { NodeTagsBlock } from '~/components/node/NodeTagsBlock';
import { INodeRelated } from '~/redux/node/types';
import StickyBox from 'react-sticky-box/dist/esnext'; import StickyBox from 'react-sticky-box/dist/esnext';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NodeAuthorBlock } from '~/components/node/NodeAuthorBlock'; import { NodeAuthorBlock } from '~/components/node/NodeAuthorBlock';
import { IUser } from '~/redux/auth/types'; import { useNodeContext } from '~/utils/providers/NodeProvider';
interface IProps { interface IProps {
node: INode;
user: IUser;
isUser: boolean; isUser: boolean;
canEdit: boolean;
isLoading: boolean;
commentsOrder: 'ASC' | 'DESC'; commentsOrder: 'ASC' | 'DESC';
comments: IComment[];
commentsCount: number;
isLoadingComments: boolean;
related: INodeRelated;
lastSeenCurrent?: string;
onShowImageModal: (images: IFile[], index: number) => void;
onLoadMoreComments: () => void;
onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
onTagsChange: (tags: string[]) => void;
onTagClick: (tag: Partial<ITag>) => void;
onTagDelete: (id: ITag['ID']) => void;
} }
const NodeBottomBlock: FC<IProps> = ({ const NodeBottomBlock: FC<IProps> = ({ commentsOrder }) => {
node, const { node, related, isUser, isLoading } = useNodeContext();
user,
canEdit,
isLoading,
isUser,
isLoadingComments,
comments,
commentsCount,
commentsOrder,
related,
lastSeenCurrent,
onLoadMoreComments,
onDeleteComment,
onShowImageModal,
onTagsChange,
onTagClick,
onTagDelete,
}) => {
const { inline } = useNodeBlocks(node, isLoading); const { inline } = useNodeBlocks(node, isLoading);
if (node.deleted_at) { if (node.deleted_at) {
@ -66,19 +32,7 @@ const NodeBottomBlock: FC<IProps> = ({
<Group className={styles.comments}> <Group className={styles.comments}>
{inline && <div className={styles.inline}>{inline}</div>} {inline && <div className={styles.inline}>{inline}</div>}
<NodeCommentsBlock <NodeCommentsBlock order={commentsOrder} />
lastSeenCurrent={lastSeenCurrent}
isLoading={isLoading}
isLoadingComments={isLoadingComments}
comments={comments}
count={commentsCount}
order={commentsOrder}
user={user}
node={node}
onShowImageModal={onShowImageModal}
onLoadMoreComments={onLoadMoreComments}
onDeleteComment={onDeleteComment}
/>
{isUser && !isLoading && <NodeCommentForm nodeId={node.id} />} {isUser && !isLoading && <NodeCommentForm nodeId={node.id} />}
</Group> </Group>
@ -89,16 +43,9 @@ const NodeBottomBlock: FC<IProps> = ({
<div className={styles.left_item}> <div className={styles.left_item}>
<NodeAuthorBlock user={node?.user} /> <NodeAuthorBlock user={node?.user} />
</div> </div>
<div className={styles.left_item}> <div className={styles.left_item}>
<NodeTagsBlock <NodeTagsBlock />
tags={node.tags}
canDelete={canEdit}
canAppend={isUser}
isLoading={isLoading}
onChange={onTagsChange}
onTagClick={onTagClick}
onTagDelete={onTagDelete}
/>
</div> </div>
<div className={styles.left_item}> <div className={styles.left_item}>
<NodeRelatedBlock isLoading={isLoading} node={node} related={related} /> <NodeRelatedBlock isLoading={isLoading} node={node} related={related} />

View file

@ -1,40 +1,30 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { NodeNoComments } from '~/components/node/NodeNoComments'; import { NodeNoComments } from '~/components/node/NodeNoComments';
import { NodeComments } from '~/components/node/NodeComments'; import { NodeComments } from '~/components/node/NodeComments';
import { IComment, IFile, INode } from '~/redux/types';
import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks';
import { IUser } from '~/redux/auth/types'; import { useCommentContext } from '~/utils/providers/CommentProvider';
interface IProps { interface IProps {
order: 'ASC' | 'DESC'; order: 'ASC' | 'DESC';
node: INode;
user: IUser;
comments: IComment[];
count: number;
lastSeenCurrent?: string;
isLoading: boolean;
isLoadingComments: boolean;
onShowImageModal: (images: IFile[], index: number) => void;
onLoadMoreComments: () => void;
onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
} }
const NodeCommentsBlock: FC<IProps> = ({ const NodeCommentsBlock: FC<IProps> = () => {
const {
node, node,
user, user,
comments, comments,
count, count,
lastSeenCurrent, lastSeenCurrent,
isLoading, isLoadingNode,
isLoadingComments, isLoadingComments,
onLoadMoreComments, onLoadMoreComments,
onDeleteComment, onDeleteComment,
onShowImageModal, onShowImageModal,
}) => { } = useCommentContext();
const { inline } = useNodeBlocks(node, isLoading); const { inline } = useNodeBlocks(node, isLoadingNode);
return isLoading || isLoadingComments || (!comments.length && !inline) ? ( return isLoadingNode || isLoadingComments || (!comments.length && !inline) ? (
<NodeNoComments is_loading={isLoadingComments || isLoading} /> <NodeNoComments is_loading={isLoadingComments || isLoadingNode} />
) : ( ) : (
<NodeComments <NodeComments
count={count} count={count}

View file

@ -1,18 +1,11 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { ITag } from '~/redux/types';
import { NodeTags } from '~/components/node/NodeTags'; import { NodeTags } from '~/components/node/NodeTags';
import { useTagContext } from '~/utils/providers/TagProvider';
interface IProps { interface IProps {}
tags: ITag[];
canAppend: boolean;
canDelete: boolean;
isLoading: boolean;
onChange: (tags: string[]) => void;
onTagClick: (tag: Partial<ITag>) => void;
onTagDelete: (id: ITag['ID']) => void;
}
const NodeTagsBlock: FC<IProps> = ({ const NodeTagsBlock: FC<IProps> = ({}) => {
const {
tags, tags,
canAppend, canAppend,
canDelete, canDelete,
@ -20,7 +13,8 @@ const NodeTagsBlock: FC<IProps> = ({
onChange, onChange,
onTagClick, onTagClick,
onTagDelete, onTagDelete,
}) => { } = useTagContext();
if (isLoading) { if (isLoading) {
return null; return null;
} }

View file

@ -12,52 +12,18 @@ import { NodeBottomBlock } from '~/components/node/NodeBottomBlock';
import { useNodeCoverImage } from '~/utils/hooks/node/useNodeCoverImage'; import { useNodeCoverImage } from '~/utils/hooks/node/useNodeCoverImage';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog'; import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog';
import { useNodePermissions } from '~/utils/hooks/node/useNodePermissions';
import { IComment, IFile, INode, ITag } from '~/redux/types';
import { INodeRelated } from '~/redux/node/types';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { IUser } from '~/redux/auth/types'; import { useNodeContext } from '~/utils/providers/NodeProvider';
type IProps = { type IProps = {};
node: INode;
user: IUser; const NodeLayout: FC<IProps> = () => {
lastSeenCurrent?: string; const { node, isUser, isLoading } = useNodeContext();
related: INodeRelated;
comments: IComment[];
commentsCount: number;
isUser: boolean;
isLoading: boolean;
isLoadingComments: boolean;
onShowImageModal: (images: IFile[], index: number) => void;
onLoadMoreComments: () => void;
onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
onTagsChange: (tags: string[]) => void;
onTagClick: (tag: Partial<ITag>) => void;
onTagDelete: (id: ITag['ID']) => void;
};
const NodeLayout: FC<IProps> = ({
node,
user,
comments,
commentsCount,
related,
lastSeenCurrent,
isUser,
isLoading,
isLoadingComments,
onLoadMoreComments,
onDeleteComment,
onShowImageModal,
onTagsChange,
onTagClick,
onTagDelete,
}) => {
useNodeCoverImage(node); useNodeCoverImage(node);
const { head, block } = useNodeBlocks(node, isLoading); const { head, block } = useNodeBlocks(node, isLoading);
const [canEdit] = useNodePermissions(node);
return ( return (
<div className={styles.wrap}> <div className={styles.wrap}>
@ -71,25 +37,7 @@ const NodeLayout: FC<IProps> = ({
<NodePanel node={node} isLoading={isLoading} /> <NodePanel node={node} isLoading={isLoading} />
</div> </div>
<NodeBottomBlock <NodeBottomBlock isUser={isUser} commentsOrder="DESC" />
isUser={isUser}
user={user}
node={node}
canEdit={canEdit}
comments={comments}
commentsCount={commentsCount}
commentsOrder="DESC"
related={related}
isLoadingComments={isLoadingComments}
isLoading={isLoading}
lastSeenCurrent={lastSeenCurrent}
onShowImageModal={onShowImageModal}
onLoadMoreComments={onLoadMoreComments}
onDeleteComment={onDeleteComment}
onTagsChange={onTagsChange}
onTagClick={onTagClick}
onTagDelete={onTagDelete}
/>
<Footer /> <Footer />
</Card> </Card>

View file

@ -7,6 +7,10 @@ import { useImageModal } from '~/utils/hooks/useImageModal';
import { useNodeComments } from '~/utils/hooks/node/useNodeComments'; import { useNodeComments } from '~/utils/hooks/node/useNodeComments';
import { useUser } from '~/utils/hooks/user/userUser'; import { useUser } from '~/utils/hooks/user/userUser';
import { useNodeTags } from '~/utils/hooks/node/useNodeTags'; import { useNodeTags } from '~/utils/hooks/node/useNodeTags';
import { NodeProvider } from '~/utils/providers/NodeProvider';
import { CommentProvider } from '~/utils/providers/CommentProvider';
import { TagProvider } from '~/utils/providers/TagProvider';
import { useNodePermissions } from '~/utils/hooks/node/useNodePermissions';
type Props = RouteComponentProps<{ id: string }> & {}; type Props = RouteComponentProps<{ id: string }> & {};
@ -31,26 +35,37 @@ const NodePage: FC<Props> = ({
parseInt(id, 10) parseInt(id, 10)
); );
const user = useUser(); const user = useUser();
const [canEdit] = useNodePermissions(node);
useScrollToTop([id, isLoadingComments]); useScrollToTop([id, isLoadingComments]);
return ( return (
<NodeLayout <NodeProvider node={node} related={related} isUser={user.is_user} isLoading={isLoading}>
<CommentProvider
node={node} node={node}
user={user} user={user}
related={related}
lastSeenCurrent={lastSeenCurrent}
comments={comments} comments={comments}
commentsCount={commentsCount} count={commentsCount}
isUser={user.is_user} lastSeenCurrent={lastSeenCurrent}
isLoading={isLoading} isLoadingNode={isLoading}
isLoadingComments={isLoadingComments} isLoadingComments={isLoadingComments}
onShowImageModal={onShowImageModal} onShowImageModal={onShowImageModal}
onLoadMoreComments={onLoadMoreComments} onLoadMoreComments={onLoadMoreComments}
onDeleteComment={onDeleteComment} onDeleteComment={onDeleteComment}
onTagDelete={onTagDelete} >
<TagProvider
tags={node.tags}
canAppend={user.is_user}
canDelete={canEdit}
isLoading={isLoading}
onChange={onTagsChange}
onTagClick={onTagClick} onTagClick={onTagClick}
onTagsChange={onTagsChange} onTagDelete={onTagDelete}
/> >
<NodeLayout />
</TagProvider>
</CommentProvider>
</NodeProvider>
); );
}; };

View file

@ -0,0 +1,37 @@
import { IComment, IFile, INode } from '~/redux/types';
import { IUser } from '~/redux/auth/types';
import React, { createContext, FC, useContext } from 'react';
import { EMPTY_USER } from '~/redux/auth/constants';
import { EMPTY_NODE } from '~/redux/node/constants';
export interface CommentProviderProps {
node: INode;
user: IUser;
comments: IComment[];
count: number;
lastSeenCurrent?: string;
isLoadingNode: boolean;
isLoadingComments: boolean;
onShowImageModal: (images: IFile[], index: number) => void;
onLoadMoreComments: () => void;
onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
}
const CommentContext = createContext<CommentProviderProps>({
node: EMPTY_NODE,
user: EMPTY_USER,
comments: [],
count: 0,
lastSeenCurrent: undefined,
isLoadingNode: false,
isLoadingComments: false,
onShowImageModal: () => {},
onLoadMoreComments: () => {},
onDeleteComment: () => {},
});
export const CommentProvider: FC<CommentProviderProps> = ({ children, ...contextValue }) => {
return <CommentContext.Provider value={contextValue}>{children}</CommentContext.Provider>;
};
export const useCommentContext = () => useContext(CommentContext);

View file

@ -0,0 +1,50 @@
import { INode } from '~/redux/types';
import { INodeRelated } from '~/redux/node/types';
import { EMPTY_NODE } from '~/redux/node/constants';
import React, { createContext, FC, useContext } from 'react';
export interface NodeContextProps {
node: INode;
related: INodeRelated;
isUser: boolean;
isLoading: boolean;
// user: IUser;
// isLoadingComments: boolean;
// lastSeenCurrent?: string;
// commentsCount: number;
// comments: IComment[];
// onShowImageModal: (images: IFile[], index: number) => void;
// onLoadMoreComments: () => void;
// onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
// onTagsChange: (tags: string[]) => void;
// onTagClick: (tag: Partial<ITag>) => void;
// onTagDelete: (id: ITag['ID']) => void;
}
export const NodeContext = createContext<NodeContextProps>({
node: EMPTY_NODE,
related: { albums: {}, similar: [] },
isUser: false,
isLoading: false,
// CommentContext
// user: EMPTY_USER,
// lastSeenCurrent: undefined,
// comments: [],
// commentsCount: 0,
// onLoadMoreComments: () => {},
// onShowImageModal: () => {},
// onDeleteComment: () => {},
// isLoadingComments: false,
// TagContext
// onTagsChange: () => {},
// onTagClick: () => {},
// onTagDelete: () => {},
});
export const NodeProvider: FC<NodeContextProps> = ({ children, ...contextValue }) => {
return <NodeContext.Provider value={contextValue}>{children}</NodeContext.Provider>;
};
export const useNodeContext = () => useContext(NodeContext);

View file

@ -0,0 +1,28 @@
import React, { createContext, FC, useContext } from 'react';
import { ITag } from '~/redux/types';
export interface TagContextProps {
tags: ITag[];
canAppend: boolean;
canDelete: boolean;
isLoading: boolean;
onChange: (tags: string[]) => void;
onTagClick: (tag: Partial<ITag>) => void;
onTagDelete: (id: ITag['ID']) => void;
}
const TagContext = createContext<TagContextProps>({
tags: [],
canDelete: false,
canAppend: false,
isLoading: false,
onChange: () => {},
onTagClick: () => {},
onTagDelete: () => {},
});
export const TagProvider: FC<TagContextProps> = ({ children, ...contextValue }) => {
return <TagContext.Provider value={contextValue}>{children}</TagContext.Provider>;
};
export const useTagContext = () => useContext(TagContext);