diff --git a/client/coral-embed-stream/src/Comment.css b/client/coral-embed-stream/src/Comment.css
index 6f89208bc..b463aa247 100644
--- a/client/coral-embed-stream/src/Comment.css
+++ b/client/coral-embed-stream/src/Comment.css
@@ -16,71 +16,9 @@
.topRightMenu {
float: right;
text-align: right;
+ cursor: pointer;
}
.topRightMenu > * {
text-align: initial;
}
-
-.topRightMenu .toggler {
- cursor: pointer;
-}
-
-.topRightMenu .Menu {
- background-color: white;
- text-align: initial;
-}
-
-.Toggleable:focus {
- outline: none;
-}
-
-.Menu {
- border: 1px solid #ddd;
- margin: 0;
-}
-ul.Menu {
- list-style-type: none;
- padding: 0;
-}
-
-.MenuItem {
- cursor: pointer;
- padding: 1em;
-}
-
-.IgnoreUserWizard {
- background-color: #2E343B;
- color: white;
- padding: 1em;
- max-width: 220px;
-}
-
-.IgnoreUserWizard header {
- font-weight: bold;
-}
-
-.IgnoreUserWizard .textAlignRight {
- text-align: right;
-}
-
-/**
- * Up/Down Chevrons for the top right menu
- */
-.chevron {
-}
-.chevron:before {
- content: '⌃';
- display: inline-block;
- position: relative;
- top: 0.25em;
-}
-
-/* Down Arrow */
-.chevron.down:before {
- display: inline-block;
- position: relative;
- transform: rotate(180deg);
- top: 0;
- /*top: -0.25em;*/
-}
diff --git a/client/coral-embed-stream/src/Comment.js b/client/coral-embed-stream/src/Comment.js
index 9ed0bee23..4b01e19a7 100644
--- a/client/coral-embed-stream/src/Comment.js
+++ b/client/coral-embed-stream/src/Comment.js
@@ -11,7 +11,6 @@ import PermalinkButton from 'coral-plugin-permalinks/PermalinkButton';
import AuthorName from 'coral-plugin-author-name/AuthorName';
-import {Button} from 'coral-ui';
import TagLabel from 'coral-plugin-tag-label/TagLabel';
import Content from 'coral-plugin-commentcontent/CommentContent';
import PubDate from 'coral-plugin-pubdate/PubDate';
@@ -22,9 +21,9 @@ import {BestButton, IfUserCanModifyBest, BEST_TAG, commentIsBest, BestIndicator}
import LoadMore from 'coral-embed-stream/src/LoadMore';
import {Slot} from 'coral-framework';
import IgnoredCommentTombstone from './IgnoredCommentTombstone';
+import {TopRightMenu} from './TopRightMenu';
import styles from './Comment.css';
-import classnames from 'classnames';
const getActionSummary = (type, comment) => comment.action_summaries
.filter((a) => a.__typename === type)[0];
@@ -152,126 +151,6 @@ class Comment extends React.Component {
tag: BEST_TAG,
}), () => 'Failed to remove best comment tag');
- class IgnoreUserWizard extends React.Component {
- static propTypes = {
-
- // comment on which this menu appears
- user: PropTypes.shape({
- id: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired
- }).isRequired,
- cancel: PropTypes.func.isRequired,
-
- // actually submit the ignore. Provide {id: user id to ignore}
- ignoreUser: PropTypes.func.isRequired,
- }
- constructor(props) {
- super(props);
- this.state = {
-
- // what step of the wizard is the user on
- step: 1
- };
- this.onClickCancel = this.onClickCancel.bind(this);
- }
- onClickCancel() {
- this.props.cancel();
- }
- render() {
- const {user, ignoreUser} = this.props;
- const goToStep = (stepNum) => this.setState({step: stepNum});
- const step1 = (
-
;
-const downArrow =
;
-class Toggleable extends React.Component {
- constructor(props) {
- super(props);
- this.toggle = this.toggle.bind(this);
- this.close = this.close.bind(this);
- 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 (
-
- // /*onBlur={ this.close } */
-
- {isOpen ? upArrow : downArrow}
- {isOpen ? children : null}
-
- );
- }
-}
-const Menu = ({children}) => (
-
-);
-Menu.Item = ({children, onClick}) => (
-
- { children }
-
-);
-
export default Comment;
diff --git a/client/coral-embed-stream/src/TopRightMenu.css b/client/coral-embed-stream/src/TopRightMenu.css
new file mode 100644
index 000000000..587920c5f
--- /dev/null
+++ b/client/coral-embed-stream/src/TopRightMenu.css
@@ -0,0 +1,39 @@
+.Toggleable:focus {
+ outline: none;
+}
+
+.IgnoreUserWizard {
+ background-color: #2E343B;
+ color: white;
+ padding: 1em;
+ max-width: 220px;
+}
+
+.IgnoreUserWizard header {
+ font-weight: bold;
+}
+
+.IgnoreUserWizard .textAlignRight {
+ text-align: right;
+}
+
+/**
+ * Up/Down Chevrons for the top right menu
+ */
+.chevron {
+}
+.chevron:before {
+ content: '⌃';
+ display: inline-block;
+ position: relative;
+ top: 0.25em;
+}
+
+/* Down Arrow */
+.chevron.down:before {
+ display: inline-block;
+ position: relative;
+ transform: rotate(180deg);
+ top: 0;
+ /*top: -0.25em;*/
+}
diff --git a/client/coral-embed-stream/src/TopRightMenu.js b/client/coral-embed-stream/src/TopRightMenu.js
new file mode 100644
index 000000000..1e06997dd
--- /dev/null
+++ b/client/coral-embed-stream/src/TopRightMenu.js
@@ -0,0 +1,156 @@
+import React, {PropTypes} from 'react';
+import classnames from 'classnames';
+
+import {Button} from 'coral-ui';
+import styles from './TopRightMenu.css';
+
+// TopRightMenu appears as a dropdown in the top right of the comment.
+// when you click the down cehvron, it expands and shows IgnoreUserWizard
+// when you click 'cancel' in the wizard, it closes the menu
+export class TopRightMenu extends React.Component {
+ static propTypes = {
+
+ // comment on which this menu appears
+ comment: PropTypes.shape({
+ user: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired
+ }).isRequired
+ }).isRequired,
+ ignoreUser: PropTypes.func,
+
+ // show notification to the user (e.g. for errors)
+ addNotification: PropTypes.func.isRequired,
+ }
+ constructor(props) {
+ super(props);
+ this.state = {
+ timesReset: 0
+ };
+ }
+ render() {
+ const {comment, ignoreUser, addNotification} = this.props;
+
+ // timesReset is used as Toggleable key so it re-renders on reset (closing the toggleable)
+ const reset = () => this.setState({timesReset: this.state.timesReset + 1});
+ const ignoreUserAndCloseMenuAndNotifyOnError = async ({id}) => {
+
+ // close menu
+ reset();
+
+ // ignore user
+ try {
+ await ignoreUser({id});
+ } catch (error) {
+ addNotification('error', 'Failed to ignore user');
+ throw error;
+ }
+ };
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+class IgnoreUserWizard extends React.Component {
+ static propTypes = {
+
+ // comment on which this menu appears
+ user: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired
+ }).isRequired,
+ cancel: PropTypes.func.isRequired,
+
+ // actually submit the ignore. Provide {id: user id to ignore}
+ ignoreUser: PropTypes.func.isRequired,
+ }
+ constructor(props) {
+ super(props);
+ this.state = {
+
+ // what step of the wizard is the user on
+ step: 1
+ };
+ this.onClickCancel = this.onClickCancel.bind(this);
+ }
+ onClickCancel() {
+ this.props.cancel();
+ }
+ render() {
+ const {user, ignoreUser} = this.props;
+ const goToStep = (stepNum) => this.setState({step: stepNum});
+ const step1 = (
+
+
+
When you ignore a user, all comments they wrote on the site will be hidden from you. You can undo this later from the Profile tab.
+
+ Cancel
+ goToStep(2)}>Ignore user
+
+
+ );
+ const onClickIgnoreUser = async () => {
+ await ignoreUser({id: user.id});
+ };
+ const step2Confirmation = (
+
+
+
Are you sure you want to ignore { user.name }?
+
+ Cancel
+ Ignore user
+
+
+ );
+ const elsForStep = [step1, step2Confirmation];
+ const {step} = this.state;
+ const elForThisStep = elsForStep[step - 1];
+ return (
+
+ { elForThisStep }
+
+ );
+ }
+}
+
+const upArrow =
;
+const downArrow =
;
+class Toggleable extends React.Component {
+ constructor(props) {
+ super(props);
+ this.toggle = this.toggle.bind(this);
+ this.close = this.close.bind(this);
+ 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 (
+
+ // /*onBlur={ this.close } */
+
+ {isOpen ? upArrow : downArrow}
+ {isOpen ? children : null}
+
+ );
+ }
+}
+