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

#34 made submitting comment form

This commit is contained in:
Fedor Katurov 2021-02-27 18:11:38 +07:00
parent 051b199d5d
commit dad416e6e2
6 changed files with 97 additions and 65 deletions

View file

@ -15,20 +15,13 @@ import { EMPTY_COMMENT } from '~/redux/node/constants';
interface IProps { interface IProps {
comment?: IComment; comment?: IComment;
nodeId: INode['id']; nodeId: INode['id'];
isBefore?: boolean;
onCancelEdit?: () => void; onCancelEdit?: () => void;
} }
const LocalCommentForm: FC<IProps> = ({ comment, nodeId, isBefore, onCancelEdit }) => { const LocalCommentForm: FC<IProps> = ({ comment, nodeId, onCancelEdit }) => {
const [textarea, setTextarea] = useState<HTMLTextAreaElement>(); const [textarea, setTextarea] = useState<HTMLTextAreaElement>();
const uploader = useFileUploader(UPLOAD_SUBJECTS.COMMENT, UPLOAD_TARGETS.COMMENTS); const uploader = useFileUploader(UPLOAD_SUBJECTS.COMMENT, UPLOAD_TARGETS.COMMENTS);
const formik = useCommentFormFormik( const formik = useCommentFormFormik(comment || EMPTY_COMMENT, nodeId, uploader, onCancelEdit);
comment || EMPTY_COMMENT,
nodeId,
uploader,
onCancelEdit,
isBefore
);
const isLoading = formik.isSubmitting || uploader.isUploading; const isLoading = formik.isSubmitting || uploader.isUploading;
const isEditing = !!comment?.id; const isEditing = !!comment?.id;
@ -51,6 +44,7 @@ const LocalCommentForm: FC<IProps> = ({ comment, nodeId, isBefore, onCancelEdit
)} )}
<Button <Button
type="submit"
size="small" size="small"
color="gray" color="gray"
iconRight={!isEditing ? 'enter' : 'check'} iconRight={!isEditing ? 'enter' : 'check'}

View file

@ -19,7 +19,7 @@ const NodeCommentFormUnconnected: FC<IProps> = ({ user, isBefore, nodeId }) => {
return ( return (
<CommentWrapper user={user}> <CommentWrapper user={user}>
<CommentForm id={0} is_before={isBefore} /> <CommentForm id={0} is_before={isBefore} />
<LocalCommentForm isBefore={isBefore} nodeId={nodeId} /> <LocalCommentForm nodeId={nodeId} />
</CommentWrapper> </CommentWrapper>
); );
}; };

View file

