diff --git a/plugins/talk-plugin-moderation-actions/client/actions.js b/plugins/talk-plugin-moderation-actions/client/actions.js new file mode 100644 index 000000000..4cc3a7dec --- /dev/null +++ b/plugins/talk-plugin-moderation-actions/client/actions.js @@ -0,0 +1,10 @@ +import {OPEN_TOOLTIP, CLOSE_TOOLTIP} from './constants'; + +export const openTooltip = (id) => ({ + type: OPEN_TOOLTIP, + id, +}); + +export const closeTooltip = () => ({ + type: CLOSE_TOOLTIP, +}); diff --git a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js index 3a3b54156..016c14728 100644 --- a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js +++ b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js @@ -9,39 +9,19 @@ 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, tooltipVisible, toogleTooltip, hideTooltip} = this.props; return( - +
- - {tooltip ? : + + {tooltipVisible ? : } - {tooltip && ( + + {tooltipVisible && ( ({ - user: auth.user +class ModerationActionsContainer extends React.Component { + + shouldComponentUpdate(nextProps) { + + // Specifically handle `showTooltipForComment` if it is the only change. + const changes = getShallowChanges(this.props, nextProps); + if (changes.length === 1 && changes[0] === 'showTooltipForComment') { + const commentId = this.props.comment.id; + if ( + commentId !== this.props.showTooltipForComment && + commentId !== nextProps.showTooltipForComment + ) { + return false; + } + } + + // Prevent Slot from rerendering when no props has shallowly changed. + return changes.length !== 0; + } + + toogleTooltip = () => { + if (this.props.showTooltipForComment === this.props.comment.id) { + this.props.closeTooltip(); + } else { + this.props.openTooltip(this.props.comment.id); + } + } + + hideTooltip = () => { + if (this.props.showTooltipForComment === this.props.comment.id) { + this.props.closeTooltip(); + } + } + + render() { + return ; + } +} + +const mapStateToProps = ({auth, talkPluginModerationActions: state}) => ({ + user: auth.user, + showTooltipForComment: state.showTooltipForComment, }); +const mapDispatchToProps = (dispatch) => + bindActionCreators({ + openTooltip, + closeTooltip, + }, 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/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..ac95ed60f --- /dev/null +++ b/plugins/talk-plugin-moderation-actions/client/reducer.js @@ -0,0 +1,23 @@ +import {OPEN_TOOLTIP, CLOSE_TOOLTIP} from './constants'; + +const initialState = { + showTooltipForComment: null, +}; + +export default function reducer(state = initialState, action) { + switch (action.type) { + case OPEN_TOOLTIP: + return { + ...state, + showTooltipForComment: action.id, + }; + case CLOSE_TOOLTIP: + return { + ...state, + showTooltipForComment: null, + contentSlot: null, + }; + default : + return state; + } +}