mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 17:45:56 +08:00
@@ -7,6 +7,7 @@ export {default as connect} from 'coral-framework/hocs/connect';
|
||||
export {default as withEmit} from 'coral-framework/hocs/withEmit';
|
||||
export {
|
||||
withIgnoreUser,
|
||||
withSetUserStatus,
|
||||
withStopIgnoringUser,
|
||||
withSetCommentStatus,
|
||||
} from 'coral-framework/graphql/mutations';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {OPEN_MENU, CLOSE_MENU} from './constants';
|
||||
import {OPEN_MENU, CLOSE_MENU, OPEN_BAN_DIALOG, CLOSE_BAN_DIALOG} from './constants';
|
||||
|
||||
export const openMenu = (id) => ({
|
||||
type: OPEN_MENU,
|
||||
@@ -8,3 +8,14 @@ export const openMenu = (id) => ({
|
||||
export const closeMenu = () => ({
|
||||
type: CLOSE_MENU,
|
||||
});
|
||||
|
||||
export const openBanDialog = ({commentId, authorId, commentStatus}) => ({
|
||||
type: OPEN_BAN_DIALOG,
|
||||
commentId,
|
||||
authorId,
|
||||
commentStatus
|
||||
});
|
||||
|
||||
export const closeBanDialog = () => ({
|
||||
type: CLOSE_BAN_DIALOG,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import styles from './styles.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import {Icon} from 'plugin-api/beta/client/components/ui';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({onBanUser}) => (
|
||||
<button
|
||||
className={cn(styles.button, 'talk-plugin-moderation-actions-reject')}
|
||||
onClick={onBanUser} >
|
||||
<Icon name="block" className={styles.icon} />
|
||||
{t('talk-plugin-moderation-actions.ban_user')}
|
||||
</button>
|
||||
);
|
||||
@@ -0,0 +1,38 @@
|
||||
.dialog {
|
||||
border: none;
|
||||
box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
text-align: right;
|
||||
margin: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cancel, .confirm {
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.copy {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: 20px;
|
||||
line-height: 14px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #6b6b6b;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import styles from './BanUserDialog.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import {Dialog, Button} from 'plugin-api/beta/client/components/ui';
|
||||
|
||||
export default ({showBanDialog, closeBanDialog, banUser}) => (
|
||||
<Dialog open={showBanDialog} className={styles.dialog}>
|
||||
<span className={styles.close} onClick={closeBanDialog}>×</span>
|
||||
<h2>{t('talk-plugin-moderation-actions.ban_user_dialog_headline')}</h2>
|
||||
<h3>{t('talk-plugin-moderation-actions.ban_user_dialog_sub')}</h3>
|
||||
<p className={styles.copy}>
|
||||
{t('talk-plugin-moderation-actions.ban_user_dialog_copy')}
|
||||
</p>
|
||||
<div className={styles.buttons}>
|
||||
<Button cStyle="cancel" onClick={closeBanDialog} className={styles.cancel} raised>
|
||||
{t('talk-plugin-moderation-actions.ban_user_dialog_cancel')}
|
||||
</Button>
|
||||
<Button cStyle="black" onClick={banUser} className={styles.confirm} raised>
|
||||
{t('talk-plugin-moderation-actions.ban_user_dialog_yes')}
|
||||
</Button>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
@@ -6,11 +6,12 @@ import {Icon} from 'plugin-api/beta/client/components/ui';
|
||||
import ClickOutside from 'coral-framework/components/ClickOutside';
|
||||
import RejectCommentAction from '../containers/RejectCommentAction';
|
||||
import ApproveCommentAction from '../containers/ApproveCommentAction';
|
||||
import BanUserAction from '../containers/BanUserAction';
|
||||
import {Slot} from 'plugin-api/beta/client/components';
|
||||
|
||||
export default class ModerationActions extends React.Component {
|
||||
render() {
|
||||
const {comment, asset, data, menuVisible, toogleMenu, hideMenu} = this.props;
|
||||
const {comment, root, asset, data, menuVisible, toogleMenu, hideMenu} = this.props;
|
||||
|
||||
return(
|
||||
<ClickOutside onClickOutside={hideMenu}>
|
||||
@@ -29,6 +30,7 @@ export default class ModerationActions extends React.Component {
|
||||
/>
|
||||
<ApproveCommentAction comment={comment} hideMenu={hideMenu} />
|
||||
<RejectCommentAction comment={comment} hideMenu={hideMenu} />
|
||||
<BanUserAction comment={comment} root={root} hideMenu={hideMenu} />
|
||||
</Menu>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,3 +2,5 @@ const prefix = 'TALK_MODERATION_ACTIONS';
|
||||
|
||||
export const OPEN_MENU = `${prefix}_OPEN_MENU`;
|
||||
export const CLOSE_MENU = `${prefix}_CLOSE_MENU`;
|
||||
export const OPEN_BAN_DIALOG = `${prefix}_OPEN_BAN_DIALOG`;
|
||||
export const CLOSE_BAN_DIALOG = `${prefix}_CLOSE_BAN_DIALOG`;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import {compose} from 'react-apollo';
|
||||
import {openBanDialog} from '../actions';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import BanUserAction from '../components/BanUserAction';
|
||||
import {connect} from 'plugin-api/beta/client/hocs';
|
||||
|
||||
class BanUserActionContainer extends React.Component {
|
||||
onBanUser = () => {
|
||||
this.props.openBanDialog({
|
||||
commentId: this.props.comment.id,
|
||||
commentStatus: this.props.comment.status,
|
||||
authorId: this.props.comment.user.id
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {root: {me}, comment} = this.props;
|
||||
return (me.id !== comment.user.id) ?
|
||||
<BanUserAction
|
||||
onBanUser={this.onBanUser}
|
||||
comment={this.props.comment}
|
||||
/> : null;
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({
|
||||
openBanDialog
|
||||
}, dispatch);
|
||||
|
||||
const enhance = compose(
|
||||
connect(null, mapDispatchToProps)
|
||||
);
|
||||
|
||||
export default enhance(BanUserActionContainer);
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
import React from 'react';
|
||||
import {compose} from 'react-apollo';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {closeBanDialog, closeMenu} from '../actions';
|
||||
import {notify} from 'plugin-api/beta/client/actions/notification';
|
||||
import {connect, withSetCommentStatus, withSetUserStatus} from 'plugin-api/beta/client/hocs';
|
||||
import {getErrorMessages} from 'plugin-api/beta/client/utils';
|
||||
import BanUserDialog from '../components/BanUserDialog';
|
||||
|
||||
class BanUserDialogContainer extends React.Component {
|
||||
|
||||
banUser = async () => {
|
||||
const {
|
||||
notify,
|
||||
authorId,
|
||||
commentId,
|
||||
commentStatus,
|
||||
closeMenu,
|
||||
closeBanDialog,
|
||||
setCommentStatus,
|
||||
setUserStatus
|
||||
} = this.props;
|
||||
|
||||
try {
|
||||
await setUserStatus({
|
||||
userId: authorId,
|
||||
status: 'BANNED'
|
||||
});
|
||||
|
||||
closeMenu();
|
||||
closeBanDialog();
|
||||
|
||||
if (commentStatus !== 'REJECTED') {
|
||||
await setCommentStatus({
|
||||
commentId: commentId,
|
||||
status: 'REJECTED'
|
||||
});
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
notify('error', getErrorMessages(err));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<BanUserDialog
|
||||
banUser={this.banUser}
|
||||
showBanDialog={this.props.showBanDialog}
|
||||
closeBanDialog={this.props.closeBanDialog}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({talkPluginModerationActions: state}) => ({
|
||||
showBanDialog: state.showBanDialog,
|
||||
commentId: state.commentId,
|
||||
authorId: state.authorId
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({
|
||||
notify,
|
||||
closeBanDialog,
|
||||
closeMenu
|
||||
}, dispatch);
|
||||
|
||||
const enhance = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withSetCommentStatus,
|
||||
withSetUserStatus
|
||||
);
|
||||
|
||||
export default enhance(BanUserDialogContainer);
|
||||
@@ -47,9 +47,9 @@ class ModerationActionsContainer extends React.Component {
|
||||
root={this.props.root}
|
||||
asset={this.props.asset}
|
||||
comment={this.props.comment}
|
||||
menuVisible={this.props.showMenuForComment === this.props.comment.id}
|
||||
toogleMenu={this.toogleMenu}
|
||||
hideMenu={this.hideMenu}
|
||||
menuVisible={this.props.showMenuForComment === this.props.comment.id}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,13 @@ const mapDispatchToProps = (dispatch) =>
|
||||
const enhance = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withFragments({
|
||||
root: gql`
|
||||
fragment TalkModerationActions_root on RootQuery {
|
||||
me {
|
||||
id
|
||||
}
|
||||
}`
|
||||
,
|
||||
asset: gql`
|
||||
fragment TalkModerationActions_asset on Asset {
|
||||
id
|
||||
@@ -77,6 +84,9 @@ const enhance = compose(
|
||||
fragment TalkModerationActions_comment on Comment {
|
||||
id
|
||||
status
|
||||
user {
|
||||
id
|
||||
}
|
||||
tags {
|
||||
tag {
|
||||
name
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import ModerationActions from './containers/ModerationActions';
|
||||
import BanUserDialog from './containers/BanUserDialog';
|
||||
import translations from './translations.yml';
|
||||
import reducer from './reducer';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
embed: [BanUserDialog],
|
||||
commentInfoBar: [ModerationActions],
|
||||
},
|
||||
reducer,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import {OPEN_MENU, CLOSE_MENU} from './constants';
|
||||
import {OPEN_MENU, CLOSE_MENU, OPEN_BAN_DIALOG, CLOSE_BAN_DIALOG} from './constants';
|
||||
|
||||
const initialState = {
|
||||
showMenuForComment: null,
|
||||
showBanDialog: false,
|
||||
authorId: null,
|
||||
commentId: null,
|
||||
commentStatus: null
|
||||
};
|
||||
|
||||
export default function reducer(state = initialState, action) {
|
||||
@@ -16,6 +20,22 @@ export default function reducer(state = initialState, action) {
|
||||
...state,
|
||||
showMenuForComment: null
|
||||
};
|
||||
case OPEN_BAN_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
showBanDialog: true,
|
||||
authorId: action.authorId,
|
||||
commentId: action.commentId,
|
||||
commentStatus: action.commentStatus
|
||||
};
|
||||
case CLOSE_BAN_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
showBanDialog: false,
|
||||
authorId: null,
|
||||
commentId: null,
|
||||
commentStatus: null
|
||||
};
|
||||
default :
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,22 @@ en:
|
||||
approve_comment: "Approve"
|
||||
approved_comment: "Approved"
|
||||
moderation_actions: "Moderation Actions"
|
||||
ban_user: "Ban User"
|
||||
ban_user_dialog_sub: "Are you sure you would like to ban this user?"
|
||||
ban_user_dialog_copy: "Note: Banning this user will also place this comment in the Rejected queue."
|
||||
ban_user_dialog_cancel: "Cancel"
|
||||
ban_user_dialog_yes: "Yes. Ban user"
|
||||
ban_user_dialog_headline: "Ban User?"
|
||||
|
||||
es:
|
||||
talk-plugin-moderation-actions:
|
||||
reject_comment: "Rechazar"
|
||||
approve_comment: "Aprobar"
|
||||
approved_comment: "Aprobado"
|
||||
moderation_actions: "Acciones de Moderación"
|
||||
moderation_actions: "Acciones de Moderación"
|
||||
ban_user: "Banear usuario"
|
||||
ban_user_dialog_sub: "Está seguro de querer banear a este usuario?"
|
||||
ban_user_dialog_copy: "Nota: Baneando a este usuario pondrá el comentario en la cola de comentarios Rechazados."
|
||||
ban_user_dialog_cancel: "Cancelar"
|
||||
ban_user_dialog_yes: "Si. Banear usuario"
|
||||
ban_user_dialog_headline: "Banear Usuario?"
|
||||
Reference in New Issue
Block a user