1
0
Fork 0
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:
Fedor Katurov 2022-01-02 20:44:41 +07:00
parent f76a5a4798
commit 168ba8cc04
30 changed files with 268 additions and 448 deletions

View file

@ -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(() => {

View 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 };
};

View 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 };
};

View file

@ -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 };
};

View file

@ -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 };
};

View file

@ -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,
};
};

View file

@ -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 };
};

View file

@ -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(

View file

@ -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);