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

fixed comment deletion with hooks

This commit is contained in:
Fedor Katurov 2021-09-20 14:43:24 +07:00
parent 20926609b9
commit 00396b31c8
8 changed files with 72 additions and 53 deletions

View file

@ -5,14 +5,23 @@ import { PersistGate } from 'redux-persist/integration/react';
import { configureStore } from '~/redux/store'; import { configureStore } from '~/redux/store';
import App from '~/containers/App'; import App from '~/containers/App';
import '~/styles/main.scss'; import '~/styles/main.scss';
import { SWRConfig } from 'swr';
const { store, persistor } = configureStore(); const { store, persistor } = configureStore();
render( render(
<SWRConfig
value={{
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
}}
>
<Provider store={store}> <Provider store={store}>
<PersistGate loading={null} persistor={persistor}> <PersistGate loading={null} persistor={persistor}>
<App /> <App />
</PersistGate> </PersistGate>
</Provider>, </Provider>
</SWRConfig>,
document.getElementById('app') document.getElementById('app')
); );

View file

@ -1,5 +1,4 @@
import React, { FC, useCallback, useEffect } from 'react'; import React, { FC, useCallback, useEffect } from 'react';
import { selectNode, selectNodeComments } from '~/redux/node/selectors';
import { selectAuthIsTester, selectUser } from '~/redux/auth/selectors'; import { selectAuthIsTester, selectUser } from '~/redux/auth/selectors';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
@ -11,7 +10,6 @@ import { BorisStats } from '~/components/boris/BorisStats';
import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
import { selectBorisStats } from '~/redux/boris/selectors'; import { selectBorisStats } from '~/redux/boris/selectors';
import { authSetState, authSetUser } from '~/redux/auth/actions'; import { authSetState, authSetUser } from '~/redux/auth/actions';
import { nodeLoadNode } from '~/redux/node/actions';
import { borisLoadStats } from '~/redux/boris/actions'; import { borisLoadStats } from '~/redux/boris/actions';
import { Container } from '~/containers/main/Container'; import { Container } from '~/containers/main/Container';
import StickyBox from 'react-sticky-box/dist/esnext'; import StickyBox from 'react-sticky-box/dist/esnext';

View file

@ -24,6 +24,6 @@ export const apiSendMessage = ({ username, message }: ApiSendMessageRequest) =>
export const apiDeleteMessage = ({ username, id, is_locked }: ApiDeleteMessageRequest) => export const apiDeleteMessage = ({ username, id, is_locked }: ApiDeleteMessageRequest) =>
api api
.delete<ApiDeleteMessageResult>(API.USER.MESSAGE_DELETE(username, id), { .delete<ApiDeleteMessageResult>(API.USER.MESSAGE_DELETE(username, id), {
params: { is_locked }, params: { isLocked: is_locked },
}) })
.then(cleanResult); .then(cleanResult);

View file

