From 5102c738b3b2d1e0156496b2572b6a855bc52077 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 3 Mar 2021 11:10:28 +0700 Subject: [PATCH] node: refactored sagas --- src/constants/api.ts | 4 +- src/redux/node/actions.ts | 5 - src/redux/node/api.ts | 169 ++++++--------- src/redux/node/constants.ts | 1 - src/redux/node/sagas.ts | 409 ++++++++++++++++++------------------ src/redux/node/types.ts | 54 ++++- 6 files changed, 318 insertions(+), 324 deletions(-) diff --git a/src/constants/api.ts b/src/constants/api.ts index 8dc1cbe6..6f57d689 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -31,9 +31,9 @@ export const API = { RELATED: (id: INode['id']) => `/node/${id}/related`, UPDATE_TAGS: (id: INode['id']) => `/node/${id}/tags`, POST_LIKE: (id: INode['id']) => `/node/${id}/like`, - POST_STAR: (id: INode['id']) => `/node/${id}/heroic`, + POST_HEROIC: (id: INode['id']) => `/node/${id}/heroic`, POST_LOCK: (id: INode['id']) => `/node/${id}/lock`, - POST_LOCK_COMMENT: (id: INode['id'], comment_id: IComment['id']) => + LOCK_COMMENT: (id: INode['id'], comment_id: IComment['id']) => `/node/${id}/comment/${comment_id}/lock`, SET_CELL_VIEW: (id: INode['id']) => `/node/${id}/cell-view`, }, diff --git a/src/redux/node/actions.ts b/src/redux/node/actions.ts index 776cb852..d2f95963 100644 --- a/src/redux/node/actions.ts +++ b/src/redux/node/actions.ts @@ -55,11 +55,6 @@ export const nodePostLocalComment = ( type: NODE_ACTIONS.POST_COMMENT, }); -export const nodeCancelCommentEdit = (id: number) => ({ - id, - type: NODE_ACTIONS.CANCEL_COMMENT_EDIT, -}); - export const nodeSetSendingComment = (is_sending_comment: boolean) => ({ is_sending_comment, type: NODE_ACTIONS.SET_SENDING_COMMENT, diff --git a/src/redux/node/api.ts b/src/redux/node/api.ts index 2748abf7..e33d49b4 100644 --- a/src/redux/node/api.ts +++ b/src/redux/node/api.ts @@ -1,22 +1,43 @@ -import { api, configWithToken, resultMiddleware, errorMiddleware, cleanResult } from '~/utils/api'; -import { INode, IResultWithStatus, IComment } from '../types'; +import { api, cleanResult, configWithToken, errorMiddleware, resultMiddleware } from '~/utils/api'; +import { IComment, INode, IResultWithStatus } from '../types'; import { API } from '~/constants/api'; -import { nodeUpdateTags, nodeLike, nodeStar, nodeLock, nodeLockComment } from './actions'; -import { INodeState } from './reducer'; import { COMMENTS_DISPLAY } from './constants'; -import { GetNodeDiffRequest, GetNodeDiffResult } from '~/redux/node/types'; +import { + ApiGetNodeRelatedRequest, + ApiGetNodeRelatedResult, + ApiGetNodeRequest, + ApiGetNodeResult, + ApiLockCommentRequest, + ApiLockcommentResult, + ApiLockNodeRequest, + ApiLockNodeResult, + ApiPostCommentRequest, + ApiPostCommentResult, + ApiPostNodeHeroicRequest, + ApiPostNodeHeroicResponse, + ApiPostNodeLikeRequest, + ApiPostNodeLikeResult, + ApiPostNodeTagsRequest, + ApiPostNodeTagsResult, + GetNodeDiffRequest, + GetNodeDiffResult, +} from '~/redux/node/types'; -export const postNode = ({ - access, - node, -}: { - access: string; +export type ApiPostNodeRequest = { node: INode }; +export type ApiPostNodeResult = { node: INode; -}): Promise> => - api - .post(API.NODE.SAVE, node, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); + errors: Record; +}; + +export type ApiGetNodeCommentsRequest = { + id: number; + take?: number; + skip?: number; +}; +export type ApiGetNodeCommentsResponse = { comments: IComment[]; comment_count: number }; + +export const apiPostNode = ({ node }: ApiPostNodeRequest) => + api.post(API.NODE.SAVE, node).then(cleanResult); export const getNodes = ({ from, @@ -53,113 +74,41 @@ export const getNodeDiff = ({ }) .then(cleanResult); -export const getNode = ({ - id, - access, -}: { - id: string | number; - access: string; -}): Promise> => - api.get(API.NODE.GET_NODE(id), configWithToken(access)).then(cleanResult); +export const apiGetNode = ({ id }: ApiGetNodeRequest) => + api.get(API.NODE.GET_NODE(id)).then(cleanResult); -export const postNodeComment = ({ - id, - data, - access, -}: { - access: string; - id: number; - data: IComment; -}): Promise> => - api - .post(API.NODE.COMMENT(id), data, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); +export const apiPostComment = ({ id, data }: ApiPostCommentRequest) => + api.post(API.NODE.COMMENT(id), data).then(cleanResult); -export const getNodeComments = ({ +export const apiGetNodeComments = ({ id, - access, take = COMMENTS_DISPLAY, skip = 0, -}: { - id: number; - access: string; - take?: number; - skip?: number; -}): Promise> => +}: ApiGetNodeCommentsRequest) => api - .get(API.NODE.COMMENT(id), configWithToken(access, { params: { take, skip } })) - .then(resultMiddleware) - .catch(errorMiddleware); + .get(API.NODE.COMMENT(id), { params: { take, skip } }) + .then(cleanResult); -export const getNodeRelated = ({ - id, - access, -}: { - id: number; - access: string; -}): Promise> => - api - .get(API.NODE.RELATED(id), configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); +export const apiGetNodeRelated = ({ id }: ApiGetNodeRelatedRequest) => + api.get(API.NODE.RELATED(id)).then(cleanResult); -export const updateNodeTags = ({ - id, - tags, - access, -}: ReturnType & { access: string }): Promise> => +export const apiPostNodeTags = ({ id, tags }: ApiPostNodeTagsRequest) => api - .post(API.NODE.UPDATE_TAGS(id), { tags }, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); + .post(API.NODE.UPDATE_TAGS(id), { tags }) + .then(cleanResult); -export const postNodeLike = ({ - id, - access, -}: ReturnType & { access: string }): Promise> => - api - .post(API.NODE.POST_LIKE(id), {}, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); +export const apiPostNodeLike = ({ id }: ApiPostNodeLikeRequest) => + api.post(API.NODE.POST_LIKE(id)).then(cleanResult); -export const postNodeStar = ({ - id, - access, -}: ReturnType & { access: string }): Promise> => - api - .post(API.NODE.POST_STAR(id), {}, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); +export const apiPostNodeHeroic = ({ id }: ApiPostNodeHeroicRequest) => + api.post(API.NODE.POST_HEROIC(id)).then(cleanResult); -export const postNodeLock = ({ - id, - is_locked, - access, -}: ReturnType & { access: string }): Promise> => +export const apiLockNode = ({ id, is_locked }: ApiLockNodeRequest) => api - .post(API.NODE.POST_LOCK(id), { is_locked }, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); + .post(API.NODE.POST_LOCK(id), { is_locked }) + .then(cleanResult); -export const postNodeLockComment = ({ - id, - is_locked, - current, - access, -}: ReturnType & { - access: string; - current: INode['id']; -}): Promise> => +export const apiLockComment = ({ id, is_locked, current }: ApiLockCommentRequest) => api - .post(API.NODE.POST_LOCK_COMMENT(current, id), { is_locked }, configWithToken(access)) - .then(resultMiddleware) - .catch(errorMiddleware); + .post(API.NODE.LOCK_COMMENT(current, id), { is_locked }) + .then(cleanResult); diff --git a/src/redux/node/constants.ts b/src/redux/node/constants.ts index 81ef9a79..acd3f348 100644 --- a/src/redux/node/constants.ts +++ b/src/redux/node/constants.ts @@ -29,7 +29,6 @@ export const NODE_ACTIONS = { LOCK: `${prefix}LOCK`, LOCK_COMMENT: `${prefix}LOCK_COMMENT`, EDIT_COMMENT: `${prefix}EDIT_COMMENT`, - CANCEL_COMMENT_EDIT: `${prefix}CANCEL_COMMENT_EDIT`, CREATE: `${prefix}CREATE`, LOAD_MORE_COMMENTS: `${prefix}LOAD_MORE_COMMENTS`, diff --git a/src/redux/node/sagas.ts b/src/redux/node/sagas.ts index 53c85f8e..2e95ff8b 100644 --- a/src/redux/node/sagas.ts +++ b/src/redux/node/sagas.ts @@ -1,6 +1,5 @@ -import { all, call, delay, put, select, takeLatest, takeLeading } from 'redux-saga/effects'; +import { all, call, put, select, takeLatest, takeLeading } from 'redux-saga/effects'; import { push } from 'connected-react-router'; -import { omit } from 'ramda'; import { COMMENTS_DISPLAY, @@ -10,10 +9,8 @@ import { NODE_EDITOR_DATA, } from './constants'; import { - nodeCancelCommentEdit, nodeCreate, nodeEdit, - nodeEditComment, nodeGotoNode, nodeLike, nodeLoadNode, @@ -34,35 +31,33 @@ import { nodeUpdateTags, } from './actions'; import { - getNode, - getNodeComments, - getNodeRelated, - postNode, - postNodeComment, - postNodeLike, - postNodeLock, - postNodeLockComment, - postNodeStar, - updateNodeTags, + apiGetNode, + apiGetNodeComments, + apiGetNodeRelated, + apiLockComment, + apiLockNode, + apiPostComment, + apiPostNode, + apiPostNodeHeroic, + apiPostNodeLike, + apiPostNodeTags, } from './api'; -import { wrap } from '../auth/sagas'; import { flowSetNodes, flowSetUpdated } from '../flow/actions'; import { ERRORS } from '~/constants/errors'; import { modalSetShown, modalShowDialog } from '../modal/actions'; import { selectFlow, selectFlowNodes } from '../flow/selectors'; import { URLS } from '~/constants/urls'; import { selectNode } from './selectors'; -import { INode, IResultWithStatus, Unwrap } from '../types'; +import { Unwrap } from '../types'; import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs'; import { DIALOGS } from '~/redux/modal/constants'; -import { INodeState } from './reducer'; -import { IFlowState } from '../flow/reducer'; export function* updateNodeEverywhere(node) { const { current: { id }, - }: INodeState = yield select(selectNode); - const flow_nodes: IFlowState['nodes'] = yield select(selectFlowNodes); + }: ReturnType = yield select(selectNode); + + const flow_nodes: ReturnType = yield select(selectFlowNodes); if (id === node.id) { yield put(nodeSetCurrent(node)); @@ -78,35 +73,33 @@ export function* updateNodeEverywhere(node) { } function* onNodeSave({ node }: ReturnType) { - yield put(nodeSetSaveErrors({})); + try { + yield put(nodeSetSaveErrors({})); - const { - error, - data: { errors, node: result }, - } = yield call(wrap, postNode, { node }); + const { errors, node: result }: Unwrap = yield call(apiPostNode, { node }); - if (errors && Object.values(errors).length > 0) { - return yield put(nodeSetSaveErrors(errors)); + if (errors && Object.values(errors).length > 0) { + yield put(nodeSetSaveErrors(errors)); + return; + } + + const nodes: ReturnType = yield select(selectFlowNodes); + const updated_flow_nodes = node.id + ? nodes.map(item => (item.id === result.id ? result : item)) + : [result, ...nodes]; + + yield put(flowSetNodes(updated_flow_nodes)); + + const { current } = yield select(selectNode); + + if (node.id && current.id === result.id) { + yield put(nodeSetCurrent(result)); + } + + return yield put(modalSetShown(false)); + } catch (error) { + yield put(nodeSetSaveErrors({ error: error || ERRORS.CANT_SAVE_NODE })); } - - if (error || !result || !result.id) { - return yield put(nodeSetSaveErrors({ error: error || ERRORS.CANT_SAVE_NODE })); - } - - const nodes = yield select(selectFlowNodes); - const updated_flow_nodes = node.id - ? nodes.map(item => (item.id === result.id ? result : item)) - : [result, ...nodes]; - - yield put(flowSetNodes(updated_flow_nodes)); - - const { current } = yield select(selectNode); - - if (node.id && current.id === result.id) { - yield put(nodeSetCurrent(result)); - } - - return yield put(modalSetShown(false)); } function* onNodeGoto({ id, node_type }: ReturnType) { @@ -114,134 +107,120 @@ function* onNodeGoto({ id, node_type }: ReturnType) { yield put(nodeLoadNode(id)); yield put(nodeSetCommentData(0, { ...EMPTY_COMMENT })); - yield put(nodeSetRelated(null)); + yield put(nodeSetRelated({ albums: {}, similar: [] })); } function* onNodeLoadMoreComments() { - const { - current: { id }, - comments, - }: ReturnType = yield select(selectNode); + try { + const { + current: { id }, + comments, + }: ReturnType = yield select(selectNode); - const { data, error }: Unwrap = yield call(wrap, getNodeComments, { - id, - take: COMMENTS_DISPLAY, - skip: comments.length, - }); + if (!id) { + return; + } - const current: ReturnType = yield select(selectNode); + const data: Unwrap = yield call(apiGetNodeComments, { + id, + take: COMMENTS_DISPLAY, + skip: comments.length, + }); - if (!data || error || current.current.id != id) { - return; - } + const current: ReturnType = yield select(selectNode); - yield put( - nodeSet({ - comments: [...comments, ...data.comments], - comment_count: data.comment_count, - }) - ); + if (!data || current.current.id != id) { + return; + } + + yield put( + nodeSet({ + comments: [...comments, ...data.comments], + comment_count: data.comment_count, + }) + ); + } catch (error) {} } -function* onNodeLoad({ id, order = 'ASC' }: ReturnType) { - yield put(nodeSetLoading(true)); - yield put(nodeSetLoadingComments(true)); +function* onNodeLoad({ id }: ReturnType) { + // Get node body + try { + yield put(nodeSetLoading(true)); + yield put(nodeSetLoadingComments(true)); - const { - data: { node, error }, - } = yield call(wrap, getNode, { id }); + const { node }: Unwrap = yield call(apiGetNode, { id }); - if (error || !node || !node.id) { + yield put(nodeSetCurrent(node)); + yield put(nodeSetLoading(false)); + } catch (error) { yield put(push(URLS.ERRORS.NOT_FOUND)); yield put(nodeSetLoading(false)); - return; } - yield put(nodeSetCurrent(node)); - yield put(nodeSetLoading(false)); + // Comments and related + try { + const [{ comments, comment_count }, { related }]: [ + Unwrap, + Unwrap + ] = yield all([ + call(apiGetNodeComments, { id, take: COMMENTS_DISPLAY, skip: 0 }), + call(apiGetNodeRelated, { id }), + ]); - const { - comments: { - data: { comments, comment_count }, - }, - related: { - data: { related }, - }, - } = yield all({ - comments: call(wrap, getNodeComments, { id, take: COMMENTS_DISPLAY, skip: 0 }), - related: call(wrap, getNodeRelated, { id }), - }); - - yield put( - nodeSet({ - comments, - comment_count, - related, - is_loading_comments: false, - comment_data: { 0: { ...EMPTY_COMMENT } }, - }) - ); + yield put( + nodeSet({ + comments, + comment_count, + related, + is_loading_comments: false, + }) + ); + } catch {} + // Remove current node from recently updated const { updated } = yield select(selectFlow); if (updated.some(item => item.id === id)) { yield put(flowSetUpdated(updated.filter(item => item.id !== id))); } - - return; } function* onPostComment({ nodeId, comment, callback }: ReturnType) { - const { data, error }: Unwrap = yield call(wrap, postNodeComment, { - data: comment, - id: nodeId, - }); + try { + const data: Unwrap = yield call(apiPostComment, { + data: comment, + id: nodeId, + }); - if (error || !data.comment) { + const { current }: ReturnType = yield select(selectNode); + + if (current?.id === nodeId) { + const { comments }: ReturnType = yield select(selectNode); + + if (!comment.id) { + yield put(nodeSetComments([data.comment, ...comments])); + } else { + yield put( + nodeSet({ + comments: comments.map(item => (item.id === comment.id ? data.comment : item)), + }) + ); + } + + callback(); + } + } catch (error) { return callback(error); } - - const { current }: ReturnType = yield select(selectNode); - - if (current?.id === nodeId) { - const { comments } = yield select(selectNode); - - if (!comment.id) { - yield put(nodeSetComments([data.comment, ...comments])); - } else { - yield put( - nodeSet({ - comments: comments.map(item => (item.id === comment.id ? data.comment : item)), - }) - ); - } - - callback(); - } -} - -function* onCancelCommentEdit({ id }: ReturnType) { - const { comment_data } = yield select(selectNode); - - yield put( - nodeSet({ - comment_data: omit([id.toString()], comment_data), - }) - ); } function* onUpdateTags({ id, tags }: ReturnType) { - yield delay(100); - - const { - data: { node }, - }: IResultWithStatus<{ node: INode }> = yield call(wrap, updateNodeTags, { id, tags }); - - const { current } = yield select(selectNode); - - if (!node || !node.id || node.id !== current.id) return; - - yield put(nodeSetTags(node.tags)); + try { + const { node }: Unwrap = yield call(apiPostNodeTags, { id, tags }); + const { current }: ReturnType = yield select(selectNode); + if (!node || !node.id || node.id !== current.id) return; + yield put(nodeSetTags(node.tags)); + } catch {} } function* onCreateSaga({ node_type: type }: ReturnType) { @@ -252,96 +231,118 @@ function* onCreateSaga({ node_type: type }: ReturnType) { } function* onEditSaga({ id }: ReturnType) { - yield put(modalShowDialog(DIALOGS.LOADING)); + try { + if (!id) { + return; + } - const { - data: { node }, - error, - } = yield call(wrap, getNode, { id }); + yield put(modalShowDialog(DIALOGS.LOADING)); - if (error || !node || !node.type || !NODE_EDITOR_DIALOGS[node.type]) - return yield put(modalSetShown(false)); + const { node }: Unwrap = yield call(apiGetNode, { id }); - yield put(nodeSetEditor(node)); - yield put(modalShowDialog(NODE_EDITOR_DIALOGS[node.type])); + if (!NODE_EDITOR_DIALOGS[node?.type]) { + throw new Error('Unknown node type'); + } - return true; + yield put(nodeSetEditor(node)); + yield put(modalShowDialog(NODE_EDITOR_DIALOGS[node.type])); + } catch (error) { + yield put(modalSetShown(false)); + } } function* onLikeSaga({ id }: ReturnType) { - const { - current, - current: { is_liked, like_count }, - } = yield select(selectNode); + try { + const { current }: ReturnType = yield select(selectNode); - yield call(updateNodeEverywhere, { - ...current, - is_liked: !is_liked, - like_count: is_liked ? Math.max(like_count - 1, 0) : like_count + 1, - }); + const count = current.like_count || 0; - const { data, error } = yield call(wrap, postNodeLike, { id }); + yield call(updateNodeEverywhere, { + ...current, + is_liked: !current.is_liked, + like_count: current.is_liked ? Math.max(count - 1, 0) : count + 1, + }); - if (!error || data.is_liked === !is_liked) return; // ok and matches + const data: Unwrap = yield call(apiPostNodeLike, { id }); - yield call(updateNodeEverywhere, { ...current, is_liked, like_count }); + yield call(updateNodeEverywhere, { + ...current, + is_liked: data.is_liked, + }); + } catch {} } function* onStarSaga({ id }: ReturnType) { - const { - current, - current: { is_heroic }, - } = yield select(selectNode); + try { + const { + current, + current: { is_heroic }, + } = yield select(selectNode); - yield call(updateNodeEverywhere, { ...current, is_heroic: !is_heroic }); + yield call(updateNodeEverywhere, { ...current, is_heroic: !is_heroic }); - const { data, error } = yield call(wrap, postNodeStar, { id }); + const data: Unwrap = yield call(apiPostNodeHeroic, { id }); - if (!error || data.is_heroic === !is_heroic) return; // ok and matches - - yield call(updateNodeEverywhere, { ...current, is_heroic }); + yield call(updateNodeEverywhere, { ...current, is_heroic: data.is_heroic }); + } catch {} } function* onLockSaga({ id, is_locked }: ReturnType) { - const { - current, - current: { deleted_at }, - } = yield select(selectNode); + const { current }: ReturnType = yield select(selectNode); - yield call(updateNodeEverywhere, { - ...current, - deleted_at: is_locked ? new Date().toISOString() : null, - }); + try { + yield call(updateNodeEverywhere, { + ...current, + deleted_at: is_locked ? new Date().toISOString() : null, + }); - const { error } = yield call(wrap, postNodeLock, { id, is_locked }); + const data: Unwrap = yield call(apiLockNode, { id, is_locked }); - if (error) return yield call(updateNodeEverywhere, { ...current, deleted_at }); + yield call(updateNodeEverywhere, { + ...current, + deleted_at: data.deleted_at || undefined, + }); + } catch { + yield call(updateNodeEverywhere, { ...current, deleted_at: current.deleted_at }); + } } function* onLockCommentSaga({ id, is_locked }: ReturnType) { - const { current, comments } = yield select(selectNode); + const { current, comments }: ReturnType = yield select(selectNode); - yield put( - nodeSetComments( - comments.map(comment => - comment.id === id - ? { ...comment, deleted_at: is_locked ? new Date().toISOString() : null } - : comment + try { + yield put( + nodeSetComments( + comments.map(comment => + comment.id === id + ? { ...comment, deleted_at: is_locked ? new Date().toISOString() : undefined } + : comment + ) ) - ) - ); + ); - yield call(wrap, postNodeLockComment, { current: current.id, id, is_locked }); -} + const data: Unwrap = yield call(apiLockComment, { + current: current.id, + id, + is_locked, + }); -function* onEditCommentSaga({ id }: ReturnType) { - const { comments } = yield select(selectNode); - - const comment = comments.find(item => item.id === id); - - if (!comment) return; - - yield put(nodeSetCommentData(id, { ...EMPTY_COMMENT, ...comment })); + yield put( + nodeSetComments( + comments.map(comment => + comment.id === id ? { ...comment, deleted_at: data.deleted_at || undefined } : comment + ) + ) + ); + } catch { + yield put( + nodeSetComments( + comments.map(comment => + comment.id === id ? { ...comment, deleted_at: current.deleted_at } : comment + ) + ) + ); + } } export default function* nodeSaga() { @@ -349,7 +350,6 @@ export default function* nodeSaga() { yield takeLatest(NODE_ACTIONS.GOTO_NODE, onNodeGoto); yield takeLatest(NODE_ACTIONS.LOAD_NODE, onNodeLoad); yield takeLatest(NODE_ACTIONS.POST_COMMENT, onPostComment); - yield takeLatest(NODE_ACTIONS.CANCEL_COMMENT_EDIT, onCancelCommentEdit); yield takeLatest(NODE_ACTIONS.UPDATE_TAGS, onUpdateTags); yield takeLatest(NODE_ACTIONS.CREATE, onCreateSaga); yield takeLatest(NODE_ACTIONS.EDIT, onEditSaga); @@ -357,6 +357,5 @@ export default function* nodeSaga() { yield takeLatest(NODE_ACTIONS.STAR, onStarSaga); yield takeLatest(NODE_ACTIONS.LOCK, onLockSaga); yield takeLatest(NODE_ACTIONS.LOCK_COMMENT, onLockCommentSaga); - yield takeLatest(NODE_ACTIONS.EDIT_COMMENT, onEditCommentSaga); yield takeLeading(NODE_ACTIONS.LOAD_MORE_COMMENTS, onNodeLoadMoreComments); } diff --git a/src/redux/node/types.ts b/src/redux/node/types.ts index 25af91fc..d7973326 100644 --- a/src/redux/node/types.ts +++ b/src/redux/node/types.ts @@ -1,4 +1,5 @@ -import { INode } from '~/redux/types'; +import { IComment, INode } from '~/redux/types'; +import { INodeState } from '~/redux/node/reducer'; export interface IEditorComponentProps { data: INode; @@ -31,3 +32,54 @@ export type PostCellViewRequest = { flow: INode['flow']; }; export type PostCellViewResult = unknown; // TODO: update it with actual type + +export type ApiGetNodeRequest = { + id: string | number; +}; +export type ApiGetNodeResult = { node: INode }; + +export type ApiGetNodeRelatedRequest = { + id: INode['id']; +}; +export type ApiGetNodeRelatedResult = { + related: INodeState['related']; +}; + +export type ApiPostCommentRequest = { + id: INode['id']; + data: IComment; +}; +export type ApiPostCommentResult = { + comment: IComment; +}; + +export type ApiPostNodeTagsRequest = { + id: INode['id']; + tags: string[]; +}; +export type ApiPostNodeTagsResult = { + node: INode; +}; + +export type ApiPostNodeLikeRequest = { id: INode['id'] }; +export type ApiPostNodeLikeResult = { is_liked: boolean }; + +export type ApiPostNodeHeroicRequest = { id: INode['id'] }; +export type ApiPostNodeHeroicResponse = { is_heroic: boolean }; + +export type ApiLockNodeRequest = { + id: INode['id']; + is_locked: boolean; +}; +export type ApiLockNodeResult = { + deleted_at: string; +}; + +export type ApiLockCommentRequest = { + id: IComment['id']; + current: INode['id']; + is_locked: boolean; +}; +export type ApiLockcommentResult = { + deleted_at: string; +};