Skip to content

Commit

Permalink
feat(reporting): implement Users should be able to report an article
Browse files Browse the repository at this point in the history
- Write tests for Users should be able to report an article feature
[Delivers ##165305242]
  • Loading branch information
Benkimeric committed Jun 20, 2019
1 parent 66e50e8 commit fa6c407
Show file tree
Hide file tree
Showing 17 changed files with 1,169 additions and 66 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
"bootstrap": "^4.3.1",
"coveralls": "^3.0.3",
"css-loader": "^2.1.1",
"draft-js-export-html": "^1.3.3",
"draft-js": "^0.10.5",
"draft-js-export-html": "^1.3.3",
"draftjs-to-html": "^0.8.4",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.13.2",
Expand All @@ -45,8 +45,8 @@
"fetch-mock": "^7.3.3",
"file-loader": "^3.0.1",
"font-awesome": "^4.7.0",
"html-react-parser": "^0.7.1",
"history": "^4.9.0",
"html-react-parser": "^0.7.1",
"html-to-draftjs": "^1.4.0",
"image-webpack-loader": "^4.6.0",
"jwt-decode": "^2.2.0",
Expand All @@ -65,6 +65,7 @@
"react-redux": "^7.0.3",
"react-router-dom": "^5.0.0",
"react-toastify": "^5.2.0",
"reactjs-popup": "^1.4.1",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"semantic-ui-react": "^0.87.1",
Expand Down
33 changes: 33 additions & 0 deletions src/assets/styles/articles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,36 @@
overflow: auto;
white-space: nowrap;
}
#report-article {
cursor: pointer;
}

.react-confirm-alert-button-group > button:first-child {
border: 1px solid $delete-red;
background-color: white;
color: black;
}

.react-confirm-alert-button-group > button:first-child:hover {
background: #f44336;
color: white;
}

.react-confirm-alert-button-group > button:nth-child(2) {
border: 1px solid $blue;
background-color: white !important;
color: black;
}

.react-confirm-alert-button-group > button:nth-child(2):hover {
background: $blue !important;
color: white;
}

#report-error {
color: red !important;
}

.reason-title {
text-decoration: underline;
}
1 change: 1 addition & 0 deletions src/assets/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ $wrapper-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
$red: rgba(0, 0, 0, 0.3);
$grey: #eee;
$lightgray: #f5f5f5;
$delete-red: #f44336;
31 changes: 27 additions & 4 deletions src/components/articles/OneArticle.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import React, { Component } from 'react';
import {
Image, Row, Col, Button, Popover, OverlayTrigger,
} from 'react-bootstrap';
import { Image, Row, Col, Button, Popover, OverlayTrigger } from 'react-bootstrap';
import { NavLink, Link } from 'react-router-dom';
import parse from 'html-react-parser';
import PropTypes from 'prop-types';
Expand All @@ -14,8 +14,9 @@ class OneArticle extends Component {
const { bookmarks } = this.props;

let Chevron;
let ReportChevron;
const {
title, description, readtime, author, image, body, handleClick, slug, tags
title, description, readtime, author, image, body, handleClick, slug, tags, id, reportClick
} = this.props;
const popover = (
<Popover id="popover-basic">
Expand Down Expand Up @@ -63,6 +64,14 @@ class OneArticle extends Component {
</Popover>
);

const reportPopover = (
<Popover id="popover-basic">
<p id="report-article" onClick={() => reportClick(id)}>
Report Article
</p>
</Popover>
);

/** get the username if any of logged in user and return empty of none */
const username = localStorage.getItem('user')
? JSON.parse(localStorage.getItem('user')).username
Expand All @@ -78,6 +87,19 @@ class OneArticle extends Component {
Chevron = () => '';
}

/** check of user is owner or article or they are not
* logged in to display reportiong chevron
* */
if (username === '' || username === author) {
ReportChevron = () => '';
} else {
ReportChevron = () => (
<OverlayTrigger trigger="click" placement="top" overlay={reportPopover} rootClose>
<span className="mdi mdi-dots-horizontal hamburger-menu" />
</OverlayTrigger>
);
}

return (
<div className="container-fluid">
<Row>
Expand Down Expand Up @@ -126,6 +148,7 @@ class OneArticle extends Component {

<Col sm={10} className="body-text read-one-image">
{parse(body)}
<ReportChevron />
</Col>
</Row>
<div className="socialShare">
Expand Down
60 changes: 60 additions & 0 deletions src/components/articles/ReadArticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import moment from 'moment';
import { confirmAlert } from 'react-confirm-alert';
import 'react-confirm-alert/src/react-confirm-alert.css';
import { Form } from 'react-bootstrap';
import '../../assets/styles/articles.scss';
import { connect } from 'react-redux';
import { Loader } from '../layout/Loader';
import OneArticle from './OneArticle';
import { isTokenExpired, errorToast } from '../../helpers';
import { fetchOneArticle, deleteArticle } from '../../redux/actions/FetchArticlesActions';
import { fetchBookmark } from '../../redux/actions/bookmarkActions';
import { createReport } from '../../redux/actions/ArticlesReportsActions';

class ReadArticle extends Component {
state = {
reason: '',
}

componentWillMount() {
const {
match: {
Expand All @@ -24,6 +32,23 @@ class ReadArticle extends Component {
bookmarkFetch(slug);
}

handleChange=(e) => {
this.setState({
[e.target.id]: e.target.value,
});
}

/** check if textarea
* is empty else try
* to report */
handleReport=(reason, id) => {
if (reason.trim()) {
this.props.createReport({ reason, article: id });
} else {
errorToast('Please enter reason for reporting this article');
}
}

handleClick = e => {
e.preventDefault();
if (!isTokenExpired()) {
Expand All @@ -41,6 +66,37 @@ class ReadArticle extends Component {
}
};

/*
* Defines the reporting article function
*takes id of article as param
*reason is gotten from the local state
*uses the react-confirm-alert library for
*displaying the alert
*/
reportClick = (id) => {
confirmAlert({
title: 'Report Article',
message:
<Form>
<Form.Group>
<Form.Control as="textarea" rows="3" id="reason" onChange={this.handleChange} placeholder="Enter reason for reporting this article" />
</Form.Group>
<Form.Text className="text-muted" id="report-error">

</Form.Text>
</Form>,
buttons: [
{
label: 'Report',
onClick: () => this.handleReport(this.state.reason.toLowerCase(), id),
},
{
label: 'Cancel',
},
],
});
}

render() {
let article;
const {
Expand Down Expand Up @@ -71,10 +127,13 @@ class ReadArticle extends Component {
author={data.author.username}
image={data.image}
slug={data.slug}
id={data.id}
body={data.body}
handleClick={this.handleClick}
bookmarks={bookmarkedArticles}
tags={data.tag_list}
reportClick={this.reportClick}
reason={this.state.reason}
/>
);
}
Expand All @@ -91,6 +150,7 @@ export const mapDispatchToProps = () => ({
fetchOneArticle,
deleteArticle,
fetchBookmark,
createReport,
});

ReadArticle.propTypes = {
Expand Down
45 changes: 19 additions & 26 deletions src/components/profiles/Profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import { connect } from 'react-redux';
import InlineEditable from 'react-inline-editable-field';
import moment from 'moment';
import PropTypes from 'prop-types';
import Popup from 'reactjs-popup';

import '../../assets/styles/profile.scss';
import { Tabs, Tab } from 'react-bootstrap';
import FollowsView from '../follows/Follows';
import UserArticlesView from '../articles/UserArticles';
import { fetchProfile, updateProfile } from '../../redux/actions/profileActions';
import LoaderView from '../layout/Loader';
import UserReports from './UserReports';


/*
Expand Down Expand Up @@ -51,9 +54,7 @@ export class Profile extends Component {
onSubmit = e => {
e.preventDefault();

const {
first_name, last_name, bio, image,
} = this.state;
const { first_name, last_name, bio, image } = this.state;

const formData = new FormData();

Expand Down Expand Up @@ -88,9 +89,7 @@ export class Profile extends Component {
}

render() {
const {
isChanged: isLocalChanged, first_name, last_name, bio,
} = this.state;
const { isChanged: isLocalChanged, first_name, last_name, bio } = this.state;

const {
profile: { profile },
Expand Down Expand Up @@ -148,8 +147,8 @@ export class Profile extends Component {
<div className="profile-img">
<img
src={
profile.image
|| 'https://res.cloudinary.com/do8v0ew77/image/upload/v1559819721/20190606111521.png'
profile.image ||
'https://res.cloudinary.com/do8v0ew77/image/upload/v1559819721/20190606111521.png'
}
alt=""
/>
Expand Down Expand Up @@ -271,29 +270,23 @@ export class Profile extends Component {
</div>
</div>
</div>

<ul className="nav nav-tabs mt-1" id="myTab" role="tablist">
<li className="nav-item">
<a
className="nav-link bold active"
id="home-tab"
data-toggle="tab"
href="#home"
role="tab"
aria-controls="home"
aria-selected="true"
>
Articles
</a>
</li>
</ul>
</div>
</div>
<div className="col-md-2" />
</div>
</form>

<UserArticlesView />
<Tabs defaultActiveKey="articles" id="uncontrolled-tab-example">
<Tab eventKey="articles" title="Articles">
<UserArticlesView />
</Tab>
{ username && isProfileOwner ? (
<Tab eventKey="reports" title="Reports">
<UserReports />
</Tab>
) : ''
}

</Tabs>
</div>
);
}
Expand Down
Loading

0 comments on commit fa6c407

Please sign in to comment.