diff --git a/plugins/talk-plugin-featured-comments/client/components/Comment.js b/plugins/talk-plugin-featured-comments/client/components/Comment.js index 1c2045110..779844177 100644 --- a/plugins/talk-plugin-featured-comments/client/components/Comment.js +++ b/plugins/talk-plugin-featured-comments/client/components/Comment.js @@ -5,7 +5,7 @@ import {t, timeago} from 'plugin-api/beta/client/services'; import {Slot, CommentAuthorName} from 'plugin-api/beta/client/components'; import {Icon} from 'plugin-api/beta/client/components/ui'; import {pluginName} from '../../package.json'; -import Button from './Button'; +import FeaturedButton from '../containers/FeaturedButton'; class Comment extends React.Component { @@ -50,7 +50,7 @@ class Comment extends React.Component { inline /> - + isApproved(status) ? ( + + + {t('talk-plugin-moderation-actions.approved_comment')} + + ) : ( + + ) ); diff --git a/plugins/talk-plugin-moderation-actions/client/components/Tooltip.css b/plugins/talk-plugin-moderation-actions/client/components/Menu.css similarity index 95% rename from plugins/talk-plugin-moderation-actions/client/components/Tooltip.css rename to plugins/talk-plugin-moderation-actions/client/components/Menu.css index def7cac82..3ef43d82e 100644 --- a/plugins/talk-plugin-moderation-actions/client/components/Tooltip.css +++ b/plugins/talk-plugin-moderation-actions/client/components/Menu.css @@ -1,4 +1,4 @@ -.tooltip { +.menu { background-color: white; border: solid 1px #999; border-radius: 3px; @@ -14,7 +14,7 @@ color: #616161; } -.tooltip::before{ +.menu::before{ content: ''; border: 10px solid transparent; border-top-color: #999; @@ -24,7 +24,7 @@ transform: rotate(180deg); } -.tooltip::after{ +.menu::after{ content: ''; border: 10px solid transparent; border-top-color: white; diff --git a/plugins/talk-plugin-moderation-actions/client/components/Tooltip.js b/plugins/talk-plugin-moderation-actions/client/components/Menu.js similarity index 77% rename from plugins/talk-plugin-moderation-actions/client/components/Tooltip.js rename to plugins/talk-plugin-moderation-actions/client/components/Menu.js index db7e56c1e..470349b69 100644 --- a/plugins/talk-plugin-moderation-actions/client/components/Tooltip.js +++ b/plugins/talk-plugin-moderation-actions/client/components/Menu.js @@ -1,10 +1,10 @@ import React from 'react'; import cn from 'classnames'; -import styles from './Tooltip.css'; +import styles from './Menu.css'; import {t} from 'plugin-api/beta/client/services'; export default ({className = '', children}) => ( -
+

{t('talk-plugin-moderation-actions.moderation_actions')}

diff --git a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js index 3a3b54156..a4a753d60 100644 --- a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js +++ b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js @@ -1,6 +1,6 @@ import React from 'react'; import cn from 'classnames'; -import Tooltip from './Tooltip'; +import Menu from './Menu'; import styles from './ModerationActions.css'; import {Icon} from 'plugin-api/beta/client/components/ui'; import ClickOutside from 'coral-framework/components/ClickOutside'; @@ -9,51 +9,27 @@ import ApproveCommentAction from '../containers/ApproveCommentAction'; import {Slot} from 'plugin-api/beta/client/components'; export default class ModerationActions extends React.Component { - constructor() { - super(); - - this.state = { - tooltip: false - }; - } - - toogleTooltip = () => { - const {tooltip} = this.state; - this.setState({ - tooltip: !tooltip - }); - } - - hideTooltip = () => { - this.setState({ - tooltip: false - }); - } - render() { - const {tooltip} = this.state; - const {comment, asset, data} = this.props; + const {comment, asset, data, menuVisible, toogleMenu, hideMenu} = this.props; return( - +
- - {tooltip ? : + + {menuVisible ? : } - {tooltip && ( - - + {menuVisible && ( + - - - - + + + )}
diff --git a/plugins/talk-plugin-moderation-actions/client/components/styles.css b/plugins/talk-plugin-moderation-actions/client/components/styles.css index 12ae4bad5..d5278a462 100644 --- a/plugins/talk-plugin-moderation-actions/client/components/styles.css +++ b/plugins/talk-plugin-moderation-actions/client/components/styles.css @@ -12,10 +12,10 @@ width: 100%; text-align: left; letter-spacing: 0.3px; +} - &:hover { - background-color: #D8D8D8; - } +.button:not(.approved):hover { + background-color: #D8D8D8; } .icon { @@ -24,6 +24,8 @@ } .approved { + display: inline-block; color: #519954; font-weight: bold; + padding: 6px; } \ No newline at end of file diff --git a/plugins/talk-plugin-moderation-actions/client/constants.js b/plugins/talk-plugin-moderation-actions/client/constants.js new file mode 100644 index 000000000..de3d5c909 --- /dev/null +++ b/plugins/talk-plugin-moderation-actions/client/constants.js @@ -0,0 +1,4 @@ +const prefix = 'TALK_MODERATION_ACTIONS'; + +export const OPEN_MENU = `${prefix}_OPEN_MENU`; +export const CLOSE_MENU = `${prefix}_CLOSE_MENU`; diff --git a/plugins/talk-plugin-moderation-actions/client/containers/ApproveCommentAction.js b/plugins/talk-plugin-moderation-actions/client/containers/ApproveCommentAction.js index c75711a56..4c4a457a2 100644 --- a/plugins/talk-plugin-moderation-actions/client/containers/ApproveCommentAction.js +++ b/plugins/talk-plugin-moderation-actions/client/containers/ApproveCommentAction.js @@ -1,28 +1,27 @@ import React from 'react'; +import {compose} from 'react-apollo'; +import {bindActionCreators} from 'redux'; import {getErrorMessages} from 'plugin-api/beta/client/utils'; -import {withSetCommentStatus} from 'plugin-api/beta/client/hocs'; import {notify} from 'plugin-api/beta/client/actions/notification'; import ApproveCommentAction from '../components/ApproveCommentAction'; -import isNil from 'lodash/isNil'; +import {connect, withSetCommentStatus} from 'plugin-api/beta/client/hocs'; class ApproveCommentActionContainer extends React.Component { approveComment = async () => { - const {setCommentStatus, comment} = this.props; + const {setCommentStatus, comment, hideMenu, notify} = this.props; try { - const result = await setCommentStatus({ + await setCommentStatus({ commentId: comment.id, status: 'ACCEPTED' }); - - if (!isNil(result.data.setCommentStatus)) { - throw result.data.setCommentStatus.errors; - } - - } catch (err) { + } + catch(err) { notify('error', getErrorMessages(err)); } + + hideMenu(); } render() { @@ -30,4 +29,14 @@ class ApproveCommentActionContainer extends React.Component { } } -export default withSetCommentStatus(ApproveCommentActionContainer); +const mapDispatchToProps = (dispatch) => + bindActionCreators({ + notify + }, dispatch); + +const enhance = compose( + connect(null, mapDispatchToProps), + withSetCommentStatus +); + +export default enhance(ApproveCommentActionContainer); diff --git a/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js b/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js index ffb711e18..984c7f57a 100644 --- a/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js +++ b/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js @@ -1,14 +1,72 @@ +import React from 'react'; +import {bindActionCreators} from 'redux'; import {gql, compose} from 'react-apollo'; +import {openMenu, closeMenu} from '../actions'; import {can} from 'plugin-api/beta/client/services'; +import {getShallowChanges} from 'plugin-api/beta/client/utils'; import ModerationActions from '../components/ModerationActions'; import {connect, excludeIf, withFragments} from 'plugin-api/beta/client/hocs'; -const mapStateToProps = ({auth}) => ({ - user: auth.user +class ModerationActionsContainer extends React.Component { + + shouldComponentUpdate(nextProps) { + + // Specifically handle `showMenuForComment` if it is the only change. + const changes = getShallowChanges(this.props, nextProps); + if (changes.length === 1 && changes[0] === 'showMenuForComment') { + const commentId = this.props.comment.id; + if ( + commentId !== this.props.showMenuForComment && + commentId !== nextProps.showMenuForComment + ) { + return false; + } + } + + // Prevent Slot from rerendering when no props has shallowly changed. + return changes.length !== 0; + } + + toogleMenu = () => { + if (this.props.showMenuForComment === this.props.comment.id) { + this.props.closeMenu(); + } else { + this.props.openMenu(this.props.comment.id); + } + } + + hideMenu = () => { + if (this.props.showMenuForComment === this.props.comment.id) { + this.props.closeMenu(); + } + } + + render() { + return ; + } +} + +const mapStateToProps = ({auth, talkPluginModerationActions: state}) => ({ + user: auth.user, + showMenuForComment: state.showMenuForComment, }); +const mapDispatchToProps = (dispatch) => + bindActionCreators({ + openMenu, + closeMenu, + }, dispatch); + const enhance = compose( - connect(mapStateToProps), + connect(mapStateToProps, mapDispatchToProps), withFragments({ asset: gql` fragment TalkModerationActions_asset on Asset { @@ -29,4 +87,4 @@ const enhance = compose( excludeIf((props) => !can(props.user, 'MODERATE_COMMENTS')), ); -export default enhance(ModerationActions); +export default enhance(ModerationActionsContainer); diff --git a/plugins/talk-plugin-moderation-actions/client/containers/RejectCommentAction.js b/plugins/talk-plugin-moderation-actions/client/containers/RejectCommentAction.js index 5497d0e8e..e744eb1d7 100644 --- a/plugins/talk-plugin-moderation-actions/client/containers/RejectCommentAction.js +++ b/plugins/talk-plugin-moderation-actions/client/containers/RejectCommentAction.js @@ -1,28 +1,27 @@ import React from 'react'; +import {compose} from 'react-apollo'; +import {bindActionCreators} from 'redux'; import {getErrorMessages} from 'plugin-api/beta/client/utils'; -import {withSetCommentStatus} from 'plugin-api/beta/client/hocs'; import {notify} from 'plugin-api/beta/client/actions/notification'; import RejectCommentAction from '../components/RejectCommentAction'; -import isNil from 'lodash/isNil'; +import {connect, withSetCommentStatus} from 'plugin-api/beta/client/hocs'; class RejectCommentActionContainer extends React.Component { rejectComment = async () => { - const {setCommentStatus, comment} = this.props; + const {setCommentStatus, comment, hideMenu, notify} = this.props; try { - const result = await setCommentStatus({ + await setCommentStatus({ commentId: comment.id, status: 'REJECTED' }); - - if (!isNil(result.data.setCommentStatus)) { - throw result.data.setCommentStatus.errors; - } - - } catch (err) { + } + catch(err) { notify('error', getErrorMessages(err)); } + + hideMenu(); } render() { @@ -30,4 +29,14 @@ class RejectCommentActionContainer extends React.Component { } } -export default withSetCommentStatus(RejectCommentActionContainer); +const mapDispatchToProps = (dispatch) => + bindActionCreators({ + notify + }, dispatch); + +const enhance = compose( + connect(null, mapDispatchToProps), + withSetCommentStatus +); + +export default enhance(RejectCommentActionContainer); diff --git a/plugins/talk-plugin-moderation-actions/client/index.js b/plugins/talk-plugin-moderation-actions/client/index.js index 3343505f3..fefcac710 100644 --- a/plugins/talk-plugin-moderation-actions/client/index.js +++ b/plugins/talk-plugin-moderation-actions/client/index.js @@ -1,9 +1,11 @@ import ModerationActions from './containers/ModerationActions'; import translations from './translations.yml'; +import reducer from './reducer'; export default { slots: { commentInfoBar: [ModerationActions], }, + reducer, translations }; diff --git a/plugins/talk-plugin-moderation-actions/client/reducer.js b/plugins/talk-plugin-moderation-actions/client/reducer.js new file mode 100644 index 000000000..d8531708b --- /dev/null +++ b/plugins/talk-plugin-moderation-actions/client/reducer.js @@ -0,0 +1,22 @@ +import {OPEN_MENU, CLOSE_MENU} from './constants'; + +const initialState = { + showMenuForComment: null, +}; + +export default function reducer(state = initialState, action) { + switch (action.type) { + case OPEN_MENU: + return { + ...state, + showMenuForComment: action.id + }; + case CLOSE_MENU: + return { + ...state, + showMenuForComment: null + }; + default : + return state; + } +}