mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
flow: refactored sagas
This commit is contained in:
parent
90ac1fe611
commit
31b03f9eae
5 changed files with 228 additions and 214 deletions
|
@ -1,8 +1,8 @@
|
||||||
import { api, configWithToken, resultMiddleware, errorMiddleware } from '~/utils/api';
|
import { api, cleanResult, configWithToken } from '~/utils/api';
|
||||||
import { INode, IResultWithStatus } from '../types';
|
import { INode, IResultWithStatus } from '../types';
|
||||||
import { API } from '~/constants/api';
|
import { API } from '~/constants/api';
|
||||||
import { flowSetCellView } from '~/redux/flow/actions';
|
import { PostCellViewRequest, PostCellViewResult } from '~/redux/node/types';
|
||||||
import { IFlowState } from './reducer';
|
import { GetSearchResultsRequest, GetSearchResultsResult } from '~/redux/flow/types';
|
||||||
|
|
||||||
export const postNode = ({
|
export const postNode = ({
|
||||||
access,
|
access,
|
||||||
|
@ -11,32 +11,14 @@ export const postNode = ({
|
||||||
access: string;
|
access: string;
|
||||||
node: INode;
|
node: INode;
|
||||||
}): Promise<IResultWithStatus<INode>> =>
|
}): Promise<IResultWithStatus<INode>> =>
|
||||||
api
|
api.post(API.NODE.SAVE, { node }, configWithToken(access)).then(cleanResult);
|
||||||
.post(API.NODE.SAVE, { node }, configWithToken(access))
|
|
||||||
.then(resultMiddleware)
|
|
||||||
.catch(errorMiddleware);
|
|
||||||
|
|
||||||
export const postCellView = ({
|
export const postCellView = ({ id, flow }: PostCellViewRequest) =>
|
||||||
id,
|
|
||||||
flow,
|
|
||||||
access,
|
|
||||||
}: ReturnType<typeof flowSetCellView> & { access: string }): Promise<IResultWithStatus<{
|
|
||||||
is_liked: INode['is_liked'];
|
|
||||||
}>> =>
|
|
||||||
api
|
api
|
||||||
.post(API.NODE.SET_CELL_VIEW(id), { flow }, configWithToken(access))
|
.post<PostCellViewResult>(API.NODE.SET_CELL_VIEW(id), { flow })
|
||||||
.then(resultMiddleware)
|
.then(cleanResult);
|
||||||
.catch(errorMiddleware);
|
|
||||||
|
|
||||||
export const getSearchResults = ({
|
export const getSearchResults = ({ text, skip = 0 }: GetSearchResultsRequest) =>
|
||||||
access,
|
|
||||||
text,
|
|
||||||
skip = 0,
|
|
||||||
}: IFlowState['search'] & {
|
|
||||||
access: string;
|
|
||||||
skip: number;
|
|
||||||
}): Promise<IResultWithStatus<{ nodes: INode[]; total: number }>> =>
|
|
||||||
api
|
api
|
||||||
.get(API.SEARCH.NODES, configWithToken(access, { params: { text, skip } }))
|
.get<GetSearchResultsResult>(API.SEARCH.NODES, { params: { text, skip } })
|
||||||
.then(resultMiddleware)
|
.then(cleanResult);
|
||||||
.catch(errorMiddleware);
|
|
||||||
|
|
|
@ -1,36 +1,41 @@
|
||||||
import { takeLatest, call, put, select, takeLeading, delay, race, take } from 'redux-saga/effects';
|
import { call, delay, put, race, select, take, takeLatest, takeLeading } from 'redux-saga/effects';
|
||||||
import { REHYDRATE } from 'redux-persist';
|
import { REHYDRATE } from 'redux-persist';
|
||||||
import { FLOW_ACTIONS } from './constants';
|
import { FLOW_ACTIONS } from './constants';
|
||||||
import { getNodeDiff } from '../node/api';
|
import { getNodeDiff } from '../node/api';
|
||||||
import {
|
import {
|
||||||
flowSetNodes,
|
|
||||||
flowSetCellView,
|
|
||||||
flowSetHeroes,
|
|
||||||
flowSetRecent,
|
|
||||||
flowSetUpdated,
|
|
||||||
flowSetFlow,
|
|
||||||
flowChangeSearch,
|
flowChangeSearch,
|
||||||
|
flowSetCellView,
|
||||||
|
flowSetFlow,
|
||||||
|
flowSetHeroes,
|
||||||
|
flowSetNodes,
|
||||||
|
flowSetRecent,
|
||||||
flowSetSearch,
|
flowSetSearch,
|
||||||
|
flowSetUpdated,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { IResultWithStatus, INode, Unwrap } from '../types';
|
import { Unwrap } from '../types';
|
||||||
import { selectFlowNodes, selectFlow } from './selectors';
|
import { selectFlow, selectFlowNodes } from './selectors';
|
||||||
import { wrap } from '../auth/sagas';
|
import { getSearchResults, postCellView } from './api';
|
||||||
import { postCellView, getSearchResults } from './api';
|
|
||||||
import { IFlowState } from './reducer';
|
|
||||||
import { uniq } from 'ramda';
|
import { uniq } from 'ramda';
|
||||||
|
|
||||||
function hideLoader() {
|
function hideLoader() {
|
||||||
document.getElementById('main_loader').style.display = 'none';
|
const loader = document.getElementById('main_loader');
|
||||||
|
|
||||||
|
if (!loader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
function* onGetFlow() {
|
function* onGetFlow() {
|
||||||
|
try {
|
||||||
const {
|
const {
|
||||||
flow: { _persist },
|
flow: { _persist },
|
||||||
} = yield select();
|
} = yield select();
|
||||||
|
|
||||||
if (!_persist.rehydrated) return;
|
if (!_persist.rehydrated) return;
|
||||||
|
|
||||||
const stored: IFlowState['nodes'] = yield select(selectFlowNodes);
|
const stored: ReturnType<typeof selectFlowNodes> = yield select(selectFlowNodes);
|
||||||
|
|
||||||
if (stored.length) {
|
if (stored.length) {
|
||||||
hideLoader();
|
hideLoader();
|
||||||
|
@ -39,15 +44,12 @@ function* onGetFlow() {
|
||||||
yield put(flowSetFlow({ is_loading: true }));
|
yield put(flowSetFlow({ is_loading: true }));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: { before = [], after = [], heroes = [], recent = [], updated = [], valid = null },
|
before = [],
|
||||||
}: IResultWithStatus<{
|
after = [],
|
||||||
before: IFlowState['nodes'];
|
heroes = [],
|
||||||
after: IFlowState['nodes'];
|
recent = [],
|
||||||
heroes: IFlowState['heroes'];
|
updated = [],
|
||||||
recent: IFlowState['recent'];
|
}: Unwrap<typeof getNodeDiff> = yield call(getNodeDiff, {
|
||||||
updated: IFlowState['updated'];
|
|
||||||
valid: INode['id'][];
|
|
||||||
}> = yield call(wrap, getNodeDiff, {
|
|
||||||
start: new Date().toISOString(),
|
start: new Date().toISOString(),
|
||||||
end: new Date().toISOString(),
|
end: new Date().toISOString(),
|
||||||
with_heroes: true,
|
with_heroes: true,
|
||||||
|
@ -65,25 +67,30 @@ function* onGetFlow() {
|
||||||
if (updated.length) yield put(flowSetUpdated(updated));
|
if (updated.length) yield put(flowSetUpdated(updated));
|
||||||
|
|
||||||
if (!stored.length) hideLoader();
|
if (!stored.length) hideLoader();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* onSetCellView({ id, flow }: ReturnType<typeof flowSetCellView>) {
|
function* onSetCellView({ id, flow }: ReturnType<typeof flowSetCellView>) {
|
||||||
const nodes = yield select(selectFlowNodes);
|
try {
|
||||||
|
const nodes: ReturnType<typeof selectFlowNodes> = yield select(selectFlowNodes);
|
||||||
yield put(flowSetNodes(nodes.map(node => (node.id === id ? { ...node, flow } : node))));
|
yield put(flowSetNodes(nodes.map(node => (node.id === id ? { ...node, flow } : node))));
|
||||||
|
yield call(postCellView, { id, flow });
|
||||||
const { data, error } = yield call(wrap, postCellView, { id, flow });
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
// TODO: error handling
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* getMore() {
|
function* getMore() {
|
||||||
|
try {
|
||||||
yield put(flowSetFlow({ is_loading: true }));
|
yield put(flowSetFlow({ is_loading: true }));
|
||||||
const nodes: IFlowState['nodes'] = yield select(selectFlowNodes);
|
const nodes: ReturnType<typeof selectFlowNodes> = yield select(selectFlowNodes);
|
||||||
|
|
||||||
const start = nodes && nodes[0] && nodes[0].created_at;
|
const start = nodes && nodes[0] && nodes[0].created_at;
|
||||||
const end = nodes && nodes[nodes.length - 1] && nodes[nodes.length - 1].created_at;
|
const end = nodes && nodes[nodes.length - 1] && nodes[nodes.length - 1].created_at;
|
||||||
|
|
||||||
const { error, data } = yield call(wrap, getNodeDiff, {
|
const data: Unwrap<typeof getNodeDiff> = yield call(getNodeDiff, {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
with_heroes: false,
|
with_heroes: false,
|
||||||
|
@ -92,8 +99,6 @@ function* getMore() {
|
||||||
with_valid: true,
|
with_valid: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error || !data) return;
|
|
||||||
|
|
||||||
const result = uniq([
|
const result = uniq([
|
||||||
...(data.before || []),
|
...(data.before || []),
|
||||||
...(data.valid ? nodes.filter(node => data.valid.includes(node.id)) : nodes),
|
...(data.valid ? nodes.filter(node => data.valid.includes(node.id)) : nodes),
|
||||||
|
@ -110,9 +115,11 @@ function* getMore() {
|
||||||
);
|
);
|
||||||
|
|
||||||
yield delay(1000);
|
yield delay(1000);
|
||||||
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* changeSearch({ search }: ReturnType<typeof flowChangeSearch>) {
|
function* changeSearch({ search }: ReturnType<typeof flowChangeSearch>) {
|
||||||
|
try {
|
||||||
yield put(
|
yield put(
|
||||||
flowSetSearch({
|
flowSetSearch({
|
||||||
...search,
|
...search,
|
||||||
|
@ -124,25 +131,25 @@ function* changeSearch({ search }: ReturnType<typeof flowChangeSearch>) {
|
||||||
|
|
||||||
yield delay(500);
|
yield delay(500);
|
||||||
|
|
||||||
const { data, error }: Unwrap<typeof getSearchResults> = yield call(wrap, getSearchResults, {
|
const data: Unwrap<typeof getSearchResults> = yield call(getSearchResults, {
|
||||||
...search,
|
text: search.text,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
|
||||||
yield put(flowSetSearch({ is_loading: false, results: [], total: 0 }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield put(
|
yield put(
|
||||||
flowSetSearch({
|
flowSetSearch({
|
||||||
is_loading: false,
|
|
||||||
results: data.nodes,
|
results: data.nodes,
|
||||||
total: data.total,
|
total: data.total,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
yield put(flowSetSearch({ results: [], total: 0 }));
|
||||||
|
} finally {
|
||||||
|
yield put(flowSetSearch({ is_loading: false }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* loadMoreSearch() {
|
function* loadMoreSearch() {
|
||||||
|
try {
|
||||||
yield put(
|
yield put(
|
||||||
flowSetSearch({
|
flowSetSearch({
|
||||||
is_loading_more: true,
|
is_loading_more: true,
|
||||||
|
@ -152,25 +159,31 @@ function* loadMoreSearch() {
|
||||||
const { search }: ReturnType<typeof selectFlow> = yield select(selectFlow);
|
const { search }: ReturnType<typeof selectFlow> = yield select(selectFlow);
|
||||||
|
|
||||||
const { result, delay }: { result: Unwrap<typeof getSearchResults>; delay: any } = yield race({
|
const { result, delay }: { result: Unwrap<typeof getSearchResults>; delay: any } = yield race({
|
||||||
result: call(wrap, getSearchResults, {
|
result: call(getSearchResults, {
|
||||||
...search,
|
...search,
|
||||||
skip: search.results.length,
|
skip: search.results.length,
|
||||||
}),
|
}),
|
||||||
delay: take(FLOW_ACTIONS.CHANGE_SEARCH),
|
delay: take(FLOW_ACTIONS.CHANGE_SEARCH),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (delay || result.error) {
|
if (delay) {
|
||||||
return put(flowSetSearch({ is_loading_more: false }));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(
|
yield put(
|
||||||
flowSetSearch({
|
flowSetSearch({
|
||||||
results: [...search.results, ...result.data.nodes],
|
results: [...search.results, ...result.nodes],
|
||||||
total: result.data.total,
|
total: result.total,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
yield put(
|
||||||
|
flowSetSearch({
|
||||||
is_loading_more: false,
|
is_loading_more: false,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function* nodeSaga() {
|
export default function* nodeSaga() {
|
||||||
yield takeLatest([FLOW_ACTIONS.GET_FLOW, REHYDRATE], onGetFlow);
|
yield takeLatest([FLOW_ACTIONS.GET_FLOW, REHYDRATE], onGetFlow);
|
||||||
|
|
10
src/redux/flow/types.ts
Normal file
10
src/redux/flow/types.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { INode } from '~/redux/types';
|
||||||
|
|
||||||
|
export type GetSearchResultsRequest = {
|
||||||
|
text: string;
|
||||||
|
skip?: number;
|
||||||
|
};
|
||||||
|
export type GetSearchResultsResult = {
|
||||||
|
nodes: INode[];
|
||||||
|
total: number;
|
||||||
|
};
|
|
@ -1,9 +1,10 @@
|
||||||
import { api, configWithToken, resultMiddleware, errorMiddleware } from '~/utils/api';
|
import { api, configWithToken, resultMiddleware, errorMiddleware, cleanResult } from '~/utils/api';
|
||||||
import { INode, IResultWithStatus, IComment } from '../types';
|
import { INode, IResultWithStatus, IComment } from '../types';
|
||||||
import { API } from '~/constants/api';
|
import { API } from '~/constants/api';
|
||||||
import { nodeUpdateTags, nodeLike, nodeStar, nodeLock, nodeLockComment } from './actions';
|
import { nodeUpdateTags, nodeLike, nodeStar, nodeLock, nodeLockComment } from './actions';
|
||||||
import { INodeState } from './reducer';
|
import { INodeState } from './reducer';
|
||||||
import { COMMENTS_DISPLAY } from './constants';
|
import { COMMENTS_DISPLAY } from './constants';
|
||||||
|
import { GetNodeDiffRequest, GetNodeDiffResult } from '~/redux/node/types';
|
||||||
|
|
||||||
export const postNode = ({
|
export const postNode = ({
|
||||||
access,
|
access,
|
||||||
|
@ -18,7 +19,7 @@ export const postNode = ({
|
||||||
.catch(errorMiddleware);
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const getNodes = ({
|
export const getNodes = ({
|
||||||
from = null,
|
from,
|
||||||
access,
|
access,
|
||||||
}: {
|
}: {
|
||||||
from?: string;
|
from?: string;
|
||||||
|
@ -30,28 +31,16 @@ export const getNodes = ({
|
||||||
.catch(errorMiddleware);
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const getNodeDiff = ({
|
export const getNodeDiff = ({
|
||||||
start = null,
|
start,
|
||||||
end = null,
|
end,
|
||||||
take,
|
take,
|
||||||
with_heroes,
|
with_heroes,
|
||||||
with_updated,
|
with_updated,
|
||||||
with_recent,
|
with_recent,
|
||||||
with_valid,
|
with_valid,
|
||||||
access,
|
}: GetNodeDiffRequest) =>
|
||||||
}: {
|
|
||||||
start?: string;
|
|
||||||
end?: string;
|
|
||||||
take?: number;
|
|
||||||
access: string;
|
|
||||||
with_heroes: boolean;
|
|
||||||
with_updated: boolean;
|
|
||||||
with_recent: boolean;
|
|
||||||
with_valid: boolean;
|
|
||||||
}): Promise<IResultWithStatus<{ nodes: INode[] }>> =>
|
|
||||||
api
|
api
|
||||||
.get(
|
.get<GetNodeDiffResult>(API.NODE.GET_DIFF, {
|
||||||
API.NODE.GET_DIFF,
|
|
||||||
configWithToken(access, {
|
|
||||||
params: {
|
params: {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
@ -62,9 +51,7 @@ export const getNodeDiff = ({
|
||||||
with_valid,
|
with_valid,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
.then(cleanResult);
|
||||||
.then(resultMiddleware)
|
|
||||||
.catch(errorMiddleware);
|
|
||||||
|
|
||||||
export const getNode = ({
|
export const getNode = ({
|
||||||
id,
|
id,
|
||||||
|
@ -73,10 +60,7 @@ export const getNode = ({
|
||||||
id: string | number;
|
id: string | number;
|
||||||
access: string;
|
access: string;
|
||||||
}): Promise<IResultWithStatus<{ nodes: INode[] }>> =>
|
}): Promise<IResultWithStatus<{ nodes: INode[] }>> =>
|
||||||
api
|
api.get(API.NODE.GET_NODE(id), configWithToken(access)).then(cleanResult);
|
||||||
.get(API.NODE.GET_NODE(id), configWithToken(access))
|
|
||||||
.then(resultMiddleware)
|
|
||||||
.catch(errorMiddleware);
|
|
||||||
|
|
||||||
export const postNodeComment = ({
|
export const postNodeComment = ({
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -6,3 +6,28 @@ export interface IEditorComponentProps {
|
||||||
temp: string[];
|
temp: string[];
|
||||||
setTemp: (val: string[]) => void;
|
setTemp: (val: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type GetNodeDiffRequest = {
|
||||||
|
start?: string;
|
||||||
|
end?: string;
|
||||||
|
take?: number;
|
||||||
|
with_heroes: boolean;
|
||||||
|
with_updated: boolean;
|
||||||
|
with_recent: boolean;
|
||||||
|
with_valid: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetNodeDiffResult = {
|
||||||
|
before?: INode[];
|
||||||
|
after?: INode[];
|
||||||
|
heroes?: INode[];
|
||||||
|
recent?: INode[];
|
||||||
|
updated?: INode[];
|
||||||
|
valid: INode['id'][];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PostCellViewRequest = {
|
||||||
|
id: INode['id'];
|
||||||
|
flow: INode['flow'];
|
||||||
|
};
|
||||||
|
export type PostCellViewResult = unknown; // TODO: update it with actual type
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue