-
Moderate comments on All Stories
+ {props.assetId &&
+
+ }
{
@@ -87,7 +91,8 @@ StorySearch.propTypes = {
goToStory: PropTypes.func.isRequired,
closeSearch: PropTypes.func.isRequired,
moderation: PropTypes.object.isRequired,
- handleSearchChange: PropTypes.func.isRequired
+ handleSearchChange: PropTypes.func.isRequired,
+ assetId: PropTypes.string
};
export default StorySearch;
diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js
index 7047a41d5..59f696b5f 100644
--- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js
+++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js
@@ -5,6 +5,7 @@ import {Button, Drawer} from 'coral-ui';
import {Slot} from 'coral-framework/components';
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
import {actionsMap} from '../helpers/moderationQueueActionsMap';
+import ClickOutside from 'coral-framework/components/ClickOutside';
export default class UserDetail extends React.Component {
@@ -80,90 +81,92 @@ export default class UserDetail extends React.Component {
}
return (
-
- {user.username}
+
+
+ {user.username}
-
- {profile && this.profile = ref} value={profile} />}
-
-
+
+ {profile && this.profile = ref} value={profile} />}
+
+
-
- Member since {new Date(user.created_at).toLocaleString()}
-
-
- Account summary
-
Data represents the last six months of activity
-
-
-
-
Total Comments
-
{totalComments}
-
-
-
Reject Rate
-
{`${(rejectedPercent).toFixed(1)}%`}
-
-
- {
- selectedIds.length === 0
- ? (
-
- )
- : (
-
-
-
- {`${selectedIds.length} comments selected`}
+
+
Member since {new Date(user.created_at).toLocaleString()}
+
+
+ Account summary
+
Data represents the last six months of activity
+
+
+
+
Total Comments
+
{totalComments}
- )
- }
-
-
+
+
Reject Rate
+
{`${(rejectedPercent).toFixed(1)}%`}
+
+
{
- nodes.map((comment, i) => {
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
- const selected = selectedIds.indexOf(comment.id) !== -1;
- return
{}}
- actions={actionsMap[status]}
- showBanUserDialog={showBanUserDialog}
- showSuspendUserDialog={showSuspendUserDialog}
- acceptComment={this.acceptThenReload}
- rejectComment={this.rejectThenReload}
- selected={selected}
- toggleSelect={toggleSelect}
- currentAsset={null}
- currentUserId={this.props.id}
- minimal={true} />;
- })
+ selectedIds.length === 0
+ ? (
+
+ )
+ : (
+
+
+
+ {`${selectedIds.length} comments selected`}
+
+ )
}
-
-
+
+
+ {
+ nodes.map((comment, i) => {
+ const status = comment.action_summaries ? 'FLAGGED' : comment.status;
+ const selected = selectedIds.indexOf(comment.id) !== -1;
+ return {}}
+ actions={actionsMap[status]}
+ showBanUserDialog={showBanUserDialog}
+ showSuspendUserDialog={showSuspendUserDialog}
+ acceptComment={this.acceptThenReload}
+ rejectComment={this.rejectThenReload}
+ selected={selected}
+ toggleSelect={toggleSelect}
+ currentAsset={null}
+ currentUserId={this.props.id}
+ minimal={true} />;
+ })
+ }
+
+
+
);
}
}
diff --git a/client/coral-admin/src/routes/Moderation/components/styles.css b/client/coral-admin/src/routes/Moderation/components/styles.css
index 8b4fe971d..1228c61a4 100644
--- a/client/coral-admin/src/routes/Moderation/components/styles.css
+++ b/client/coral-admin/src/routes/Moderation/components/styles.css
@@ -190,8 +190,6 @@ span {
}
&.selected {
- max-width: 720px;
- max-height: 410px;
}
.context {
diff --git a/client/coral-admin/src/routes/Moderation/containers/StorySearch.js b/client/coral-admin/src/routes/Moderation/containers/StorySearch.js
index cf47ca662..f4ab6f23e 100644
--- a/client/coral-admin/src/routes/Moderation/containers/StorySearch.js
+++ b/client/coral-admin/src/routes/Moderation/containers/StorySearch.js
@@ -41,7 +41,13 @@ class StorySearchContainer extends React.Component {
goToStory = (id) => {
const {router, closeSearch} = this.props;
- router.push(`/admin/moderate/${id}`);
+ router.push(`/admin/moderate/all/${id}`);
+ closeSearch();
+ }
+
+ goToModerateAll = () => {
+ const {router, closeSearch} = this.props;
+ router.push('/admin/moderate/all');
closeSearch();
}
@@ -50,6 +56,7 @@ class StorySearchContainer extends React.Component {
{
};
export default class Comment extends React.Component {
+ isLoadingReplies = false;
+
constructor(props) {
super(props);
@@ -211,14 +213,24 @@ export default class Comment extends React.Component {
}
loadNewReplies = () => {
- const {replies, replyCount, id} = this.props.comment;
- if (replyCount > replies.nodes.length) {
- this.props.loadMore(id).then(() => {
- this.setState(resetCursors(this.state, this.props));
- });
- return;
+ if (!this.isLoadingReplies) {
+ this.isLoadingReplies = true;
+ const {replies, replyCount, id} = this.props.comment;
+ if (replyCount > replies.nodes.length) {
+ this.props.loadMore(id)
+ .then(() => {
+ this.setState(resetCursors(this.state, this.props));
+ this.isLoadingReplies = false;
+ })
+ .catch((e) => {
+ this.isLoadingReplies = false;
+ throw e;
+ });
+ return;
+ }
+ this.setState(resetCursors);
+ this.isLoadingReplies = false;
}
- this.setState(resetCursors);
};
showReplyBox = () => {
@@ -432,28 +444,28 @@ export default class Comment extends React.Component {
inline
/>
- { (currentUser &&
- (comment.user.id === currentUser.id))
+ { (currentUser && (comment.user.id === currentUser.id)) &&
- /* User can edit/delete their own comment for a short window after posting */
- ?
- {
- commentIsStillEditable(comment) &&
- Edit
- }
-
+ /* User can edit/delete their own comment for a short window after posting */
+
+ {
+ commentIsStillEditable(comment) &&
+ Edit
+ }
+
+ }
+ { (currentUser && (comment.user.id !== currentUser.id)) &&
/* TopRightMenu allows currentUser to ignore other users' comments */
- :
-
-
+
+
+
}
-
{
this.state.isEditing
? {
+ this.initialState = false;
+ this.props.loadMore();
+ }
+
render () {
- const {topLevel, moreComments, loadMore, replyCount} = this.props;
+ const {topLevel, moreComments, replyCount} = this.props;
return moreComments
?
diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js
index 62a58129b..f6c67fd8d 100644
--- a/client/coral-embed-stream/src/components/Stream.js
+++ b/client/coral-embed-stream/src/components/Stream.js
@@ -53,6 +53,8 @@ function invalidateCursor(invalidated, state, props) {
class Stream extends React.Component {
+ isLoadingMore = false;
+
constructor(props) {
super(props);
this.state = resetCursors(this.state, props);
@@ -95,6 +97,18 @@ class Stream extends React.Component {
}
};
+ loadMoreComments = () => {
+ if (!this.isLoadingMore) {
+ this.isLoadingMore = true;
+ this.props.loadMoreComments()
+ .then(() => this.isLoadingMore = false)
+ .catch((e) => {
+ this.isLoadingMore = false;
+ throw e;
+ });
+ }
+ }
+
// getVisibileComments returns a list containing comments
// which were authored by current user or comes after the `idCursor`.
getVisibleComments() {
@@ -288,7 +302,7 @@ class Stream extends React.Component {
}
diff --git a/client/coral-embed-stream/src/components/TopRightMenu.css b/client/coral-embed-stream/src/components/Toggleable.css
similarity index 100%
rename from client/coral-embed-stream/src/components/TopRightMenu.css
rename to client/coral-embed-stream/src/components/Toggleable.css
diff --git a/client/coral-embed-stream/src/components/Toggleable.js b/client/coral-embed-stream/src/components/Toggleable.js
new file mode 100644
index 000000000..c7996d866
--- /dev/null
+++ b/client/coral-embed-stream/src/components/Toggleable.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import ClickOutside from 'coral-framework/components/ClickOutside';
+import styles from './Toggleable.css';
+import classnames from 'classnames';
+
+const upArrow =
;
+const downArrow =
;
+
+export default class Toggleable extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ isOpen: false
+ };
+ }
+
+ toggle = () => {
+ this.setState({isOpen: !this.state.isOpen});
+ }
+
+ close = () => {
+ this.setState({isOpen: false});
+ }
+
+ render() {
+ const {children} = this.props;
+ const {isOpen} = this.state;
+ return (
+
+
+ {isOpen ? upArrow : downArrow}
+ {isOpen ? children : null}
+
+
+ );
+ }
+}
+
diff --git a/client/coral-embed-stream/src/components/TopRightMenu.js b/client/coral-embed-stream/src/components/TopRightMenu.js
index 84d64f061..d65722b6d 100644
--- a/client/coral-embed-stream/src/components/TopRightMenu.js
+++ b/client/coral-embed-stream/src/components/TopRightMenu.js
@@ -1,8 +1,6 @@
import React, {PropTypes} from 'react';
-import classnames from 'classnames';
-
import {IgnoreUserWizard} from './IgnoreUserWizard';
-import styles from './TopRightMenu.css';
+import Toggleable from './Toggleable';
// TopRightMenu appears as a dropdown in the top right of the comment.
// when you click the down cehvron, it expands and shows IgnoreUserWizard
@@ -56,38 +54,6 @@ export class TopRightMenu extends React.Component {
/>
- );
- }
-}
-
-const upArrow =