@ -1,5 +1,5 @@
import { INode, IValidationErrors, IComment, ITag, IFile } from '../types'; import { IComment, IFile, INode, ITag, IValidationErrors } from '../types';
import { NODE_ACTIONS, NODE_TYPES } from './constants'; import { NODE_ACTIONS } from './constants';
import { INodeState } from './reducer'; import { INodeState } from './reducer';
export const nodeSet = (node: Partial<INodeState>) => ({ export const nodeSet = (node: Partial<INodeState>) => ({
@ -50,6 +50,17 @@ export const nodePostComment = (id: number, is_before: boolean) => ({
type: NODE_ACTIONS.POST_COMMENT, type: NODE_ACTIONS.POST_COMMENT,
}); });
export const nodePostLocalComment = (
nodeId: INode['id'],
comment: IComment,
callback: (e?: string) => void
) => ({
nodeId,
comment,
callback,
type: NODE_ACTIONS.POST_LOCAL_COMMENT,
});
export const nodeCancelCommentEdit = (id: number) => ({ export const nodeCancelCommentEdit = (id: number) => ({
id, id,
type: NODE_ACTIONS.CANCEL_COMMENT_EDIT, type: NODE_ACTIONS.CANCEL_COMMENT_EDIT,

View file

@ -42,6 +42,7 @@ export const NODE_ACTIONS = {
SET_EDITOR: `${prefix}SET_EDITOR`, SET_EDITOR: `${prefix}SET_EDITOR`,
POST_COMMENT: `${prefix}POST_COMMENT`, POST_COMMENT: `${prefix}POST_COMMENT`,
POST_LOCAL_COMMENT: `${prefix}POST_LOCAL_COMMENT`,
SET_COMMENTS: `${prefix}SET_COMMENTS`, SET_COMMENTS: `${prefix}SET_COMMENTS`,
SET_RELATED: `${prefix}SET_RELATED`, SET_RELATED: `${prefix}SET_RELATED`,

View file

@ -1,59 +1,54 @@
import { takeLatest, call, put, select, delay, all, takeLeading } from 'redux-saga/effects'; import { all, call, delay, put, select, takeLatest, takeLeading } from 'redux-saga/effects';
import { push } from 'connected-react-router'; import { push } from 'connected-react-router';
import { omit } from 'ramda'; import { omit } from 'ramda';
import { COMMENTS_DISPLAY, EMPTY_COMMENT, EMPTY_NODE, NODE_ACTIONS, NODE_EDITOR_DATA } from './constants';
import { import {
NODE_ACTIONS, nodeCancelCommentEdit,
EMPTY_NODE,
EMPTY_COMMENT,
NODE_EDITOR_DATA,
COMMENTS_DISPLAY,
} from './constants';
import {
nodeSave,
nodeSetSaveErrors,
nodeLoadNode,
nodeSetLoading,
nodeSetCurrent,
nodeSetLoadingComments,
nodePostComment,
nodeSetSendingComment,
nodeSetComments,
nodeSetCommentData,
nodeUpdateTags,
nodeSetTags,
nodeCreate, nodeCreate,
nodeSetEditor,
nodeEdit, nodeEdit,
nodeLike, nodeEditComment,
nodeSetRelated,
nodeGotoNode, nodeGotoNode,
nodeLike,
nodeLoadNode,
nodeLock, nodeLock,
nodeLockComment, nodeLockComment,
nodeEditComment, nodePostComment,
nodePostLocalComment,
nodeSave,
nodeSet, nodeSet,
nodeCancelCommentEdit, nodeSetCommentData,
nodeSetComments,
nodeSetCurrent,
nodeSetEditor,
nodeSetLoading,
nodeSetLoadingComments,
nodeSetRelated,
nodeSetSaveErrors,
nodeSetSendingComment,
nodeSetTags,
nodeUpdateTags
} from './actions'; } from './actions';
import { import {
postNode,
getNode, getNode,
postNodeComment,
getNodeComments, getNodeComments,
updateNodeTags,
postNodeLike,
postNodeStar,
getNodeRelated, getNodeRelated,
postNode,
postNodeComment,
postNodeLike,
postNodeLock, postNodeLock,
postNodeLockComment, postNodeLockComment,
postNodeStar,
updateNodeTags
} from './api'; } from './api';
import { reqWrapper } from '../auth/sagas'; import { reqWrapper } from '../auth/sagas';
import { flowSetNodes, flowSetUpdated } from '../flow/actions'; import { flowSetNodes, flowSetUpdated } from '../flow/actions';
import { ERRORS } from '~/constants/errors'; import { ERRORS } from '~/constants/errors';
import { modalSetShown, modalShowDialog } from '../modal/actions'; import { modalSetShown, modalShowDialog } from '../modal/actions';
import { selectFlowNodes, selectFlow } from '../flow/selectors'; import { selectFlow, selectFlowNodes } from '../flow/selectors';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { selectNode } from './selectors'; import { selectNode } from './selectors';
import { IResultWithStatus, INode, Unwrap } from '../types'; import { INode, IResultWithStatus, Unwrap } from '../types';
import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs'; import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs';
import { DIALOGS } from '~/redux/modal/constants'; import { DIALOGS } from '~/redux/modal/constants';
import { INodeState } from './reducer'; import { INodeState } from './reducer';
@ -229,6 +224,43 @@ function* onPostComment({ id }: ReturnType<typeof nodePostComment>) {
} }
} }
function* onPostLocalComment({
nodeId,
comment,
callback,
}: ReturnType<typeof nodePostLocalComment>) {
const { data, error }: Unwrap<ReturnType<typeof postNodeComment>> = yield call(
reqWrapper,
postNodeComment,
{
data: comment,
id: nodeId,
}
);
if (error || !data.comment) {
return callback(error);
}
const { current }: ReturnType<typeof selectNode> = 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<typeof nodeCancelCommentEdit>) { function* onCancelCommentEdit({ id }: ReturnType<typeof nodeCancelCommentEdit>) {
const { comment_data } = yield select(selectNode); const { comment_data } = yield select(selectNode);
@ -358,6 +390,7 @@ export default function* nodeSaga() {
yield takeLatest(NODE_ACTIONS.GOTO_NODE, onNodeGoto); yield takeLatest(NODE_ACTIONS.GOTO_NODE, onNodeGoto);
yield takeLatest(NODE_ACTIONS.LOAD_NODE, onNodeLoad); yield takeLatest(NODE_ACTIONS.LOAD_NODE, onNodeLoad);
yield takeLatest(NODE_ACTIONS.POST_COMMENT, onPostComment); yield takeLatest(NODE_ACTIONS.POST_COMMENT, onPostComment);
yield takeLatest(NODE_ACTIONS.POST_LOCAL_COMMENT, onPostLocalComment);
yield takeLatest(NODE_ACTIONS.CANCEL_COMMENT_EDIT, onCancelCommentEdit); yield takeLatest(NODE_ACTIONS.CANCEL_COMMENT_EDIT, onCancelCommentEdit);
yield takeLatest(NODE_ACTIONS.UPDATE_TAGS, onUpdateTags); yield takeLatest(NODE_ACTIONS.UPDATE_TAGS, onUpdateTags);
yield takeLatest(NODE_ACTIONS.CREATE, onCreateSaga); yield takeLatest(NODE_ACTIONS.CREATE, onCreateSaga);

View file

@ -3,22 +3,14 @@ import { useCallback, useRef } from 'react';
import { FormikHelpers, useFormik, useFormikContext } from 'formik'; import { FormikHelpers, useFormik, useFormikContext } from 'formik';
import { array, object, string } from 'yup'; import { array, object, string } from 'yup';
import { FileUploader } from '~/utils/hooks/fileUploader'; import { FileUploader } from '~/utils/hooks/fileUploader';
import { useDispatch } from 'react-redux';
import { nodePostLocalComment } from '~/redux/node/actions';
const validationSchema = object().shape({ const validationSchema = object().shape({
text: string(), text: string(),
files: array(), files: array(),
}); });
const submitComment = (
id: INode['id'],
values: IComment,
isBefore: boolean,
callback: (e?: string) => void
) => {
console.log('Submitting', id, values);
new Promise(resolve => setTimeout(resolve, 500)).then(() => callback());
};
const onSuccess = ({ resetForm, setStatus, setSubmitting }: FormikHelpers<IComment>) => ( const onSuccess = ({ resetForm, setStatus, setSubmitting }: FormikHelpers<IComment>) => (
e: string e: string
) => { ) => {
@ -38,25 +30,26 @@ export const useCommentFormFormik = (
values: IComment, values: IComment,
nodeId: INode['id'], nodeId: INode['id'],
uploader: FileUploader, uploader: FileUploader,
stopEditing?: () => void, stopEditing?: () => void
isBefore: boolean = false
) => { ) => {
const dispatch = useDispatch();
const { current: initialValues } = useRef(values); const { current: initialValues } = useRef(values);
const onSubmit = useCallback( const onSubmit = useCallback(
(values: IComment, helpers: FormikHelpers<IComment>) => { (values: IComment, helpers: FormikHelpers<IComment>) => {
helpers.setSubmitting(true); helpers.setSubmitting(true);
submitComment( dispatch(
nodeId, nodePostLocalComment(
{ nodeId,
...values, {
files: uploader.files, ...values,
}, files: uploader.files,
isBefore, },
onSuccess(helpers) onSuccess(helpers)
)
); );
}, },
[isBefore, nodeId, uploader.files] [dispatch, nodeId, uploader.files]
); );
const onReset = useCallback(() => { const onReset = useCallback(() => {