@ -118,10 +118,17 @@ export const nodeLock = (id: INode['id'], is_locked: boolean) => ({
is_locked, is_locked,
}); });
export const nodeLockComment = (id: IComment['id'], is_locked: boolean) => ({ export const nodeLockComment = (
nodeID: INode['id'],
commentID: IComment['id'],
isLocked: boolean,
callback: (e?: string) => void
) => ({
type: NODE_ACTIONS.LOCK_COMMENT, type: NODE_ACTIONS.LOCK_COMMENT,
id, nodeID,
is_locked, commentID,
callback,
isLocked,
}); });
export const nodeEditComment = (id: IComment['id']) => ({ export const nodeEditComment = (id: IComment['id']) => ({

View file

@ -108,10 +108,10 @@ export const apiPostNodeHeroic = ({ id }: ApiPostNodeHeroicRequest) =>
export const apiLockNode = ({ id, is_locked }: ApiLockNodeRequest) => export const apiLockNode = ({ id, is_locked }: ApiLockNodeRequest) =>
api api
.post<ApiLockNodeResult>(API.NODE.POST_LOCK(id), { is_locked }) .post<ApiLockNodeResult>(API.NODE.POST_LOCK(id), { isLocked: is_locked })
.then(cleanResult); .then(cleanResult);
export const apiLockComment = ({ id, is_locked, current }: ApiLockCommentRequest) => export const apiLockComment = ({ nodeID, isLocked, commentID }: ApiLockCommentRequest) =>
api api
.post<ApiLockcommentResult>(API.NODE.LOCK_COMMENT(current, id), { is_locked }) .post<ApiLockcommentResult>(API.NODE.LOCK_COMMENT(nodeID, commentID), { is_locked: isLocked })
.then(cleanResult); .then(cleanResult);

View file

@ -312,41 +312,23 @@ function* onLockSaga({ id, is_locked }: ReturnType<typeof nodeLock>) {
} }
} }
function* onLockCommentSaga({ id, is_locked }: ReturnType<typeof nodeLockComment>) { function* onLockCommentSaga({
const { current, comments }: ReturnType<typeof selectNode> = yield select(selectNode); commentID,
nodeID,
isLocked,
callback,
}: ReturnType<typeof nodeLockComment>) {
try { try {
yield put( yield call(apiLockComment, {
nodeSetComments( commentID,
comments.map(comment => nodeID,
comment.id === id isLocked,
? { ...comment, deleted_at: is_locked ? new Date().toISOString() : undefined }
: comment
)
)
);
const data: Unwrap<typeof apiLockComment> = yield call(apiLockComment, {
current: current.id,
id,
is_locked,
}); });
yield put( callback();
nodeSetComments( } catch (e) {
comments.map(comment => console.log(e);
comment.id === id ? { ...comment, deleted_at: data.deleted_at || undefined } : comment callback(e.toString());
)
)
);
} catch {
yield put(
nodeSetComments(
comments.map(comment =>
comment.id === id ? { ...comment, deleted_at: current.deleted_at } : comment
)
)
);
} }
} }

View file

@ -71,9 +71,9 @@ export type ApiLockNodeResult = {
}; };
export type ApiLockCommentRequest = { export type ApiLockCommentRequest = {
id: IComment['id']; commentID: IComment['id'];
current: INode['id']; nodeID: INode['id'];
is_locked: boolean; isLocked: boolean;
}; };
export type ApiLockcommentResult = { export type ApiLockcommentResult = {
deleted_at: string; deleted_at: string;

View file

@ -22,7 +22,7 @@ export const useNodeComments = (id: INode['id']) => {
[id] [id]
); );
const { data, error, isValidating, size, setSize } = useSWRInfinite(getKey, fetcher); const { data, error, isValidating, size, setSize, mutate } = useSWRInfinite(getKey, fetcher);
const comments = useMemo<IComment[]>( const comments = useMemo<IComment[]>(
() => (data || []).reduce((acc, { comments }) => [...acc, ...comments], [] as IComment[]), () => (data || []).reduce((acc, { comments }) => [...acc, ...comments], [] as IComment[]),
@ -40,14 +40,37 @@ export const useNodeComments = (id: INode['id']) => {
const isLoading = !data && !isValidating; const isLoading = !data && !isValidating;
const onDelete = useCallback( const onDelete = useCallback(
(id: IComment['id'], locked: boolean) => dispatch(nodeLockComment(id, locked)), (commentID: IComment['id'], locked: boolean) => {
[dispatch] const callback = (e?: string) => {
if (!e && data) {
console.log({ data, commentID });
mutate(
data.map(page => ({
...page,
comments: page.comments.map(comment =>
comment.id === commentID
? {
...comment,
deleted_at: locked ? new Date().toISOString() : undefined,
}
: comment
),
})),
false
);
}
};
dispatch(nodeLockComment(id, commentID, locked, callback));
},
[id, mutate, data]
); );
const onLoadMoreComments = useCallback(() => setSize(size + 1), [size, setSize]); const onLoadMoreComments = useCallback(() => setSize(size + 1), [size, setSize]);
const onShowPhotoswipe = useCallback( const onShowPhotoswipe = useCallback(
(images: IFile[], index: number) => dispatch(modalShowPhotoswipe(images, index)), (images: IFile[], index: number) => dispatch(modalShowPhotoswipe(images, index)),
[dispatch] []
); );
return { comments, count, error, isLoading, onDelete, onLoadMoreComments, onShowPhotoswipe }; return { comments, count, error, isLoading, onDelete, onLoadMoreComments, onShowPhotoswipe };