mirror of
https://github.com/wassname/talk.git
synced 2026-08-18 12:30:39 +08:00
replaced eslint:recommended with prettier
This commit is contained in:
@@ -2,19 +2,22 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import {can} from 'coral-framework/services/perms';
|
||||
import {forEachError} from 'coral-framework/utils';
|
||||
import { can } from 'coral-framework/services/perms';
|
||||
import { forEachError } from 'coral-framework/utils';
|
||||
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
import {connect} from 'react-redux';
|
||||
import {CommentForm} from './CommentForm';
|
||||
import { connect } from 'react-redux';
|
||||
import { CommentForm } from './CommentForm';
|
||||
|
||||
export const name = 'talk-plugin-commentbox';
|
||||
|
||||
const notifyReasons = ['LINKS', 'TRUST'];
|
||||
|
||||
function shouldNotify(actions = []) {
|
||||
return actions.some(({__typename, reason}) => __typename === 'FlagAction' && notifyReasons.includes(reason));
|
||||
return actions.some(
|
||||
({ __typename, reason }) =>
|
||||
__typename === 'FlagAction' && notifyReasons.includes(reason)
|
||||
);
|
||||
}
|
||||
|
||||
// Given a newly posted comment's status, show a notification to the user
|
||||
@@ -24,7 +27,8 @@ export const notifyForNewCommentStatus = (notify, comment, actions) => {
|
||||
notify('error', t('comment_box.comment_post_banned_word'));
|
||||
} else if (
|
||||
comment.status === 'PREMOD' ||
|
||||
comment.status === 'SYSTEM_WITHHELD' && shouldNotify(actions)) {
|
||||
(comment.status === 'SYSTEM_WITHHELD' && shouldNotify(actions))
|
||||
) {
|
||||
notify('success', t('comment_box.comment_post_notif_premod'));
|
||||
}
|
||||
};
|
||||
@@ -43,8 +47,8 @@ class CommentBox extends React.Component {
|
||||
|
||||
hooks: {
|
||||
preSubmit: [],
|
||||
postSubmit: []
|
||||
}
|
||||
postSubmit: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -67,21 +71,21 @@ class CommentBox extends React.Component {
|
||||
asset_id: assetId,
|
||||
parent_id: parentId,
|
||||
body: this.state.body,
|
||||
...this.props.commentBox
|
||||
...this.props.commentBox,
|
||||
};
|
||||
|
||||
// Execute preSubmit Hooks
|
||||
this.state.hooks.preSubmit.forEach((hook) => hook(input));
|
||||
this.setState({loadingState: 'loading'});
|
||||
this.state.hooks.preSubmit.forEach(hook => hook(input));
|
||||
this.setState({ loadingState: 'loading' });
|
||||
|
||||
postComment(input, 'comments')
|
||||
.then(({data}) => {
|
||||
this.setState({loadingState: 'success', body: ''});
|
||||
.then(({ data }) => {
|
||||
this.setState({ loadingState: 'success', body: '' });
|
||||
const postedComment = data.createComment.comment;
|
||||
const actions = data.createComment.actions;
|
||||
|
||||
// Execute postSubmit Hooks
|
||||
this.state.hooks.postSubmit.forEach((hook) => hook(data));
|
||||
this.state.hooks.postSubmit.forEach(hook => hook(data));
|
||||
|
||||
notifyForNewCommentStatus(notify, postedComment, actions);
|
||||
|
||||
@@ -89,100 +93,104 @@ class CommentBox extends React.Component {
|
||||
commentPostedHandler();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.setState({loadingState: 'error'});
|
||||
forEachError(err, ({msg}) => notify('error', msg));
|
||||
.catch(err => {
|
||||
this.setState({ loadingState: 'error' });
|
||||
forEachError(err, ({ msg }) => notify('error', msg));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleBodyChange = (body) => {
|
||||
this.setState({body});
|
||||
}
|
||||
handleBodyChange = body => {
|
||||
this.setState({ body });
|
||||
};
|
||||
|
||||
registerHook = (hookType = '', hook = () => {}) => {
|
||||
if (typeof hook !== 'function') {
|
||||
return console.warn(`Hooks must be functions. Please check your ${hookType} hooks`);
|
||||
return console.warn(
|
||||
`Hooks must be functions. Please check your ${hookType} hooks`
|
||||
);
|
||||
} else if (typeof hookType === 'string') {
|
||||
this.setState((state) => ({
|
||||
this.setState(state => ({
|
||||
hooks: {
|
||||
...state.hooks,
|
||||
[hookType]: [
|
||||
...state.hooks[hookType],
|
||||
hook
|
||||
]
|
||||
}
|
||||
[hookType]: [...state.hooks[hookType], hook],
|
||||
},
|
||||
}));
|
||||
|
||||
return {
|
||||
hookType,
|
||||
hook
|
||||
hook,
|
||||
};
|
||||
|
||||
} else {
|
||||
return console.warn('hookTypes must be a string. Please check your hooks');
|
||||
return console.warn(
|
||||
'hookTypes must be a string. Please check your hooks'
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unregisterHook = (hookData) => {
|
||||
const {hookType, hook} = hookData;
|
||||
unregisterHook = hookData => {
|
||||
const { hookType, hook } = hookData;
|
||||
|
||||
this.setState((state) => {
|
||||
this.setState(state => {
|
||||
let newHooks = state.hooks[newHooks];
|
||||
const idx = state.hooks[hookType].indexOf(hook);
|
||||
|
||||
if (idx !== -1) {
|
||||
newHooks = [
|
||||
...state.hooks[hookType].slice(0, idx),
|
||||
...state.hooks[hookType].slice(idx + 1)
|
||||
...state.hooks[hookType].slice(idx + 1),
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
hooks: {
|
||||
...state.hooks,
|
||||
[hookType]: newHooks
|
||||
}
|
||||
[hookType]: newHooks,
|
||||
},
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const {isReply, maxCharCount} = this.props;
|
||||
let {onCancel} = this.props;
|
||||
render() {
|
||||
const { isReply, maxCharCount } = this.props;
|
||||
let { onCancel } = this.props;
|
||||
|
||||
if (isReply && typeof onCancel !== 'function') {
|
||||
console.warn('the CommentBox component should have a onCancel callback defined if it lives in a Reply');
|
||||
console.warn(
|
||||
'the CommentBox component should have a onCancel callback defined if it lives in a Reply'
|
||||
);
|
||||
onCancel = () => {};
|
||||
}
|
||||
|
||||
return <div>
|
||||
<CommentForm
|
||||
defaultValue={this.props.defaultValue}
|
||||
bodyLabel={isReply ? t('comment_box.reply') : t('comment.comment')}
|
||||
maxCharCount={maxCharCount}
|
||||
charCountEnable={this.props.charCountEnable}
|
||||
bodyPlaceholder={t('comment.comment')}
|
||||
bodyInputId={isReply ? 'replyText' : 'commentText'}
|
||||
body={this.state.body}
|
||||
buttonContainerStart={<Slot
|
||||
fill="commentInputDetailArea"
|
||||
registerHook={this.registerHook}
|
||||
unregisterHook={this.unregisterHook}
|
||||
isReply={isReply}
|
||||
inline
|
||||
/>}
|
||||
onBodyChange={this.handleBodyChange}
|
||||
loadingState={this.state.loadingState}
|
||||
onCancel={onCancel}
|
||||
onSubmit={this.handleSubmit}
|
||||
/>
|
||||
</div>;
|
||||
return (
|
||||
<div>
|
||||
<CommentForm
|
||||
defaultValue={this.props.defaultValue}
|
||||
bodyLabel={isReply ? t('comment_box.reply') : t('comment.comment')}
|
||||
maxCharCount={maxCharCount}
|
||||
charCountEnable={this.props.charCountEnable}
|
||||
bodyPlaceholder={t('comment.comment')}
|
||||
bodyInputId={isReply ? 'replyText' : 'commentText'}
|
||||
body={this.state.body}
|
||||
buttonContainerStart={
|
||||
<Slot
|
||||
fill="commentInputDetailArea"
|
||||
registerHook={this.registerHook}
|
||||
unregisterHook={this.unregisterHook}
|
||||
isReply={isReply}
|
||||
inline
|
||||
/>
|
||||
}
|
||||
onBodyChange={this.handleBodyChange}
|
||||
loadingState={this.state.loadingState}
|
||||
onCancel={onCancel}
|
||||
onSubmit={this.handleSubmit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CommentBox.propTypes = {
|
||||
|
||||
// Initial value for underlying comment body textarea
|
||||
defaultValue: PropTypes.string,
|
||||
charCountEnable: PropTypes.bool.isRequired,
|
||||
@@ -199,6 +207,6 @@ CommentBox.propTypes = {
|
||||
commentBox: PropTypes.object,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({commentBox}) => ({commentBox});
|
||||
const mapStateToProps = ({ commentBox }) => ({ commentBox });
|
||||
|
||||
export default connect(mapStateToProps, null)(CommentBox);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Button} from 'coral-ui';
|
||||
import { Button } from 'coral-ui';
|
||||
import cn from 'classnames';
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
|
||||
import {name} from './CommentBox';
|
||||
import { name } from './CommentBox';
|
||||
import styles from './styles.css';
|
||||
|
||||
import t from 'coral-framework/services/i18n';
|
||||
@@ -14,7 +14,6 @@ import t from 'coral-framework/services/i18n';
|
||||
*/
|
||||
export class CommentForm extends React.Component {
|
||||
static propTypes = {
|
||||
|
||||
charCountEnable: PropTypes.bool.isRequired,
|
||||
maxCharCount: PropTypes.number,
|
||||
|
||||
@@ -50,7 +49,7 @@ export class CommentForm extends React.Component {
|
||||
onCancel: PropTypes.func,
|
||||
state: PropTypes.string,
|
||||
loadingState: PropTypes.oneOf(['', 'loading', 'success', 'error']),
|
||||
}
|
||||
};
|
||||
static get defaultProps() {
|
||||
return {
|
||||
bodyLabel: t('comment_box.comment'),
|
||||
@@ -61,88 +60,111 @@ export class CommentForm extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
onBodyChange = (e) => {
|
||||
onBodyChange = e => {
|
||||
this.props.onBodyChange(e.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
onClickSubmit = () => {
|
||||
this.props.onSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
getButtonClassName = () => {
|
||||
switch (this.props.loadingState) {
|
||||
case 'loading':
|
||||
return cn(`${name}-button-loading`, styles.buttonLoading);
|
||||
case 'success':
|
||||
return cn(`${name}-button-success`, styles.buttonSuccess);
|
||||
case 'error':
|
||||
return cn(`${name}-button-error`, styles.buttonError);
|
||||
default:
|
||||
return '';
|
||||
case 'loading':
|
||||
return cn(`${name}-button-loading`, styles.buttonLoading);
|
||||
case 'success':
|
||||
return cn(`${name}-button-success`, styles.buttonSuccess);
|
||||
case 'error':
|
||||
return cn(`${name}-button-error`, styles.buttonError);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {maxCharCount, submitEnabled, cancelButtonClassName, submitButtonClassName, charCountEnable, body, loadingState} = this.props;
|
||||
const {
|
||||
maxCharCount,
|
||||
submitEnabled,
|
||||
cancelButtonClassName,
|
||||
submitButtonClassName,
|
||||
charCountEnable,
|
||||
body,
|
||||
loadingState,
|
||||
} = this.props;
|
||||
|
||||
const length = body.length;
|
||||
const isRespectingMaxCount = (length) => charCountEnable && maxCharCount && length > maxCharCount;
|
||||
const isRespectingMaxCount = length =>
|
||||
charCountEnable && maxCharCount && length > maxCharCount;
|
||||
const disableSubmitButton =
|
||||
!length ||
|
||||
body.trim().length === 0 ||
|
||||
isRespectingMaxCount(length) ||
|
||||
!submitEnabled({body}) ||
|
||||
!submitEnabled({ body }) ||
|
||||
loadingState === 'loading';
|
||||
const disableCancelButton = loadingState === 'loading';
|
||||
const disableTextArea = loadingState === 'loading';
|
||||
|
||||
return <div>
|
||||
<div className={`${name}-container`}>
|
||||
<label
|
||||
htmlFor={this.props.bodyInputId}
|
||||
className="screen-reader-text"
|
||||
aria-hidden={true}>
|
||||
{this.props.bodyLabel}
|
||||
</label>
|
||||
<textarea
|
||||
className={`${name}-textarea`}
|
||||
value={body}
|
||||
placeholder={this.props.bodyPlaceholder}
|
||||
id={this.props.bodyInputId}
|
||||
onChange={this.onBodyChange}
|
||||
rows={3}
|
||||
disabled={disableTextArea}
|
||||
/>
|
||||
<Slot fill='commentInputArea' />
|
||||
</div>
|
||||
{
|
||||
this.props.charCountEnable &&
|
||||
<div className={`${name}-char-count ${length > maxCharCount ? `${name}-char-max` : ''}`}>
|
||||
{maxCharCount && `${maxCharCount - length} ${t('comment_box.characters_remaining')}`}
|
||||
return (
|
||||
<div>
|
||||
<div className={`${name}-container`}>
|
||||
<label
|
||||
htmlFor={this.props.bodyInputId}
|
||||
className="screen-reader-text"
|
||||
aria-hidden={true}
|
||||
>
|
||||
{this.props.bodyLabel}
|
||||
</label>
|
||||
<textarea
|
||||
className={`${name}-textarea`}
|
||||
value={body}
|
||||
placeholder={this.props.bodyPlaceholder}
|
||||
id={this.props.bodyInputId}
|
||||
onChange={this.onBodyChange}
|
||||
rows={3}
|
||||
disabled={disableTextArea}
|
||||
/>
|
||||
<Slot fill="commentInputArea" />
|
||||
</div>
|
||||
}
|
||||
<div className={`${name}-button-container`}>
|
||||
{ this.props.buttonContainerStart }
|
||||
{
|
||||
typeof this.props.onCancel === 'function' && (
|
||||
{this.props.charCountEnable && (
|
||||
<div
|
||||
className={`${name}-char-count ${
|
||||
length > maxCharCount ? `${name}-char-max` : ''
|
||||
}`}
|
||||
>
|
||||
{maxCharCount &&
|
||||
`${maxCharCount - length} ${t(
|
||||
'comment_box.characters_remaining'
|
||||
)}`}
|
||||
</div>
|
||||
)}
|
||||
<div className={`${name}-button-container`}>
|
||||
{this.props.buttonContainerStart}
|
||||
{typeof this.props.onCancel === 'function' && (
|
||||
<Button
|
||||
cStyle='darkGrey'
|
||||
cStyle="darkGrey"
|
||||
className={cn(`${name}-cancel-button`, cancelButtonClassName)}
|
||||
onClick={this.props.onCancel}
|
||||
disabled={disableCancelButton}
|
||||
>
|
||||
{t('comment_box.cancel')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
<Button
|
||||
cStyle={disableSubmitButton ? 'lightGrey' : this.props.submitButtonCStyle}
|
||||
className={cn(`${name}-button`, submitButtonClassName, this.getButtonClassName())}
|
||||
onClick={this.onClickSubmit}
|
||||
disabled={disableSubmitButton ? 'disabled' : ''}>
|
||||
{this.props.submitText}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
cStyle={
|
||||
disableSubmitButton ? 'lightGrey' : this.props.submitButtonCStyle
|
||||
}
|
||||
className={cn(
|
||||
`${name}-button`,
|
||||
submitButtonClassName,
|
||||
this.getButtonClassName()
|
||||
)}
|
||||
onClick={this.onClickSubmit}
|
||||
disabled={disableSubmitButton ? 'disabled' : ''}
|
||||
>
|
||||
{this.props.submitText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export const addTag = (tag) => ({
|
||||
export const addTag = tag => ({
|
||||
type: 'ADD_TAG',
|
||||
tag
|
||||
tag,
|
||||
});
|
||||
|
||||
export const removeTag = (idx) => ({
|
||||
export const removeTag = idx => ({
|
||||
type: 'REMOVE_TAG',
|
||||
idx
|
||||
idx,
|
||||
});
|
||||
|
||||
export const clearTags = () => ({
|
||||
|
||||
@@ -1 +1 @@
|
||||
export {default as reducer} from './reducer';
|
||||
export { default as reducer } from './reducer';
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import {ADD_TAG, REMOVE_TAG, CLEAR_TAGS} from './constants';
|
||||
import { ADD_TAG, REMOVE_TAG, CLEAR_TAGS } from './constants';
|
||||
|
||||
const initialState = {
|
||||
tags: []
|
||||
tags: [],
|
||||
};
|
||||
|
||||
export default function commentBox (state = initialState, action) {
|
||||
export default function commentBox(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case ADD_TAG :
|
||||
return {
|
||||
...state,
|
||||
tags: [...state.tags, action.tag]
|
||||
};
|
||||
case REMOVE_TAG :
|
||||
return {
|
||||
...state,
|
||||
tags: [
|
||||
...state.tags.slice(0, action.idx),
|
||||
...state.tags.slice(action.idx + 1)
|
||||
]
|
||||
};
|
||||
case CLEAR_TAGS :
|
||||
return initialState;
|
||||
default :
|
||||
return state;
|
||||
case ADD_TAG:
|
||||
return {
|
||||
...state,
|
||||
tags: [...state.tags, action.tag],
|
||||
};
|
||||
case REMOVE_TAG:
|
||||
return {
|
||||
...state,
|
||||
tags: [
|
||||
...state.tags.slice(0, action.idx),
|
||||
...state.tags.slice(action.idx + 1),
|
||||
],
|
||||
};
|
||||
case CLEAR_TAGS:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user