mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
#34 made submitting comment form
This commit is contained in:
parent
051b199d5d
commit
dad416e6e2
6 changed files with 97 additions and 65 deletions
|
@ -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'}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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`,
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue