Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#166816082 Implement edit comment and view comment edit history functionality #49

Merged
merged 1 commit into from
Sep 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/actionTypes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,9 @@ export const REQUEST_PASSWORD_RESET = 'REQUEST_PASSWORD_RESET';

export const GET_NOTIFICATION_SUCCESS = 'GET_NOTIFICATION_SUCCESS';
export const GET_NOTIFICATION_START = 'GET_NOTIFICATION_START';
export const UPDATE_COMMENT_START = 'UPDATE_COMMENT_START';
export const UPDATE_COMMENT = 'UPDATE_COMMENT';
export const UPDATE_COMMENT_FAIL = 'UPDATE_COMMENT_FAIL';
export const GET_COMMENT_EDIT_HISTORY_START = 'GET_COMMENT_EDIT_HISTORY_START';
export const GET_COMMENT_EDIT_HISTORY = 'GET_COMMENT_EDIT_HISTORY';
export const CLEAN_UP_COMMENT_EDIT_HISTORY = 'CLEAN_UP_COMMENT_EDIT_HISTORY';
8 changes: 7 additions & 1 deletion src/components/CreateComment/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class CreateComment extends Component {
{...comment}
datePublished={datePublished}
handleLike={this.handleLike}
handleCommentModalOpen={this.props.handleCommentModalOpen}
handleCommentModalClose={this.props.handleCommentModalClose}
token={this.props.auth.user.token}
viewerEmail={this.props.auth.user.email}
/>
);
});
Expand Down Expand Up @@ -119,7 +123,9 @@ CreateComment.propTypes = {
token: PropTypes.string,
slugtoken: PropTypes.string,
allComment: PropTypes.object,
auth: PropTypes.object
auth: PropTypes.object,
handleCommentModalOpen: PropTypes.func,
handleCommentModalClose: PropTypes.func
};

