-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from andela/feature/164829182-user-report-article
feature(report-article): users can report an article in violation
- Loading branch information
Showing
13 changed files
with
316 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { toast } from 'react-toastify'; | ||
import { REPORT_SUCCESS, REPORT_FAILED, REPORTED_ARTICLE, LOADING_REPORT } from './types'; | ||
import { api } from '../services/Api'; | ||
import { loadingMessage } from './articlesActions'; | ||
|
||
export function successMessage(responseData) { | ||
return { type: REPORT_SUCCESS, payload: responseData }; | ||
} | ||
export function failureMessage(error) { | ||
return { type: REPORT_FAILED, payload: error }; | ||
} | ||
|
||
export const reportAnArticleAction = data => (dispatch, history) => { | ||
dispatch(loadingMessage(LOADING_REPORT)); | ||
return api.articles.reportAnArticle(data) | ||
.then((response) => { | ||
dispatch(successMessage(response.data)); | ||
}) | ||
.catch((error) => { | ||
dispatch(failureMessage(error.response.data)); | ||
}); | ||
}; | ||
|
||
export default reportAnArticleAction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import React, { Component } from 'react'; | ||
import { PropTypes } from 'prop-types'; | ||
import _ from 'lodash'; | ||
import { connect } from 'react-redux'; | ||
import { Button, Header, Icon, Modal, Form, Popup, Message } from 'semantic-ui-react'; | ||
import { reportAnArticleAction } from '../../actions/reportArticleActions'; | ||
import { SHOW_MODAL } from '../../actions/types'; | ||
import store from '../../store'; | ||
import isEmpty from "../../utils/is_empty"; | ||
|
||
export class ReportArticleModal extends Component { | ||
constructor() { | ||
super(); | ||
this.state = { | ||
type_of_report: '', | ||
report: '', | ||
}; | ||
} | ||
|
||
handleChange = (event) => { | ||
this.setState({ [event.target.name]: event.target.value }); | ||
}; | ||
|
||
handleSelectChange=(e, { value }) => this.setState({ type_of_report: value }); | ||
|
||
reportArticle = (event) => { | ||
event.preventDefault(); | ||
const { articleReporter, slug } = this.props; | ||
|
||
articleReporter({ slug, report: this.state }); | ||
store.dispatch({ type: SHOW_MODAL, payload: { modalShow: false } }); | ||
}; | ||
|
||
componentWillReceiveProps(nextProps) { | ||
if (nextProps.reports){ | ||
this.setState({ | ||
type_of_report: '', | ||
report: '' | ||
}) | ||
} | ||
} | ||
|
||
render() { | ||
const countryOptions = _.map(['spam', 'harassment', 'rules violation', 'plagiarism'], country => ({ | ||
key: country, | ||
text: country, | ||
value: country, | ||
})); | ||
const {type_of_report, report} = this.state | ||
const {loading, reports, errorMessage} = this.props; | ||
|
||
console.log(this.props) | ||
|
||
return ( | ||
<Modal | ||
as='h1' | ||
trigger={ | ||
<Popup | ||
trigger={<Button circular size='large' icon="fas fa-ellipsis-h" />} | ||
content='Report this article' | ||
on={['click']} | ||
hideOnScroll | ||
position='bottom center' | ||
/> | ||
} | ||
basic | ||
closeIcon> | ||
<Header | ||
as='h1' | ||
icon='shield alternate' | ||
content='REPORT ARTICLE' /> | ||
<Modal.Content> | ||
{!isEmpty(reports.report) | ||
? <Message success header='Reporting Completed' content="Your report has successfully been recieved. Kindly close the form." /> | ||
: '' | ||
} | ||
|
||
<Form loading={loading}> | ||
<Form.Select | ||
label="Type of report" | ||
placeholder='Type_of_report' | ||
options={countryOptions} | ||
name='type_of_report' | ||
value={type_of_report} | ||
onChange={this.handleSelectChange} | ||
error={!isEmpty(errorMessage ? errorMessage.type_of_report : '')} | ||
/> | ||
<Form.TextArea | ||
label='Report' | ||
placeholder='Tell us more about it...' | ||
name='report' | ||
value={report} | ||
onChange={this.handleChange} | ||
error={!isEmpty(errorMessage ? errorMessage.report : '')} | ||
/> | ||
</Form> | ||
</Modal.Content> | ||
<Modal.Actions> | ||
<Button | ||
color='green' | ||
type="submit" | ||
onClick={this.reportArticle} | ||
> | ||
<Icon name='checkmark' /> | ||
Report | ||
</Button> | ||
</Modal.Actions> | ||
</Modal> | ||
); | ||
} | ||
} | ||
|
||
|
||
ReportArticleModal.defaultProps = { | ||
slug: '', | ||
loading: false, | ||
reports: {}, | ||
errorMessage: {}, | ||
}; | ||
|
||
ReportArticleModal.propTypes = { | ||
isLoading: PropTypes.bool.isRequired, | ||
slug: PropTypes.string, | ||
articleReporter: PropTypes.func.isRequired, | ||
}; | ||
|
||
export const mapStateToProps = ({reports}) => ({ | ||
loading: reports.loading, | ||
reports: reports.report, | ||
errorMessage: reports.errorMessage.errors, | ||
}); | ||
|
||
export const mapDispatchToProps = dispatch => ({ | ||
articleReporter: (slug, reportData) => { | ||
dispatch(reportAnArticleAction(slug, reportData)); | ||
}, | ||
}); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(ReportArticleModal); | ||
// export default ReportArticleModal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import React from 'react'; | ||
import { shallow, mount } from 'enzyme'; | ||
import { ReportArticleModal } from '../ReportArticleModal'; | ||
|
||
|
||
const setUp = () => { | ||
const props = { | ||
slug: "try", | ||
isLoading: false, | ||
articleReporter: jest.fn(), | ||
}; | ||
const wrapper = shallow(<ReportArticleModal {...props} />); | ||
|
||
return { | ||
props, | ||
wrapper, | ||
}; | ||
}; | ||
|
||
describe('ReportArticleModal slug test', () => { | ||
const { wrapper, props } = setUp(); | ||
|
||
it(' render slug section exists', () => { | ||
const slugSection = wrapper.find('slug'); | ||
expect(wrapper.find('Form')).toBeDefined(); | ||
|
||
expect(slugSection.exists()) | ||
.toBe(false); | ||
}); | ||
}); | ||
|
||
describe('ReportArticleModal', () => { | ||
it('displays Form tag correctly', () => { | ||
const wrapper = shallow(<ReportArticleModal />); | ||
expect(wrapper.find('Modal')).toBeDefined(); | ||
}); | ||
|
||
it('displays Modal.Content tag correctly', () => { | ||
const component = shallow(<ReportArticleModal />); | ||
expect(component.find('Modal.Content')).toBeDefined(); | ||
}); | ||
|
||
it('displays the select tag correctly', () => { | ||
const component = shallow(<ReportArticleModal debug />); | ||
expect(component.find('Form.Select')).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import expect from 'expect'; | ||
import reducer from '../reportArticleReducer'; | ||
|
||
import { | ||
successMessage, | ||
reportAnArticleAction, | ||
failureMessage, | ||
} from '../../actions/reportArticleActions'; | ||
|
||
import { loadingMessage } from '../../actions/articlesActions'; | ||
|
||
const INITIAL_STATE = { | ||
loading: false, | ||
loading: true, | ||
report: {"id": 1}, | ||
errorMessage: {}, | ||
}; | ||
|
||
describe('Testing REPORT ARTICLE REDUCER', () => { | ||
it('should return the initial state', () => { | ||
const state = reducer(INITIAL_STATE, {}); | ||
expect(state).toEqual(INITIAL_STATE); | ||
}); | ||
|
||
it('should handle LOADING_PROGRESS', () => { | ||
const loadingAction = loadingMessage(); | ||
const state = reducer(INITIAL_STATE, loadingAction); | ||
const expectedState = { | ||
...INITIAL_STATE, | ||
loading: true, | ||
}; | ||
expect(state) | ||
.toEqual(expectedState); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { REPORT_SUCCESS, REPORT_FAILED, LOADING_REPORT } from '../actions/types'; | ||
|
||
export const initialState = { | ||
loading: false, | ||
report: {}, | ||
errorMessage: {}, | ||
}; | ||
|
||
const reportArticleReducers = (state = initialState, action) => { | ||
switch (action.type) { | ||
case LOADING_REPORT: | ||
return { | ||
...state, | ||
loading: true, | ||
}; | ||
case REPORT_SUCCESS: | ||
return { | ||
...state, | ||
report: action.payload, | ||
errorMessage: {}, | ||
loading: false, | ||
}; | ||
case REPORT_FAILED: | ||
return { | ||
...state, | ||
errorMessage: action.payload, | ||
loading: false, | ||
}; | ||
default: | ||
return state; | ||
} | ||
}; | ||
|
||
export default reportArticleReducers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters