@plone/volto
Version:
Volto
304 lines (288 loc) • 8.67 kB
JSX
/**
* Moderate comments component.
* @module components/manage/Controlpanels/ModerateComments
*/
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { Link } from 'react-router-dom';
import { getParentUrl } from '@plone/volto/helpers/Url/Url';
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
import { createPortal } from 'react-dom';
import { Container, Button, Table } from 'semantic-ui-react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { deleteComment } from '@plone/volto/actions/comments/comments';
import { searchContent } from '@plone/volto/actions/search/search';
import FormattedRelativeDate from '@plone/volto/components/theme/FormattedDate/FormattedRelativeDate';
import Icon from '@plone/volto/components/theme/Icon/Icon';
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
import { CommentEditModal } from '@plone/volto/components/theme/Comments';
import backSVG from '@plone/volto/icons/back.svg';
const messages = defineMessages({
back: {
id: 'Back',
defaultMessage: 'Back',
},
ModerateComments: {
id: 'Moderate comments',
defaultMessage: 'Moderate comments',
},
});
/**
* ModerateCommentsComponent class.
* @class ModerateComments
* @extends Component
*/
class ModerateComments extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
searchContent: PropTypes.func.isRequired,
deleteComment: PropTypes.func.isRequired,
items: PropTypes.arrayOf(
PropTypes.shape({
'@id': PropTypes.string,
author_name: PropTypes.string,
creation_date: PropTypes.string,
text: PropTypes.shape({
data: PropTypes.string,
}),
is_deletable: PropTypes.bool,
is_editable: PropTypes.bool,
}),
).isRequired,
deleteRequest: PropTypes.shape({
loading: PropTypes.bool,
loaded: PropTypes.bool,
}).isRequired,
pathname: PropTypes.string.isRequired,
};
/**
* Constructor
* @method constructor
* @param {Object} props Component properties
* @constructs Comments
*/
constructor(props) {
super(props);
this.onDelete = this.onDelete.bind(this);
this.onEdit = this.onEdit.bind(this);
this.onEditOk = this.onEditOk.bind(this);
this.onEditCancel = this.onEditCancel.bind(this);
this.state = {
showEdit: false,
editId: null,
editText: null,
isClient: false,
};
}
/**
* Component did mount
* @method componentDidMount
* @returns {undefined}
*/
componentDidMount() {
this.props.searchContent('', {
portal_type: 'Discussion Item',
fullobjects: true,
});
this.setState({ isClient: true });
}
/**
* Component will receive props
* @method componentWillReceiveProps
* @param {Object} nextProps Next properties
* @returns {undefined}
*/
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.deleteRequest.loading && nextProps.deleteRequest.loaded) {
this.props.searchContent('', {
portal_type: 'Discussion Item',
fullobjects: true,
});
}
}
/**
* Delete handler
* @method onDelete
* @param {Object} event Event object.
* @param {string} value Delete value.
* @returns {undefined}
*/
onDelete(event, { value }) {
this.props.deleteComment(value);
}
/**
* Edit handler
* @method onEdit
* @param {Object} event Event object.
* @param {string} value Delete value.
* @returns {undefined}
*/
onEdit(event, { value }) {
this.setState({
showEdit: true,
editId: value.id,
editText: value.text,
});
}
/**
* On edit ok
* @method onEditOk
* @returns {undefined}
*/
onEditOk() {
this.setState({
showEdit: false,
editId: null,
editText: null,
});
this.props.searchContent('', {
portal_type: 'Discussion Item',
fullobjects: true,
});
}
/**
* On edit cancel
* @method onEditCancel
* @returns {undefined}
*/
onEditCancel() {
this.setState({
showEdit: false,
editId: null,
editText: null,
});
}
/**
* Back/Cancel handler
* @method onCancel
* @returns {undefined}
*/
onCancel() {
this.props.history.push(getParentUrl(this.props.pathname));
}
/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
return (
<div id="page-moderate-comments">
<CommentEditModal
open={this.state.showEdit}
onCancel={this.onEditCancel}
onOk={this.onEditOk}
id={this.state.editId}
text={this.state.editText}
/>
<Helmet
title={this.props.intl.formatMessage(messages.ModerateComments)}
/>
<Container>
<article id="content">
<header>
<h1 className="documentFirstHeading">
<FormattedMessage
id="Moderate comments"
defaultMessage="Moderate comments"
/>
</h1>
</header>
<section id="content-core">
<Table compact singleLine striped>
<Table.Header>
<Table.Row>
<Table.HeaderCell>
<FormattedMessage
id="Commenter"
defaultMessage="Commenter"
/>
</Table.HeaderCell>
<Table.HeaderCell>
<FormattedMessage id="Date" defaultMessage="Date" />
</Table.HeaderCell>
<Table.HeaderCell>
<FormattedMessage id="Comment" defaultMessage="Comment" />
</Table.HeaderCell>
<Table.HeaderCell>
<FormattedMessage id="Action" defaultMessage="Action" />
</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{this.props.items.map((item) => (
<Table.Row key={item['@id']}>
<Table.Cell>{item.author_name}</Table.Cell>
<Table.Cell>
<FormattedRelativeDate date={item.creation_date} />
</Table.Cell>
<Table.Cell>{item.text.data}</Table.Cell>
<Table.Cell>
{item.is_editable && (
<Button
onClick={this.onEdit}
value={{ id: item['@id'], text: item.text.data }}
primary
>
<FormattedMessage id="Edit" defaultMessage="Edit" />
</Button>
)}
{item.is_deletable && (
<Button
onClick={this.onDelete}
value={item['@id']}
color="red"
>
<FormattedMessage
id="Delete"
defaultMessage="Delete"
/>
</Button>
)}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</section>
</article>
</Container>
{this.state.isClient &&
createPortal(
<Toolbar
pathname={this.props.pathname}
hideDefaultViewButtons
inner={
<Link className="item" to="#" onClick={() => this.onCancel()}>
<Icon
name={backSVG}
className="contents circled"
size="30px"
title={this.props.intl.formatMessage(messages.back)}
/>
</Link>
}
/>,
document.getElementById('toolbar'),
)}
</div>
);
}
}
export default compose(
injectIntl,
connect(
(state, props) => ({
items: state.search.items,
deleteRequest: state.comments.delete,
pathname: props.location.pathname,
}),
{ deleteComment, searchContent },
),
)(ModerateComments);