export const mapStateToProps = state => {
Expand Down
27 changes: 27 additions & 0 deletions src/components/EditCommentHistory/editCommentHistory.action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import axiosUtil from '../../utils/axiosConfig';
import * as actionTypes from '../../actionTypes/index';

export const getCommentEditHistory = payload => {
return { type: actionTypes.GET_COMMENT_EDIT_HISTORY, payload };
};

export const getCommentEditHistoryStart = () => {
return { type: actionTypes.GET_COMMENT_EDIT_HISTORY_START };
};

export const cleanUpEditHistory = () => {
return { type: actionTypes.CLEAN_UP_COMMENT_EDIT_HISTORY };
};
export const getEditHistoryRequest = (slug, commentId, token) => {
return async dispatch => {
dispatch(cleanUpEditHistory());
dispatch(getCommentEditHistoryStart());
const response = await axiosUtil.get(
`articles/${slug}/comments/${commentId}/history`,
{
headers: { Authorization: `Bearer ${token}` }
}
);
dispatch(getCommentEditHistory(response.data.data));
};
};
25 changes: 25 additions & 0 deletions src/components/EditCommentHistory/editCommentHistory.reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as types from '../../actionTypes';

const commentEditHistoryReducer = (state = {}, action) => {
switch (action.type) {
case types.GET_COMMENT_EDIT_HISTORY_START:
return {
...state,
isLoading: true
};
case types.GET_COMMENT_EDIT_HISTORY:
return {
...state,
history: action.payload,
isLoading: false
};
case types.CLEAN_UP_COMMENT_EDIT_HISTORY:
return {
...state,
isLoading: false
};
default:
return state;
}
};
export default commentEditHistoryReducer;
136 changes: 136 additions & 0 deletions src/components/EditCommentHistory/editCommentHistory.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React from 'react';
import '@babel/polyfill';
import mockAxios from 'axios';
import { shallow } from 'enzyme';
import editCommentHistoryReducer from './editCommentHistory.reducer';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { getEditHistoryRequest } from './editCommentHistory.action';
import { EditCommentHistory } from './index.jsx';
import {
GET_COMMENT_EDIT_HISTORY,
GET_COMMENT_EDIT_HISTORY_START,
CLEAN_UP_COMMENT_EDIT_HISTORY
} from '../../actionTypes/index';
import Loader from '../LoadingIndicator/index.jsx';

const middlewares = [thunk];
const mockStore = configureStore(middlewares);

const slug = 'How-To-Become-a-10x-Engineer';
const comment = 'Some new comment';
const token = 'jndmfdfdfdfkldk';
const response = {
'6:00pm, 12th August 2030': 'previous comment',
'6:01pm, 12th August 2030': 'another comment',
'6:03pm, 12th August 2030': 'another comment'
};

describe('Edit comment History actions tests', () => {
let store;
beforeEach(() => {
store = mockStore({});
jest.resetAllMocks();
});
afterEach(() => {
store.clearActions();
});

it('Should dispatch The UPDATE_COMMENT action', async () => {
const mockData = {
data: {
data: {
response
}
}
};

mockAxios.get.mockResolvedValue({
data: mockData.data
});

const expectedActions = [
{ type: 'CLEAN_UP_COMMENT_EDIT_HISTORY' },
{ type: 'GET_COMMENT_EDIT_HISTORY_START' },
{
type: 'GET_COMMENT_EDIT_HISTORY',
payload: {
response
}
}
];

await store.dispatch(getEditHistoryRequest(slug, comment, token));
expect(store.getActions()).toEqual(expectedActions);
});
});

describe('Get Comment Edit History Reducer Tests', () => {
const initialState = {};
it('Should return a new state if it recieves a GET_COMMENT_EDIT_HISTORY_START action type', () => {
const newState = editCommentHistoryReducer(initialState, {
type: GET_COMMENT_EDIT_HISTORY_START,
payload: {}
});
expect(newState).toEqual({
isLoading: true
});
});

it('Should return a new state if it recieves a GET_COMMENT_EDIT_HISTORY action type', () => {
const newState = editCommentHistoryReducer(initialState, {
type: GET_COMMENT_EDIT_HISTORY,
payload: response
});
expect(newState).toEqual({
isLoading: false,
history: response
});
});

it('Should return a new state if it recieves a CLEAN_UP_COMMENT_EDIT_HISTORY action type', () => {
const newState = editCommentHistoryReducer(initialState, {
type: CLEAN_UP_COMMENT_EDIT_HISTORY,
payload: {}
});
expect(newState).toEqual({
isLoading: false
});
});
});

describe('EditCommentHistory Template', () => {
it(`should render the EditCommentHistory Template when there is no edit history`, () => {
const props = {
commentHistory: {
history: {
commentEditHistory: {}
}
},
isLoading: false
};
const component = shallow(<EditCommentHistory {...props} />);
expect(
component
.find('.comment-edit-history')
.contains(
<h5 className="pt-5 text-center">This comment has no edit history</h5>
)
).toBeTruthy();
});

it(`should render the EditCommentHistory Template when the request is loading`, () => {
const props = {
commentHistory: {
history: {
commentEditHistory: { response }
}
},
isLoading: true
};
const component = shallow(<EditCommentHistory {...props} />);
expect(
component.find('.comment-edit-history').contains(<Loader />)
).toBeTruthy();
});
});
48 changes: 48 additions & 0 deletions src/components/EditCommentHistory/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import './style.scss';
import Loader from '../LoadingIndicator/index.jsx';

export class EditCommentHistory extends Component {
render() {
const { commentHistory, isLoading, lightTheme } = this.props;
const additionalClass = lightTheme ? 'comment-body-light' : '';
const historyList = isLoading ? (
<Loader />
) : commentHistory &&
commentHistory.history &&
Object.keys(commentHistory.history.commentEditHistory).length > 1 ? (
Object.entries(commentHistory.history.commentEditHistory).map(
(comment, i) => {
return (
<div key={i} className={`comment-body ${additionalClass}`}>
<span className={'w-100 d-block p-2'}>{comment[1]}</span>
<span className={'w-100 d-block time-stamp text-right p-1'}>
{moment(comment[0]).format('MMMM Do, YYYY, h:mm:ss a')}
</span>
</div>
);
}
)
) : (
<h5 className="pt-5 text-center">This comment has no edit history</h5>
);
return (
<>
<div className="comment-edit-history">{historyList}</div>
</>
);
}
}

EditCommentHistory.propTypes = {
lightTheme: PropTypes.bool,
commentHistory: PropTypes.object,
slug: PropTypes.string,
token: PropTypes.string,
commentId: PropTypes.any,
isLoading: PropTypes.bool
};

export default EditCommentHistory;
32 changes: 32 additions & 0 deletions src/components/EditCommentHistory/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.comment-edit-history {
height: 300px;
width: 50vw;
overflow: scroll;
}
.time-stamp {
background-color: rgba(0, 0, 0, 0.64);
border-top: 1px solid rgba(0, 0, 0, 0.125);
font-size: 0.5em;
}
.comment-body {
background: #161616;
border: 1px solid grey;
border-radius: 3px;
color: inherit;
min-height: 2em;
margin-bottom: 7px;
}
.edit-functionality:hover {
cursor: pointer;
}
.modal-main {
top: 35% !important;
}

.comment-body-light {
background: white !important;
color: black !important;
.time-stamp {
background: rgba(0, 0, 0, 0.03) !important;
}
}
22 changes: 22 additions & 0 deletions src/components/Editcomment/editComment.action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import axiosUtil from '../../utils/axiosConfig';
import * as actionTypes from '../../actionTypes/index';

export const updateComment = payload => {
return {
type: actionTypes.UPDATE_COMMENT,
payload: { payload, isEdited: true }
};
};

export const updateCommentRequest = (slug, commentId, comment, token) => {
return async dispatch => {
const response = await axiosUtil.patch(
`articles/${slug}/comments/${commentId}/edit`,
{ comment },
{
headers: { Authorization: `Bearer ${token}` }
}
);
dispatch(updateComment(response.data.data));
};
};
Loading