mirror of
https://github.com/wassname/talk.git
synced 2026-08-09 12:30:42 +08:00
Merge branch 'master' into story-137818425-tag-staff
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {GraphQLDocs} from 'graphql-docs';
|
||||
|
||||
import fetcher from './services/fetcher';
|
||||
|
||||
// Render the application into the DOM
|
||||
ReactDOM.render(<GraphQLDocs fetcher={fetcher} />, document.querySelector('#root'));
|
||||
@@ -0,0 +1,10 @@
|
||||
export default function fetcher(query) {
|
||||
return fetch(`${window.location.host}/api/v1/graph/ql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({query}),
|
||||
}).then((res) => res.json());
|
||||
}
|
||||
@@ -20,7 +20,8 @@ import LikeButton from 'coral-plugin-likes/LikeButton';
|
||||
|
||||
import styles from './Comment.css';
|
||||
|
||||
const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0];
|
||||
const getActionSummary = (type, comment) => comment.action_summaries
|
||||
.filter((a) => a.__typename === type)[0];
|
||||
const isStaff = (tags) => !tags.every((t) => t.name !== 'STAFF') ;
|
||||
|
||||
class Comment extends React.Component {
|
||||
@@ -38,7 +39,8 @@ class Comment extends React.Component {
|
||||
setActiveReplyBox: PropTypes.func.isRequired,
|
||||
refetch: PropTypes.func.isRequired,
|
||||
showSignInDialog: PropTypes.func.isRequired,
|
||||
postAction: PropTypes.func.isRequired,
|
||||
postFlag: PropTypes.func.isRequired,
|
||||
postLike: PropTypes.func.isRequired,
|
||||
deleteAction: PropTypes.func.isRequired,
|
||||
parentId: PropTypes.string,
|
||||
addNotification: PropTypes.func.isRequired,
|
||||
@@ -54,7 +56,7 @@ class Comment extends React.Component {
|
||||
}),
|
||||
comment: PropTypes.shape({
|
||||
depth: PropTypes.number,
|
||||
actions: PropTypes.array.isRequired,
|
||||
action_summaries: PropTypes.array.isRequired,
|
||||
body: PropTypes.string.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
tags: PropTypes.arrayOf(
|
||||
@@ -85,15 +87,16 @@ class Comment extends React.Component {
|
||||
refetch,
|
||||
addNotification,
|
||||
showSignInDialog,
|
||||
postAction,
|
||||
postLike,
|
||||
postFlag,
|
||||
setActiveReplyBox,
|
||||
activeReplyBox,
|
||||
deleteAction
|
||||
} = this.props;
|
||||
|
||||
const like = getAction('LIKE', comment);
|
||||
const flag = getAction('FLAG', comment);
|
||||
|
||||
const like = getActionSummary('LikeActionSummary', comment);
|
||||
const flag = getActionSummary('FlagActionSummary', comment);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={parentId ? `reply ${styles.Reply}` : `comment ${styles.Comment}`}
|
||||
@@ -111,7 +114,7 @@ class Comment extends React.Component {
|
||||
<LikeButton
|
||||
like={like}
|
||||
id={comment.id}
|
||||
postAction={postAction}
|
||||
postLike={postLike}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser} />
|
||||
@@ -127,7 +130,7 @@ class Comment extends React.Component {
|
||||
flag={flag}
|
||||
id={comment.id}
|
||||
author_id={comment.user.id}
|
||||
postAction={postAction}
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser} />
|
||||
@@ -160,7 +163,8 @@ class Comment extends React.Component {
|
||||
depth={depth + 1}
|
||||
asset={asset}
|
||||
currentUser={currentUser}
|
||||
postAction={postAction}
|
||||
postLike={postLike}
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
reactKey={reply.id}
|
||||
@@ -168,7 +172,6 @@ class Comment extends React.Component {
|
||||
comment={reply} />;
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const {addNotification, clearNotification} = notificationActions;
|
||||
const {fetchAssetSuccess} = assetActions;
|
||||
|
||||
import {queryStream} from 'coral-framework/graphql/queries';
|
||||
import {postComment, postAction, deleteAction} from 'coral-framework/graphql/mutations';
|
||||
import {postComment, postFlag, postLike, deleteAction} from 'coral-framework/graphql/mutations';
|
||||
import {editName} from 'coral-framework/actions/user';
|
||||
import {Notification, notificationActions, authActions, assetActions, pym} from 'coral-framework';
|
||||
|
||||
@@ -91,7 +91,7 @@ class Embed extends Component {
|
||||
minHeight: document.body.scrollHeight + 200
|
||||
} : {};
|
||||
|
||||
if (loading) {
|
||||
if (loading || !asset) {
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ class Embed extends Component {
|
||||
postItem={this.props.postItem}
|
||||
asset={asset}
|
||||
currentUser={user}
|
||||
postAction={this.props.postAction}
|
||||
postLike={this.props.postLike}
|
||||
postFlag={this.props.postFlag}
|
||||
deleteAction={this.props.deleteAction}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
comments={asset.comments} />
|
||||
@@ -209,7 +210,8 @@ const mapDispatchToProps = dispatch => ({
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
postComment,
|
||||
postAction,
|
||||
postFlag,
|
||||
postLike,
|
||||
deleteAction,
|
||||
queryStream
|
||||
)(Embed);
|
||||
|
||||
@@ -37,7 +37,8 @@ class Stream extends React.Component {
|
||||
asset,
|
||||
postItem,
|
||||
addNotification,
|
||||
postAction,
|
||||
postFlag,
|
||||
postLike,
|
||||
deleteAction,
|
||||
showSignInDialog,
|
||||
refetch
|
||||
@@ -56,7 +57,8 @@ class Stream extends React.Component {
|
||||
postItem={postItem}
|
||||
asset={asset}
|
||||
currentUser={currentUser}
|
||||
postAction={postAction}
|
||||
postLike={postLike}
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
key={comment.id}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fragment actionSummaryView on ActionSummary {
|
||||
__typename
|
||||
count
|
||||
current_user {
|
||||
id
|
||||
created_at
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
#import "../fragments/actionSummaryView.graphql"
|
||||
|
||||
fragment commentView on Comment {
|
||||
id
|
||||
body
|
||||
@@ -10,12 +12,7 @@ fragment commentView on Comment {
|
||||
id
|
||||
name: displayName
|
||||
}
|
||||
actions {
|
||||
type: action_type
|
||||
count
|
||||
current: current_user {
|
||||
id
|
||||
created_at
|
||||
}
|
||||
action_summaries {
|
||||
...actionSummaryView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
mutation deleteAction ($id: ID!) {
|
||||
deleteAction(id:$id)
|
||||
deleteAction(id:$id) {
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {graphql} from 'react-apollo';
|
||||
import POST_COMMENT from './postComment.graphql';
|
||||
import POST_ACTION from './postAction.graphql';
|
||||
import POST_FLAG from './postFlag.graphql';
|
||||
import POST_LIKE from './postLike.graphql';
|
||||
import DELETE_ACTION from './deleteAction.graphql';
|
||||
|
||||
import commentView from '../fragments/commentView.graphql';
|
||||
@@ -21,12 +22,23 @@ export const postComment = graphql(POST_COMMENT, {
|
||||
}}),
|
||||
});
|
||||
|
||||
export const postAction = graphql(POST_ACTION, {
|
||||
export const postLike = graphql(POST_LIKE, {
|
||||
props: ({mutate}) => ({
|
||||
postAction: (action) => {
|
||||
postLike: (like) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
action
|
||||
like
|
||||
}
|
||||
});
|
||||
}}),
|
||||
});
|
||||
|
||||
export const postFlag = graphql(POST_FLAG, {
|
||||
props: ({mutate}) => ({
|
||||
postFlag: (flag) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
flag
|
||||
}
|
||||
});
|
||||
}}),
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
mutation CreateAction ($action: CreateActionInput!) {
|
||||
createAction(action:$action) {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
mutation CreateComment ($asset_id: ID!, $parent_id: ID, $body: String!) {
|
||||
createComment(asset_id:$asset_id, parent_id:$parent_id, body:$body) {
|
||||
...commentView
|
||||
comment {
|
||||
...commentView
|
||||
}
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
mutation CreateFlag($flag: CreateFlagInput!) {
|
||||
createFlag(flag:$flag) {
|
||||
flag {
|
||||
id
|
||||
}
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
mutation CreateLike ($like: CreateLikeInput!) {
|
||||
createLike(like:$like) {
|
||||
like {
|
||||
id
|
||||
}
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ function getQueryVariable(variable) {
|
||||
}
|
||||
|
||||
// If no query is included, return a default string for development
|
||||
return 'http://localhost:3030';
|
||||
return 'http://localhost/default/stream';
|
||||
}
|
||||
|
||||
export const queryStream = graphql(STREAM_QUERY, {
|
||||
|
||||
@@ -8,9 +8,6 @@ const name = 'coral-plugin-commentbox';
|
||||
class CommentBox extends Component {
|
||||
|
||||
static propTypes = {
|
||||
|
||||
// updateItem: PropTypes.func,
|
||||
// comments: PropTypes.array,
|
||||
commentPostedHandler: PropTypes.func,
|
||||
postItem: PropTypes.func.isRequired,
|
||||
cancelButtonClicked: PropTypes.func,
|
||||
@@ -29,10 +26,6 @@ class CommentBox extends Component {
|
||||
|
||||
postComment = () => {
|
||||
const {
|
||||
|
||||
// child_id,
|
||||
// updateItem,
|
||||
// appendItemArray,
|
||||
commentPostedHandler,
|
||||
postItem,
|
||||
assetId,
|
||||
@@ -48,28 +41,13 @@ class CommentBox extends Component {
|
||||
parent_id: parentId
|
||||
};
|
||||
|
||||
// let related;
|
||||
// let parent_type;
|
||||
// if (parent_id) {
|
||||
// comment.parent_id = parent_id;
|
||||
// related = 'children';
|
||||
// parent_type = 'comments';
|
||||
// } else {
|
||||
// related = 'comments';
|
||||
// parent_type = 'assets';
|
||||
// }
|
||||
// if (child_id || parent_id) {
|
||||
// updateItem(child_id || parent_id, 'showReply', false, 'comments');
|
||||
// }
|
||||
|
||||
if (this.props.charCount && this.state.body.length > this.props.charCount) {
|
||||
return;
|
||||
}
|
||||
postItem(comment, 'comments')
|
||||
.then(({data}) => {
|
||||
const postedComment = data.createComment;
|
||||
const postedComment = data.createComment.comment;
|
||||
|
||||
// const commentId = postedComment.id;
|
||||
if (postedComment.status === 'REJECTED') {
|
||||
addNotification('error', lang.t('comment-post-banned-word'));
|
||||
} else if (postedComment.status === 'PREMOD') {
|
||||
|
||||
@@ -12,7 +12,7 @@ class FlagButton extends Component {
|
||||
showMenu: false,
|
||||
itemType: '',
|
||||
reason: '',
|
||||
note: '',
|
||||
message: '',
|
||||
step: 0,
|
||||
posted: false,
|
||||
localPost: null,
|
||||
@@ -23,7 +23,7 @@ class FlagButton extends Component {
|
||||
onReportClick = () => {
|
||||
const {currentUser, flag, deleteAction} = this.props;
|
||||
const {localPost, localDelete} = this.state;
|
||||
const flagged = (flag && flag.current && !localDelete) || localPost;
|
||||
const flagged = (flag && flag.current_user && !localDelete) || localPost;
|
||||
if (!currentUser) {
|
||||
const offset = document.getElementById(`c_${this.props.id}`).getBoundingClientRect().top - 75;
|
||||
this.props.showSignInDialog(offset);
|
||||
@@ -31,15 +31,15 @@ class FlagButton extends Component {
|
||||
}
|
||||
if (flagged) {
|
||||
this.setState((prev) => prev.localPost ? {...prev, localPost: null, step: 0} : {...prev, localDelete: true});
|
||||
deleteAction(localPost || flag.current.id);
|
||||
deleteAction(localPost || flag.current_user.id);
|
||||
} else {
|
||||
this.setState({showMenu: !this.state.showMenu});
|
||||
}
|
||||
}
|
||||
|
||||
onPopupContinue = () => {
|
||||
const {postAction, id, author_id} = this.props;
|
||||
const {itemType, reason, step, posted} = this.state;
|
||||
const {postFlag, id, author_id} = this.props;
|
||||
const {itemType, reason, step, posted, message} = this.state;
|
||||
|
||||
// Proceed to the next step or close the menu if we've reached the end
|
||||
if (step + 1 >= this.props.getPopupMenu.length) {
|
||||
@@ -67,13 +67,14 @@ class FlagButton extends Component {
|
||||
if (itemType === 'COMMENTS') {
|
||||
this.setState({localPost: 'temp'});
|
||||
}
|
||||
postAction({
|
||||
postFlag({
|
||||
item_id,
|
||||
item_type: itemType,
|
||||
action_type: 'FLAG'
|
||||
reason,
|
||||
message
|
||||
}).then(({data}) => {
|
||||
if (itemType === 'COMMENTS') {
|
||||
this.setState({localPost: data.createAction.id});
|
||||
this.setState({localPost: data.createFlag.flag.id});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -99,7 +100,7 @@ class FlagButton extends Component {
|
||||
}
|
||||
|
||||
onNoteTextChange = (e) => {
|
||||
this.setState({note: e.target.value});
|
||||
this.setState({message: e.target.value});
|
||||
}
|
||||
|
||||
handleClickOutside () {
|
||||
@@ -109,7 +110,7 @@ class FlagButton extends Component {
|
||||
render () {
|
||||
const {flag, getPopupMenu} = this.props;
|
||||
const {localPost, localDelete} = this.state;
|
||||
const flagged = (flag && flag.current && !localDelete) || localPost;
|
||||
const flagged = (flag && flag.current_user && !localDelete) || localPost;
|
||||
const popupMenu = getPopupMenu[this.state.step](this.state.itemType);
|
||||
|
||||
return <div className={`${name}-container`}>
|
||||
@@ -150,15 +151,15 @@ class FlagButton extends Component {
|
||||
}
|
||||
{
|
||||
this.state.reason && <div>
|
||||
<label htmlFor={'note'} className={`${name}-popup-radio-label`}>
|
||||
<label htmlFor={'message'} className={`${name}-popup-radio-label`}>
|
||||
{lang.t('flag-reason')}
|
||||
</label><br/>
|
||||
<textarea
|
||||
className={`${name}-reason-text`}
|
||||
id="note"
|
||||
id="message"
|
||||
rows={4}
|
||||
onChange={this.onNoteTextChange}
|
||||
value={this.state.note}/>
|
||||
value={this.state.message}/>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
|
||||
@@ -12,7 +12,7 @@ class LikeButton extends Component {
|
||||
count: PropTypes.number
|
||||
}),
|
||||
id: PropTypes.string,
|
||||
postAction: PropTypes.func.isRequired,
|
||||
postLike: PropTypes.func.isRequired,
|
||||
deleteAction: PropTypes.func.isRequired,
|
||||
showSignInDialog: PropTypes.func.isRequired,
|
||||
currentUser: PropTypes.shape({
|
||||
@@ -26,9 +26,9 @@ class LikeButton extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {like, id, postAction, deleteAction, showSignInDialog, currentUser} = this.props;
|
||||
const {like, id, postLike, deleteAction, showSignInDialog, currentUser} = this.props;
|
||||
const {localPost, localDelete} = this.state;
|
||||
const liked = (like && like.current && !localDelete) || localPost;
|
||||
const liked = (like && like.current_user && !localDelete) || localPost;
|
||||
let count = like ? like.count : 0;
|
||||
if (localPost) {count += 1;}
|
||||
if (localDelete) {count -= 1;}
|
||||
@@ -42,28 +42,23 @@ class LikeButton extends Component {
|
||||
if (currentUser.banned) {
|
||||
return;
|
||||
}
|
||||
if (!liked) {
|
||||
this.setState({localPost: 'temp', localDelete: false});
|
||||
postAction({
|
||||
if (!liked) { // this comment has not yet been liked by this user.
|
||||
this.setState({localPost: 'temp'});
|
||||
postLike({
|
||||
item_id: id,
|
||||
item_type: 'COMMENTS',
|
||||
action_type: 'LIKE'
|
||||
item_type: 'COMMENTS'
|
||||
}).then(({data}) => {
|
||||
this.setState({localPost: data.createAction.id});
|
||||
this.setState({localPost: data.createLike.like.id});
|
||||
});
|
||||
} else {
|
||||
this.setState((prev) => prev.localPost ? {...prev, localPost: null} : {...prev, localDelete: true});
|
||||
deleteAction(localPost || like.current.id);
|
||||
deleteAction(localPost || like.current_user.id);
|
||||
}
|
||||
};
|
||||
|
||||
return <div className={`${name}-container`}>
|
||||
<button onClick={onLikeClick} className={`${name}-button ${liked && 'likedButton'}`}>
|
||||
{
|
||||
liked
|
||||
? <span className={`${name}-button-text`}>{lang.t('liked')}</span>
|
||||
: <span className={`${name}-button-text`}>{lang.t('like')}</span>
|
||||
}
|
||||
<span className={`${name}-button-text`}>{lang.t(liked ? 'liked' : 'like')}</span>
|
||||
<i className={`${name}-icon material-icons`}
|
||||
aria-hidden={true}>thumb_up</i>
|
||||
<span className={`${name}-like-count`}>{count > 0 && count}</span>
|
||||
|
||||
Reference in New Issue
Block a user