zcash-grant-system/frontend/client/modules/create/sagas.ts

165 lines
4.8 KiB
TypeScript

import { SagaIterator } from 'redux-saga';
import { takeEvery, takeLatest, put, take, call, select } from 'redux-saga/effects';
import { replace } from 'connected-react-router';
import {
postProposalDraft,
getProposalDrafts,
putProposal,
deleteProposal,
getProposal,
} from 'api/api';
import { getDrafts, getDraftById, getFormState } from './selectors';
import {
createDraft,
fetchDrafts,
fetchAndCreateDrafts,
initializeForm,
deleteDraft,
} from './actions';
import types from './types';
export function* handleCreateDraft(action: ReturnType<typeof createDraft>): SagaIterator {
try {
const res: Yielded<typeof postProposalDraft> = yield call(
postProposalDraft,
action.payload.rfpId,
);
yield put({
type: types.CREATE_DRAFT_FULFILLED,
payload: res.data,
});
if (action.payload.redirect) {
yield put(replace(`/proposals/${res.data.proposalId}/edit`));
}
} catch (err) {
yield put({
type: types.CREATE_DRAFT_REJECTED,
payload: err.message || err.toString(),
error: true,
});
}
}
export function* handleFetchDrafts(): SagaIterator {
try {
const res: Yielded<typeof getProposalDrafts> = yield call(getProposalDrafts);
yield put({
type: types.FETCH_DRAFTS_FULFILLED,
payload: res.data,
});
} catch (err) {
yield put({
type: types.FETCH_DRAFTS_REJECTED,
payload: err.message || err.toString(),
error: true,
});
}
}
export function* handleSaveDraft(): SagaIterator {
try {
const draft: Yielded<typeof getFormState> = yield select(getFormState);
if (!draft) {
throw new Error('No form state to save draft');
}
yield call(putProposal, draft);
yield put({ type: types.SAVE_DRAFT_FULFILLED });
} catch (err) {
yield put({
type: types.SAVE_DRAFT_REJECTED,
payload: err.message || err.toString(),
error: true,
});
}
}
export function* handleFetchAndCreateDrafts(
action: ReturnType<typeof fetchAndCreateDrafts>,
): SagaIterator {
yield put(fetchDrafts());
yield take([types.FETCH_DRAFTS_FULFILLED, types.FETCH_DRAFTS_PENDING]);
const drafts: Yielded<typeof getDrafts> = yield select(getDrafts);
// Back out if draft fetch failed and we don't have drafts
if (!drafts) {
console.warn('Fetch of drafts failed, not creating new draft');
return;
}
// Create new draft if we don't have one for rfp (if provided) or if
// we don't have any at all
if (action.payload.rfpId) {
const rfpDraft = drafts.find(d => !!d.rfp && d.rfp.id === action.payload.rfpId);
if (!rfpDraft) {
yield put(createDraft(action.payload));
} else if (action.payload.redirect) {
// If we were supposed to redirect, redirect to existing rfp draft
yield put(replace(`/proposals/${rfpDraft.proposalId}/edit`));
}
} else if (drafts.length === 0) {
yield put(createDraft(action.payload));
}
}
export function* handleDeleteDraft(action: ReturnType<typeof deleteDraft>): SagaIterator {
try {
yield call(deleteProposal, action.payload);
put({ type: types.DELETE_DRAFT_FULFILLED });
} catch (err) {
yield put({
type: types.DELETE_DRAFT_REJECTED,
payload: err.message || err.toString(),
error: true,
});
return;
}
yield call(handleFetchDrafts);
}
export function* handleInitializeForm(
action: ReturnType<typeof initializeForm>,
): SagaIterator {
try {
yield put(fetchDrafts());
yield take([types.FETCH_DRAFTS_FULFILLED]);
const proposalId = action.payload;
let draft: Yielded<typeof getDraftById> = yield select(getDraftById, proposalId);
if (!draft) {
yield call(handleFetchDrafts);
draft = yield select(getDraftById, proposalId);
if (!draft) {
// If it's a real proposal, just not in draft form, redirect to it
try {
yield call(getProposal, proposalId);
yield put({ type: types.INITIALIZE_FORM_REJECTED });
yield put(replace(`/proposals/${action.payload}`));
return;
} catch (err) {
throw new Error('Proposal not found');
}
}
}
yield put({
type: types.INITIALIZE_FORM_FULFILLED,
payload: draft,
});
} catch (err) {
yield put({
type: types.INITIALIZE_FORM_REJECTED,
payload: err.message || err.toString(),
error: true,
});
}
}
export default function* createSagas(): SagaIterator {
yield takeEvery(types.CREATE_DRAFT_PENDING, handleCreateDraft);
yield takeLatest(types.FETCH_DRAFTS_PENDING, handleFetchDrafts);
yield takeLatest(types.SAVE_DRAFT_PENDING, handleSaveDraft);
yield takeEvery(types.DELETE_DRAFT_PENDING, handleDeleteDraft);
yield takeEvery(types.INITIALIZE_FORM_PENDING, handleInitializeForm);
yield takeEvery(types.FETCH_AND_CREATE_DRAFTS, handleFetchAndCreateDrafts);
}