- );
-};
+ );
+ }
+}
Comment.propTypes = {
comment: PropTypes.shape({
id: PropTypes.string,
body: PropTypes.string
}).isRequired,
- asset: PropTypes.shape({
- url: PropTypes.string,
- title: PropTypes.string
- }).isRequired
};
export default Comment;
diff --git a/client/talk-plugin-history/CommentHistory.js b/client/talk-plugin-history/CommentHistory.js
index d584d6a0a..43ae93f1d 100644
--- a/client/talk-plugin-history/CommentHistory.js
+++ b/client/talk-plugin-history/CommentHistory.js
@@ -22,16 +22,18 @@ class CommentHistory extends React.Component {
}
render() {
- const {link, comments} = this.props;
+ const {link, comments, data, root} = this.props;
return (
{comments.nodes.map((comment, i) => {
return ;
+ />;
})}
{comments.hasNextPage &&
diff --git a/plugin-api/beta/client/hocs/withReaction.js b/plugin-api/beta/client/hocs/withReaction.js
index 22c30d639..3300ac2d3 100644
--- a/plugin-api/beta/client/hocs/withReaction.js
+++ b/plugin-api/beta/client/hocs/withReaction.js
@@ -11,14 +11,29 @@ import {showSignInDialog} from 'coral-framework/actions/auth';
import {addNotification} from 'coral-framework/actions/notification';
import {capitalize} from 'coral-framework/helpers/strings';
import {getMyActionSummary, getTotalActionCount} from 'coral-framework/utils';
+import hoistStatics from 'recompose/hoistStatics';
import * as PropTypes from 'prop-types';
+import {getDefinitionName} from '../utils';
-export default (reaction) => (WrappedComponent) => {
+/*
+ * Disable false-positive warning below, as it doesn't work well with how we currently
+ * assemble the queries.
+ *
+ * Warning: fragment with name {fragment name} already exists.
+ * graphql-tag enforces all fragment names across your application to be unique; read more about
+ * this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names
+ */
+gql.disableFragmentWarnings();
+
+export default (reaction, options = {}) => hoistStatics((WrappedComponent) => {
if (typeof reaction !== 'string') {
console.error('Reaction must be a valid string');
return null;
}
+ // fragments allow the extension of the fragments defined in this HOC.
+ const {fragments = {}} = options;
+
// Global instance counter for each `reaction` type.
let instances = 0;
@@ -175,7 +190,7 @@ export default (reaction) => (WrappedComponent) => {
createdSubscription = context.client.subscribe({
query: REACTION_CREATED_SUBSCRIPTION,
variables: {
- assetId: this.props.root.asset.id,
+ assetId: this.props.asset.id,
},
}).subscribe({
next: this.onReactionCreated,
@@ -185,7 +200,7 @@ export default (reaction) => (WrappedComponent) => {
deletedSubscription = context.client.subscribe({
query: REACTION_DELETED_SUBSCRIPTION,
variables: {
- assetId: this.props.root.asset.id,
+ assetId: this.props.asset.id,
},
}).subscribe({
next: this.onReactionDeleted,
@@ -247,7 +262,7 @@ export default (reaction) => (WrappedComponent) => {
}
render() {
- const {comment} = this.props;
+ const {root, asset, comment} = this.props;
const reactionSummary = getMyActionSummary(
`${Reaction}ActionSummary`,
@@ -262,10 +277,12 @@ export default (reaction) => (WrappedComponent) => {
const alreadyReacted = !!reactionSummary;
return
(WrappedComponent) => {
const enhance = compose(
withFragments({
+ ...fragments,
+ asset: gql`
+ fragment ${Reaction}Button_asset on Asset {
+ id
+ ${fragments.asset ? `...${getDefinitionName(fragments.asset)}` : ''}
+ }
+ ${fragments.asset ? fragments.asset : ''}
+ `,
comment: gql`
fragment ${Reaction}Button_comment on Comment {
+ id
action_summaries {
+ __typename
... on ${Reaction}ActionSummary {
count
current_user {
@@ -381,7 +408,10 @@ export default (reaction) => (WrappedComponent) => {
}
}
}
- }`
+ ${fragments.comment ? `...${getDefinitionName(fragments.comment)}` : ''}
+ }
+ ${fragments.comment ? fragments.comment : ''}
+ `
}),
connect(mapStateToProps, mapDispatchToProps),
withDeleteReaction,
@@ -391,4 +421,4 @@ export default (reaction) => (WrappedComponent) => {
WithReactions.displayName = `WithReactions(${getDisplayName(WrappedComponent)})`;
return enhance(WithReactions);
-};
+});
diff --git a/plugin-api/beta/client/hocs/withTags.js b/plugin-api/beta/client/hocs/withTags.js
index b0a74f4d7..491c35038 100644
--- a/plugin-api/beta/client/hocs/withTags.js
+++ b/plugin-api/beta/client/hocs/withTags.js
@@ -8,13 +8,28 @@ import {withAddTag, withRemoveTag} from 'coral-framework/graphql/mutations';
import withFragments from 'coral-framework/hocs/withFragments';
import {addNotification} from 'coral-framework/actions/notification';
import {forEachError, isTagged} from 'coral-framework/utils';
+import hoistStatics from 'recompose/hoistStatics';
+import {getDefinitionName} from '../utils';
-export default (tag) => (WrappedComponent) => {
+/*
+ * Disable false-positive warning below, as it doesn't work well with how we currently
+ * assemble the queries.
+ *
+ * Warning: fragment with name {fragment name} already exists.
+ * graphql-tag enforces all fragment names across your application to be unique; read more about
+ * this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names
+ */
+gql.disableFragmentWarnings();
+
+export default (tag, options = {}) => hoistStatics((WrappedComponent) => {
if (typeof tag !== 'string') {
console.error('Tag must be a valid string');
return null;
}
+ // fragments allow the extension of the fragments defined in this HOC.
+ const {fragments = {}} = options;
+
const Tag = capitalize(tag);
const TAG = tag.toUpperCase();
@@ -68,13 +83,15 @@ export default (tag) => (WrappedComponent) => {
}
render() {
- const {comment, user, config} = this.props;
+ const {root, asset, comment, user, config} = this.props;
const alreadyTagged = isTagged(comment.tags, TAG);
return (WrappedComponent) => {
const enhance = compose(
withFragments({
+ ...fragments,
+ asset: gql`
+ fragment ${Tag}Button_asset on Asset {
+ id
+ ${fragments.asset ? `...${getDefinitionName(fragments.asset)}` : ''}
+ }
+ ${fragments.asset ? fragments.asset : ''}
+ `,
comment: gql`
fragment ${Tag}Button_comment on Comment {
+ id
tags {
tag {
name
}
}
- }`
+ ${fragments.comment ? `...${getDefinitionName(fragments.comment)}` : ''}
+ }
+ ${fragments.comment ? fragments.comment : ''}
+ `
}),
connect(mapStateToProps, mapDispatchToProps),
withAddTag,
@@ -109,4 +138,4 @@ export default (tag) => (WrappedComponent) => {
WithTags.displayName = `WithTags(${getDisplayName(WrappedComponent)})`;
return enhance(WithTags);
-};
+});
diff --git a/plugins/talk-plugin-featured-comments/client/containers/Comment.js b/plugins/talk-plugin-featured-comments/client/containers/Comment.js
index 7080627e6..bba764a1d 100644
--- a/plugins/talk-plugin-featured-comments/client/containers/Comment.js
+++ b/plugins/talk-plugin-featured-comments/client/containers/Comment.js
@@ -31,7 +31,6 @@ export default withFragments({
name
}
}
-
user {
id
username
diff --git a/plugins/talk-plugin-featured-comments/client/containers/ModTag.js b/plugins/talk-plugin-featured-comments/client/containers/ModTag.js
index 3b564d127..7081c7ec6 100644
--- a/plugins/talk-plugin-featured-comments/client/containers/ModTag.js
+++ b/plugins/talk-plugin-featured-comments/client/containers/ModTag.js
@@ -1,5 +1,16 @@
import ModTag from '../components/ModTag';
import {withTags} from 'plugin-api/beta/client/hocs';
+import {gql} from 'react-apollo';
-export default withTags('featured')(ModTag);
+const fragments = {
+ comment: gql`
+ fragment TalkFeaturedComments_ModTag_comment on Comment {
+ user {
+ username
+ }
+ }
+ `
+};
+
+export default withTags('featured', {fragments})(ModTag);
diff --git a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
index 2195b0107..63ce30d01 100644
--- a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
+++ b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
@@ -16,8 +16,8 @@ class TabPaneContainer extends React.Component {
query: LOAD_MORE_QUERY,
variables: {
limit: 5,
- cursor: this.props.root.asset.featuredComments.endCursor,
- asset_id: this.props.root.asset.id,
+ cursor: this.props.asset.featuredComments.endCursor,
+ asset_id: this.props.asset.id,
sort: 'REVERSE_CHRONOLOGICAL',
excludeIgnored: this.props.data.variables.excludeIgnored,
},
diff --git a/plugins/talk-plugin-featured-comments/client/containers/Tag.js b/plugins/talk-plugin-featured-comments/client/containers/Tag.js
new file mode 100644
index 000000000..60d9e1e2b
--- /dev/null
+++ b/plugins/talk-plugin-featured-comments/client/containers/Tag.js
@@ -0,0 +1,15 @@
+import {gql} from 'react-apollo';
+import Tag from '../components/Tag';
+import {withFragments} from 'plugin-api/beta/client/hocs';
+
+export default withFragments({
+ comment: gql`
+ fragment TalkFeaturedComments_Tag_comment on Comment {
+ tags {
+ tag {
+ name
+ }
+ }
+ }
+ `
+})(Tag);
diff --git a/plugins/talk-plugin-featured-comments/client/index.js b/plugins/talk-plugin-featured-comments/client/index.js
index ad10f87ca..79c3d874f 100644
--- a/plugins/talk-plugin-featured-comments/client/index.js
+++ b/plugins/talk-plugin-featured-comments/client/index.js
@@ -1,5 +1,5 @@
import Tab from './containers/Tab';
-import Tag from './components/Tag';
+import Tag from './containers/Tag';
import Button from './components/Button';
import TabPane from './containers/TabPane';
import translations from './translations.yml';
diff --git a/plugins/talk-plugin-offtopic/client/containers/OffTopicTag.js b/plugins/talk-plugin-offtopic/client/containers/OffTopicTag.js
new file mode 100644
index 000000000..bf57dc5cb
--- /dev/null
+++ b/plugins/talk-plugin-offtopic/client/containers/OffTopicTag.js
@@ -0,0 +1,15 @@
+import {gql} from 'react-apollo';
+import OffTopicTag from '../components/OffTopicTag';
+import {withFragments} from 'plugin-api/beta/client/hocs';
+
+export default withFragments({
+ comment: gql`
+ fragment TalkOfftopic_OffTopicTag_comment on Comment {
+ tags {
+ tag {
+ name
+ }
+ }
+ }
+ `
+})(OffTopicTag);
diff --git a/plugins/talk-plugin-offtopic/client/index.js b/plugins/talk-plugin-offtopic/client/index.js
index b284f7280..24bfc095f 100644
--- a/plugins/talk-plugin-offtopic/client/index.js
+++ b/plugins/talk-plugin-offtopic/client/index.js
@@ -1,5 +1,5 @@
import translations from './translations.json';
-import OffTopicTag from './components/OffTopicTag';
+import OffTopicTag from './containers/OffTopicTag';
import OffTopicFilter from './containers/OffTopicFilter';
import OffTopicCheckbox from './containers/OffTopicCheckbox';
import reducer from './reducer';
diff --git a/plugins/talk-plugin-permalink/client/components/PermalinkButton.js b/plugins/talk-plugin-permalink/client/components/PermalinkButton.js
index 27cbf9188..e2536f86f 100644
--- a/plugins/talk-plugin-permalink/client/components/PermalinkButton.js
+++ b/plugins/talk-plugin-permalink/client/components/PermalinkButton.js
@@ -28,9 +28,11 @@ export default class PermalinkButton extends React.Component {
}
handleClickOutside = () => {
- this.setState({
- popoverOpen: false
- });
+ if (this.state.popoverOpen) {
+ this.setState({
+ popoverOpen: false
+ });
+ }
}
copyPermalink = () => {
diff --git a/plugins/talk-plugin-permalink/client/containers/PermalinkButton.js b/plugins/talk-plugin-permalink/client/containers/PermalinkButton.js
new file mode 100644
index 000000000..5e1d11110
--- /dev/null
+++ b/plugins/talk-plugin-permalink/client/containers/PermalinkButton.js
@@ -0,0 +1,16 @@
+import {gql} from 'react-apollo';
+import PermalinkButton from '../components/PermalinkButton';
+import {withFragments} from 'plugin-api/beta/client/hocs';
+
+export default withFragments({
+ asset: gql`
+ fragment TalkPermalink_Button_asset on Asset {
+ url
+ }
+ `,
+ comment: gql`
+ fragment TalkPermalink_Button_comment on Comment {
+ id
+ }
+ `
+})(PermalinkButton);
diff --git a/plugins/talk-plugin-permalink/client/index.js b/plugins/talk-plugin-permalink/client/index.js
index d413da870..c28c4ae71 100644
--- a/plugins/talk-plugin-permalink/client/index.js
+++ b/plugins/talk-plugin-permalink/client/index.js
@@ -1,4 +1,4 @@
-import PermalinkButton from './components/PermalinkButton';
+import PermalinkButton from './containers/PermalinkButton';
export default {
slots: {