Add edit and delete actions to posts and comments (#125)

This commit is contained in:
Riccardo Graziosi
2022-06-22 10:17:42 +02:00
committed by GitHub
parent 07ca2a304a
commit bc15140512
52 changed files with 1495 additions and 481 deletions

View File

@@ -0,0 +1,72 @@
import { Action } from "redux";
import { ThunkAction } from "redux-thunk";
import HttpStatus from "../../constants/http_status";
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
import { State } from "../../reducers/rootReducer";
export const COMMENT_DELETE_START = 'COMMENT_DELETE_START';
interface CommentDeleteStartAction {
type: typeof COMMENT_DELETE_START;
}
export const COMMENT_DELETE_SUCCESS = 'COMMENT_DELETE_SUCCESS';
interface CommentDeleteSuccessAction {
type: typeof COMMENT_DELETE_SUCCESS;
postId: number;
commentId: number;
}
export const COMMENT_DELETE_FAILURE = 'COMMENT_DELETE_FAILURE';
interface CommentDeleteFailureAction {
type: typeof COMMENT_DELETE_FAILURE;
error: string;
}
export type CommentDeleteActionTypes =
CommentDeleteStartAction |
CommentDeleteSuccessAction |
CommentDeleteFailureAction;
const commentDeleteStart = (): CommentDeleteStartAction => ({
type: COMMENT_DELETE_START,
});
const commentDeleteSuccess = (
postId: number,
commentId: number,
): CommentDeleteSuccessAction => ({
type: COMMENT_DELETE_SUCCESS,
postId,
commentId,
});
const commentDeleteFailure = (error: string): CommentDeleteFailureAction => ({
type: COMMENT_DELETE_FAILURE,
error,
});
export const deleteComment = (
postId: number,
commentId: number,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => (
async (dispatch) => {
dispatch(commentDeleteStart());
try {
const res = await fetch(`/posts/${postId}/comments/${commentId}`, {
method: 'DELETE',
headers: buildRequestHeaders(authenticityToken),
});
const json = await res.json();
if (res.status === HttpStatus.Accepted) {
dispatch(commentDeleteSuccess(postId, commentId));
} else {
dispatch(commentDeleteFailure(json.error));
}
} catch (e) {
dispatch(commentDeleteFailure(e));
}
}
);

View File

@@ -1,43 +1,81 @@
import { ThunkAction } from "redux-thunk";
import { State } from "../../reducers/rootReducer";
import { Action } from "redux";
import { ThunkAction } from "redux-thunk";
import HttpStatus from "../../constants/http_status";
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
import ICommentJSON from "../../interfaces/json/IComment";
import { State } from "../../reducers/rootReducer";
export const TOGGLE_COMMENT_IS_UPDATE_SUCCESS = 'TOGGLE_COMMENT_IS_UPDATE_SUCCESS';
export interface ToggleIsUpdateSuccessAction {
type: typeof TOGGLE_COMMENT_IS_UPDATE_SUCCESS;
commentId: number;
export const COMMENT_UPDATE_START = 'COMMENT_UPDATE_START';
interface CommentUpdateStartAction {
type: typeof COMMENT_UPDATE_START;
}
const toggleIsUpdateSuccess = (
commentId: number,
): ToggleIsUpdateSuccessAction => ({
type: TOGGLE_COMMENT_IS_UPDATE_SUCCESS,
commentId,
export const COMMENT_UPDATE_SUCCESS = 'COMMENT_UPDATE_SUCCESS';
interface CommentUpdateSuccessAction {
type: typeof COMMENT_UPDATE_SUCCESS;
comment: ICommentJSON;
}
export const COMMENT_UPDATE_FAILURE = 'COMMENT_UPDATE_FAILURE';
interface CommentUpdateFailureAction {
type: typeof COMMENT_UPDATE_FAILURE;
error: string;
}
export type CommentUpdateActionTypes =
CommentUpdateStartAction |
CommentUpdateSuccessAction |
CommentUpdateFailureAction;
const commentUpdateStart = (): CommentUpdateStartAction => ({
type: COMMENT_UPDATE_START,
});
export const toggleCommentIsUpdate = (
const commentUpdateSuccess = (
commentJSON: ICommentJSON,
): CommentUpdateSuccessAction => ({
type: COMMENT_UPDATE_SUCCESS,
comment: commentJSON,
});
const commentUpdateFailure = (error: string): CommentUpdateFailureAction => ({
type: COMMENT_UPDATE_FAILURE,
error,
});
export const updateComment = (
postId: number,
commentId: number,
currentIsPostUpdate: boolean,
body: string,
isPostUpdate: boolean,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
dispatch(commentUpdateStart());
try {
const response = await fetch(`/posts/${postId}/comments/${commentId}`, {
const res = await fetch(`/posts/${postId}/comments/${commentId}`, {
method: 'PATCH',
headers: buildRequestHeaders(authenticityToken),
body: JSON.stringify({
comment: {
is_post_update: !currentIsPostUpdate,
body,
is_post_update: isPostUpdate,
},
})
}),
});
const json = await res.json();
if (response.status === 200) {
dispatch(toggleIsUpdateSuccess(commentId));
if (res.status === HttpStatus.OK) {
dispatch(commentUpdateSuccess(json));
} else {
dispatch(commentUpdateFailure(json.error));
}
return Promise.resolve(res);
} catch (e) {
console.log(e);
dispatch(commentUpdateFailure(e));
return Promise.resolve(null);
}
}
};

View File

@@ -1,40 +0,0 @@
import { Action } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { State } from '../../reducers/rootReducer';
import buildRequestHeaders from '../../helpers/buildRequestHeaders';
export const CHANGE_POST_BOARD_SUCCESS = 'CHANGE_POST_BOARD_SUCCESS';
export interface ChangePostBoardSuccessAction {
type: typeof CHANGE_POST_BOARD_SUCCESS;
newBoardId: number;
}
const changePostBoardSuccess = (newBoardId: number): ChangePostBoardSuccessAction => ({
type: CHANGE_POST_BOARD_SUCCESS,
newBoardId,
});
export const changePostBoard = (
postId: number,
newBoardId: number,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
try {
const response = await fetch(`/posts/${postId}`, {
method: 'PATCH',
headers: buildRequestHeaders(authenticityToken),
body: JSON.stringify({
post: {
board_id: newBoardId,
},
})
});
if (response.status === 204) {
dispatch(changePostBoardSuccess(newBoardId));
}
} catch (e) {
console.log(e);
}
}

View File

@@ -0,0 +1,61 @@
export const POST_CHANGE_EDIT_FORM_TITLE = 'POST_CHANGE_EDIT_FORM_TITLE';
interface PostChangeEditFormTitle {
type: typeof POST_CHANGE_EDIT_FORM_TITLE,
title: string,
}
export const changePostEditFormTitle = (
title: string
): PostChangeEditFormTitle => ({
type: POST_CHANGE_EDIT_FORM_TITLE,
title,
});
export const POST_CHANGE_EDIT_FORM_DESCRIPTION = 'POST_CHANGE_EDIT_FORM_DESCRIPTION';
interface PostChangeEditFormDescription {
type: typeof POST_CHANGE_EDIT_FORM_DESCRIPTION,
description: string,
}
export const changePostEditFormDescription = (
description: string
): PostChangeEditFormDescription => ({
type: POST_CHANGE_EDIT_FORM_DESCRIPTION,
description,
});
export const POST_CHANGE_EDIT_FORM_BOARD = 'POST_CHANGE_EDIT_FORM_BOARD';
interface PostChangeEditFormBoard {
type: typeof POST_CHANGE_EDIT_FORM_BOARD,
boardId: number,
}
export const changePostEditFormBoard = (
boardId: number
): PostChangeEditFormBoard => ({
type: POST_CHANGE_EDIT_FORM_BOARD,
boardId,
});
export const POST_CHANGE_EDIT_FORM_POST_STATUS = 'POST_CHANGE_EDIT_FORM_POST_STATUS';
interface PostChangeEditFormPostStatus {
type: typeof POST_CHANGE_EDIT_FORM_POST_STATUS,
postStatusId: number,
}
export const changePostEditFormPostStatus = (
postStatusId: number
): PostChangeEditFormPostStatus => ({
type: POST_CHANGE_EDIT_FORM_POST_STATUS,
postStatusId,
});
export type ChangePostEditFormActionTypes =
PostChangeEditFormTitle |
PostChangeEditFormDescription |
PostChangeEditFormBoard |
PostChangeEditFormPostStatus;

View File

@@ -1,40 +0,0 @@
import { Action } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { State } from '../../reducers/rootReducer';
import buildRequestHeaders from '../../helpers/buildRequestHeaders';
export const CHANGE_POST_STATUS_SUCCESS = 'CHANGE_POST_STATUS_SUCCESS';
export interface ChangePostStatusSuccessAction {
type: typeof CHANGE_POST_STATUS_SUCCESS;
newPostStatusId: number;
}
const changePostStatusSuccess = (newPostStatusId: number): ChangePostStatusSuccessAction => ({
type: CHANGE_POST_STATUS_SUCCESS,
newPostStatusId,
});
export const changePostStatus = (
postId: number,
newPostStatusId: number,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
try {
const response = await fetch(`/posts/${postId}`, {
method: 'PATCH',
headers: buildRequestHeaders(authenticityToken),
body: JSON.stringify({
post: {
post_status_id: newPostStatusId,
},
})
});
if (response.status === 204) {
dispatch(changePostStatusSuccess(newPostStatusId));
}
} catch (e) {
console.log(e);
}
}

View File

@@ -0,0 +1,69 @@
import { Action } from "redux";
import { ThunkAction } from "redux-thunk";
import HttpStatus from "../../constants/http_status";
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
import { State } from "../../reducers/rootReducer";
export const POST_DELETE_START = 'POST_DELETE_START';
interface PostDeleteStartAction {
type: typeof POST_DELETE_START;
}
export const POST_DELETE_SUCCESS = 'POST_DELETE_SUCCESS';
interface PostDeleteSuccessAction {
type: typeof POST_DELETE_SUCCESS;
postId: number;
}
export const POST_DELETE_FAILURE = 'POST_DELETE_FAILURE';
interface PostDeleteFailureAction {
type: typeof POST_DELETE_FAILURE;
error: string;
}
export type PostDeleteActionTypes =
PostDeleteStartAction |
PostDeleteSuccessAction |
PostDeleteFailureAction;
const postDeleteStart = (): PostDeleteStartAction => ({
type: POST_DELETE_START,
});
const postDeleteSuccess = (
postId: number,
): PostDeleteSuccessAction => ({
type: POST_DELETE_SUCCESS,
postId,
});
const postDeleteFailure = (error: string): PostDeleteFailureAction => ({
type: POST_DELETE_FAILURE,
error,
});
export const deletePost = (
postId: number,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => (
async (dispatch) => {
dispatch(postDeleteStart());
try {
const res = await fetch(`/posts/${postId}`, {
method: 'DELETE',
headers: buildRequestHeaders(authenticityToken),
});
const json = await res.json();
if (res.status === HttpStatus.Accepted) {
dispatch(postDeleteSuccess(postId));
} else {
dispatch(postDeleteFailure(json.error));
}
} catch (e) {
dispatch(postDeleteFailure(e));
}
}
);

View File

@@ -0,0 +1,9 @@
export const POST_TOGGLE_EDIT_MODE = 'POST_TOGGLE_EDIT_MODE';
export interface PostToggleEditMode {
type: typeof POST_TOGGLE_EDIT_MODE;
}
export const togglePostEditMode = (): PostToggleEditMode => ({
type: POST_TOGGLE_EDIT_MODE,
});

View File

@@ -0,0 +1,83 @@
import { Action } from "redux";
import { ThunkAction } from "redux-thunk";
import HttpStatus from "../../constants/http_status";
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
import IPostJSON from "../../interfaces/json/IPost";
import { State } from "../../reducers/rootReducer";
export const POST_UPDATE_START = 'POST_UPDATE_START';
interface PostUpdateStartAction {
type: typeof POST_UPDATE_START;
}
export const POST_UPDATE_SUCCESS = 'POST_UPDATE_SUCCESS';
interface PostUpdateSuccessAction {
type: typeof POST_UPDATE_SUCCESS;
post: IPostJSON;
}
export const POST_UPDATE_FAILURE = 'POST_UPDATE_FAILURE';
interface PostUpdateFailureAction {
type: typeof POST_UPDATE_FAILURE;
error: string;
}
export type PostUpdateActionTypes =
PostUpdateStartAction |
PostUpdateSuccessAction |
PostUpdateFailureAction;
const postUpdateStart = (): PostUpdateStartAction => ({
type: POST_UPDATE_START,
});
const postUpdateSuccess = (
postJSON: IPostJSON,
): PostUpdateSuccessAction => ({
type: POST_UPDATE_SUCCESS,
post: postJSON,
});
const postUpdateFailure = (error: string): PostUpdateFailureAction => ({
type: POST_UPDATE_FAILURE,
error,
});
export const updatePost = (
id: number,
title: string,
description: string,
boardId: number,
postStatusId: number,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
dispatch(postUpdateStart());
try {
const res = await fetch(`/posts/${id}`, {
method: 'PATCH',
headers: buildRequestHeaders(authenticityToken),
body: JSON.stringify({
post: {
title,
description,
board_id: boardId,
post_status_id: postStatusId,
}
}),
});
const json = await res.json();
if (res.status === HttpStatus.OK) {
dispatch(postUpdateSuccess(json));
} else {
dispatch(postUpdateFailure(json.error));
}
return Promise.resolve(res);
} catch (e) {
dispatch(postUpdateFailure(e));
return Promise.resolve(null);
}
};