mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
removed almost all node sagas
This commit is contained in:
parent
f76a5a4798
commit
168ba8cc04
30 changed files with 268 additions and 448 deletions
|
@ -3,21 +3,23 @@ import { useCallback, useEffect, useRef } from 'react';
|
|||
import { FormikHelpers, useFormik, useFormikContext } from 'formik';
|
||||
import { array, object, string } from 'yup';
|
||||
import { FileUploader } from '~/hooks/data/useFileUploader';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { nodePostLocalComment } from '~/redux/node/actions';
|
||||
import { showErrorToast } from '~/utils/errors/showToast';
|
||||
import { hasPath, path } from 'ramda';
|
||||
|
||||
const validationSchema = object().shape({
|
||||
text: string(),
|
||||
files: array(),
|
||||
});
|
||||
|
||||
const onSuccess = ({ resetForm, setStatus, setSubmitting }: FormikHelpers<IComment>) => (
|
||||
e?: string
|
||||
const onSuccess = ({ resetForm, setSubmitting, setErrors }: FormikHelpers<IComment>) => (
|
||||
error?: unknown
|
||||
) => {
|
||||
setSubmitting(false);
|
||||
|
||||
if (e) {
|
||||
setStatus(e);
|
||||
if (hasPath(['response', 'data', 'error'], error)) {
|
||||
const message = path(['response', 'data', 'error'], error) as string;
|
||||
setErrors({ text: message });
|
||||
showErrorToast(error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -30,26 +32,23 @@ export const useCommentFormFormik = (
|
|||
values: IComment,
|
||||
nodeId: INode['id'],
|
||||
uploader: FileUploader,
|
||||
sendData: (data: IComment) => Promise<unknown>,
|
||||
stopEditing?: () => void
|
||||
) => {
|
||||
const dispatch = useDispatch();
|
||||
const { current: initialValues } = useRef(values);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(values: IComment, helpers: FormikHelpers<IComment>) => {
|
||||
helpers.setSubmitting(true);
|
||||
dispatch(
|
||||
nodePostLocalComment(
|
||||
nodeId,
|
||||
{
|
||||
...values,
|
||||
files: uploader.files,
|
||||
},
|
||||
onSuccess(helpers)
|
||||
)
|
||||
);
|
||||
async (values: IComment, helpers: FormikHelpers<IComment>) => {
|
||||
try {
|
||||
helpers.setSubmitting(true);
|
||||
await sendData(values);
|
||||
onSuccess(helpers)();
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
onSuccess(helpers)(error);
|
||||
}
|
||||
},
|
||||
[dispatch, nodeId, uploader.files]
|
||||
[sendData]
|
||||
);
|
||||
|
||||
const onReset = useCallback(() => {
|
||||
|
|
52
src/hooks/comments/useGetComments.ts
Normal file
52
src/hooks/comments/useGetComments.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { KeyLoader } from 'swr';
|
||||
import { IComment } from '~/redux/types';
|
||||
import { API } from '~/constants/api';
|
||||
import { flatten, isNil } from 'ramda';
|
||||
import useSWRInfinite from 'swr/infinite';
|
||||
import { apiGetNodeComments } from '~/redux/node/api';
|
||||
import { COMMENTS_DISPLAY } from '~/redux/node/constants';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const getKey: (nodeId: number) => KeyLoader<IComment[]> = (nodeId: number) => (
|
||||
pageIndex,
|
||||
previousPageData
|
||||
) => {
|
||||
if (pageIndex > 0 && !previousPageData?.length) return null;
|
||||
return `${API.NODE.COMMENT(nodeId)}?page=${pageIndex}`;
|
||||
};
|
||||
|
||||
const extractKey = (key: string) => {
|
||||
const re = new RegExp(`${API.NODE.COMMENT('\\d+')}\\?page=(\\d+)`);
|
||||
const match = key.match(re);
|
||||
|
||||
if (!match || !Array.isArray(match) || isNil(match[1])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return parseInt(match[1], 10) || 0;
|
||||
};
|
||||
|
||||
export const useGetComments = (nodeId: number) => {
|
||||
// TODO: const postedCommentsLength = Math.min(0, data[data.length - 1] - COMMENTS_DISPLAY);
|
||||
|
||||
const { data, isValidating, setSize, size, mutate } = useSWRInfinite(
|
||||
getKey(nodeId),
|
||||
async (key: string) => {
|
||||
const result = await apiGetNodeComments({
|
||||
id: nodeId,
|
||||
take: COMMENTS_DISPLAY,
|
||||
skip: extractKey(key) * COMMENTS_DISPLAY, // TODO: - postedCommentsLength,
|
||||
});
|
||||
|
||||
return result.comments;
|
||||
}
|
||||
);
|
||||
|
||||
const comments = flatten(data || []);
|
||||
const hasMore =
|
||||
!!data?.[data?.length - 1].length && data[data.length - 1].length === COMMENTS_DISPLAY;
|
||||
|
||||
const onLoadMoreComments = useCallback(() => setSize(size + 1), [setSize, size]);
|
||||
|
||||
return { comments, hasMore, onLoadMoreComments, isLoading: !data && isValidating, mutate, data };
|
||||
};
|
62
src/hooks/comments/useNodeComments.ts
Normal file
62
src/hooks/comments/useNodeComments.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { useCallback } from 'react';
|
||||
import { IComment } from '~/redux/types';
|
||||
import { useGetComments } from '~/hooks/comments/useGetComments';
|
||||
import { apiLockComment, apiPostComment } from '~/redux/node/api';
|
||||
import { showErrorToast } from '~/utils/errors/showToast';
|
||||
|
||||
export const useNodeComments = (nodeId: number) => {
|
||||
const { comments, isLoading, onLoadMoreComments, hasMore, data, mutate } = useGetComments(nodeId);
|
||||
|
||||
const onDelete = useCallback(
|
||||
async (id: IComment['id'], isLocked: boolean) => {
|
||||
try {
|
||||
const { deleted_at } = await apiLockComment({ id, nodeId, isLocked });
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
await mutate(
|
||||
prev =>
|
||||
prev?.map(list =>
|
||||
list.map(comment => (comment.id === id ? { ...comment, deleted_at } : comment))
|
||||
),
|
||||
false
|
||||
);
|
||||
} catch (error) {
|
||||
showErrorToast(error);
|
||||
}
|
||||
},
|
||||
[data, mutate, nodeId]
|
||||
);
|
||||
|
||||
const onEdit = useCallback(
|
||||
async (comment: IComment) => {
|
||||
const result = await apiPostComment({ id: nodeId, data: comment });
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Comment was created
|
||||
if (!comment.id) {
|
||||
await mutate(
|
||||
data.map((list, index) => (index === 0 ? [result.comment, ...list] : list)),
|
||||
false
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await mutate(
|
||||
prev =>
|
||||
prev?.map(list =>
|
||||
list.map(it => (it.id === result.comment.id ? { ...it, ...result.comment } : it))
|
||||
),
|
||||
false
|
||||
);
|
||||
},
|
||||
[data, mutate, nodeId]
|
||||
);
|
||||
|
||||
return { onLoadMoreComments, onDelete, comments, hasMore, isLoading, onEdit };
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
import { useShallowSelect } from '~/hooks/data/useShallowSelect';
|
||||
import { selectNode } from '~/redux/node/selectors';
|
||||
import { useLoadNode } from '~/hooks/node/useLoadNode';
|
||||
import { useOnNodeSeen } from '~/hooks/node/useOnNodeSeen';
|
||||
|
||||
export const useFullNode = (id: string) => {
|
||||
const {
|
||||
is_loading: isLoading,
|
||||
current: node,
|
||||
comments,
|
||||
comment_count: commentsCount,
|
||||
is_loading_comments: isLoadingComments,
|
||||
lastSeenCurrent,
|
||||
} = useShallowSelect(selectNode);
|
||||
|
||||
useLoadNode(id);
|
||||
// useOnNodeSeen(node);
|
||||
|
||||
return { node, comments, commentsCount, lastSeenCurrent, isLoading, isLoadingComments };
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
import useSWR from 'swr';
|
||||
import { ApiGetNodeResponse } from '~/redux/node/types';
|
||||
import { API } from '~/constants/api';
|
||||
import { useOnNodeSeen } from '~/hooks/node/useOnNodeSeen';
|
||||
import { apiGetNode } from '~/redux/node/api';
|
||||
import { useCallback } from 'react';
|
||||
import { INode } from '~/redux/types';
|
||||
import { EMPTY_NODE } from '~/redux/node/constants';
|
||||
|
||||
export const useGetNode = (id: number) => {
|
||||
const { data, isValidating, mutate } = useSWR<ApiGetNodeResponse>(API.NODE.GET_NODE(id), () =>
|
||||
apiGetNode({ id })
|
||||
);
|
||||
|
||||
const update = useCallback(
|
||||
async (node?: Partial<INode>) => {
|
||||
if (!data?.node) {
|
||||
await mutate();
|
||||
return;
|
||||
}
|
||||
|
||||
await mutate({ node: { ...data.node, ...node } }, true);
|
||||
},
|
||||
[data, mutate]
|
||||
);
|
||||
|
||||
useOnNodeSeen(data?.node);
|
||||
|
||||
return { node: data?.node || EMPTY_NODE, isLoading: isValidating && !data, update };
|
||||
};
|
|
@ -1,12 +1,35 @@
|
|||
import { useEffect } from 'react';
|
||||
import { nodeGotoNode } from '~/redux/node/actions';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import useSWR from 'swr';
|
||||
import { ApiGetNodeResponse } from '~/redux/node/types';
|
||||
import { API } from '~/constants/api';
|
||||
import { useOnNodeSeen } from '~/hooks/node/useOnNodeSeen';
|
||||
import { apiGetNode } from '~/redux/node/api';
|
||||
import { useCallback } from 'react';
|
||||
import { INode } from '~/redux/types';
|
||||
import { EMPTY_NODE } from '~/redux/node/constants';
|
||||
|
||||
// useLoadNode loads node on id change
|
||||
export const useLoadNode = (id: any) => {
|
||||
const dispatch = useDispatch();
|
||||
export const useLoadNode = (id: number) => {
|
||||
const { data, isValidating, mutate } = useSWR<ApiGetNodeResponse>(API.NODE.GET_NODE(id), () =>
|
||||
apiGetNode({ id })
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(nodeGotoNode(parseInt(id, 10), undefined));
|
||||
}, [dispatch, id]);
|
||||
const update = useCallback(
|
||||
async (node?: Partial<INode>) => {
|
||||
if (!data?.node) {
|
||||
await mutate();
|
||||
return;
|
||||
}
|
||||
|
||||
await mutate({ node: { ...data.node, ...node } }, true);
|
||||
},
|
||||
[data, mutate]
|
||||
);
|
||||
|
||||
useOnNodeSeen(data?.node);
|
||||
|
||||
return {
|
||||
node: data?.node || EMPTY_NODE,
|
||||
isLoading: isValidating && !data,
|
||||
update,
|
||||
lastSeen: data?.last_seen,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { useCallback } from 'react';
|
||||
import { nodeLoadMoreComments, nodeLockComment } from '~/redux/node/actions';
|
||||
import { IComment } from '~/redux/types';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
export const useNodeComments = (nodeId: number) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onLoadMoreComments = useCallback(() => dispatch(nodeLoadMoreComments()), [dispatch]);
|
||||
|
||||
const onDelete = useCallback(
|
||||
(id: IComment['id'], locked: boolean) => dispatch(nodeLockComment(id, locked, nodeId)),
|
||||
[dispatch, nodeId]
|
||||
);
|
||||
|
||||
return { onLoadMoreComments, onDelete };
|
||||
};
|
|
@ -2,11 +2,11 @@ import { useHistory } from 'react-router';
|
|||
import { useCallback } from 'react';
|
||||
import { ITag } from '~/redux/types';
|
||||
import { URLS } from '~/constants/urls';
|
||||
import { useGetNode } from '~/hooks/node/useGetNode';
|
||||
import { useLoadNode } from '~/hooks/node/useLoadNode';
|
||||
import { apiDeleteNodeTag, apiPostNodeTags } from '~/redux/node/api';
|
||||
|
||||
export const useNodeTags = (id: number) => {
|
||||
const { update } = useGetNode(id);
|
||||
const { update } = useLoadNode(id);
|
||||
const history = useHistory();
|
||||
|
||||
const onChange = useCallback(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useGetNode } from '~/hooks/node/useGetNode';
|
||||
import { useLoadNode } from '~/hooks/node/useLoadNode';
|
||||
import { useCallback } from 'react';
|
||||
import { INode } from '~/redux/types';
|
||||
import { apiPostNode } from '~/redux/node/api';
|
||||
|
@ -11,7 +11,7 @@ import { useDispatch } from 'react-redux';
|
|||
|
||||
export const useUpdateNode = (id: number) => {
|
||||
const dispatch = useDispatch();
|
||||
const { update } = useGetNode(id);
|
||||
const { update } = useLoadNode(id);
|
||||
const flowNodes = useShallowSelect(selectFlowNodes);
|
||||
const labNodes = useShallowSelect(selectLabListNodes);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue