mirror of
https://github.com/wassname/talk.git
synced 2026-07-06 05:17:19 +08:00
Get rid of data direct dependency in the plugins
This commit is contained in:
@@ -14,6 +14,10 @@ export { default as withPopupAuthHandler } from './withPopupAuthHandler';
|
||||
export { default as withEnumValues } from './withEnumValues';
|
||||
export { default as withCombatPassthrough } from './withCombatPassthrough';
|
||||
export { default as withSlotElements } from './withSlotElements';
|
||||
export { default as withVariables } from './withVariables';
|
||||
export { default as WithRefetch } from './withRefetch';
|
||||
export { default as withFetchMore } from './withFetchMore';
|
||||
export { default as withSubscribeToMore } from './withSubscribeToMore';
|
||||
export {
|
||||
default as withResendEmailConfirmation,
|
||||
} from './withResendEmailConfirmation';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import hoistStatics from 'recompose/hoistStatics';
|
||||
import { Subscriber } from 'react-broadcast';
|
||||
import get from 'lodash/get';
|
||||
|
||||
/**
|
||||
* WithFetchMore provides a property `fetchMore` to the wrapped component.
|
||||
* Calling `fetchMore` is the same as calling `data.fetchMore` from the
|
||||
* Apollo React API.
|
||||
*/
|
||||
export default hoistStatics(WrappedComponent => {
|
||||
class WithFetchMore extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Subscriber channel="queryData">
|
||||
{data => (
|
||||
<WrappedComponent
|
||||
{...this.props}
|
||||
fetchMore={get(data, 'fetchMore')}
|
||||
/>
|
||||
)}
|
||||
</Subscriber>
|
||||
);
|
||||
}
|
||||
}
|
||||
return WithFetchMore;
|
||||
});
|
||||
@@ -11,6 +11,8 @@ import { getOperationName } from 'apollo-client/queries/getFromAST';
|
||||
import throttle from 'lodash/throttle';
|
||||
import get from 'lodash/get';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
import { Broadcast } from 'react-broadcast';
|
||||
import { compose } from 'recompose';
|
||||
|
||||
const withSkipOnErrors = reducer => (prev, action, ...rest) => {
|
||||
if (
|
||||
@@ -71,6 +73,15 @@ function networkStatusToString(networkStatus) {
|
||||
}
|
||||
}
|
||||
|
||||
// When wrapped broadcast all data changes to channel "queryData".
|
||||
const withBroadcaster = WrappedComponent => props => (
|
||||
/* eslint-disable react/prop-types */
|
||||
<Broadcast channel="queryData" value={props.data}>
|
||||
<WrappedComponent {...props} />
|
||||
</Broadcast>
|
||||
/* eslint-enable react/prop-types */
|
||||
);
|
||||
|
||||
const createHOC = (document, config, { notifyOnError = true }) =>
|
||||
hoistStatics(WrappedComponent => {
|
||||
return class WithQuery extends React.Component {
|
||||
@@ -357,10 +368,13 @@ const createHOC = (document, config, { notifyOnError = true }) =>
|
||||
if (!this.memoized) {
|
||||
this.resolvedDocument = this.resolveDocument(document);
|
||||
this.name = getDefinitionName(this.resolvedDocument);
|
||||
this.memoized = graphql(this.resolvedDocument, {
|
||||
...this.wrappedConfig,
|
||||
options: this.wrappedOptions,
|
||||
})(WrappedComponent);
|
||||
this.memoized = compose(
|
||||
graphql(this.resolvedDocument, {
|
||||
...this.wrappedConfig,
|
||||
options: this.wrappedOptions,
|
||||
}),
|
||||
withBroadcaster
|
||||
)(WrappedComponent);
|
||||
}
|
||||
return this.memoized;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import hoistStatics from 'recompose/hoistStatics';
|
||||
import { Subscriber } from 'react-broadcast';
|
||||
import get from 'lodash/get';
|
||||
|
||||
/**
|
||||
* WithRefetch provides a property `refetch` to the wrapped component.
|
||||
* Calling refetch will perform a refetch of the parent Query.
|
||||
*/
|
||||
export default hoistStatics(WrappedComponent => {
|
||||
class WithRefetch extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Subscriber channel="queryData">
|
||||
{data => (
|
||||
<WrappedComponent {...this.props} refetch={get(data, 'refetch')} />
|
||||
)}
|
||||
</Subscriber>
|
||||
);
|
||||
}
|
||||
}
|
||||
return WithRefetch;
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import hoistStatics from 'recompose/hoistStatics';
|
||||
import { Subscriber } from 'react-broadcast';
|
||||
import get from 'lodash/get';
|
||||
|
||||
/**
|
||||
* WithSubscribeToMore provides a property `subscribeToMore` to the wrapped component.
|
||||
* Calling `subscribeToMore` is the same as calling `data.subscribeToMore` from the
|
||||
* Apollo React API.
|
||||
*/
|
||||
export default hoistStatics(WrappedComponent => {
|
||||
class WithSubscribeToMore extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Subscriber channel="queryData">
|
||||
{data => (
|
||||
<WrappedComponent
|
||||
{...this.props}
|
||||
subscribeToMore={get(data, 'subscribeToMoreThrottled')}
|
||||
/>
|
||||
)}
|
||||
</Subscriber>
|
||||
);
|
||||
}
|
||||
}
|
||||
return WithSubscribeToMore;
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import hoistStatics from 'recompose/hoistStatics';
|
||||
import { Subscriber } from 'react-broadcast';
|
||||
import get from 'lodash/get';
|
||||
|
||||
/**
|
||||
* WithVariables provides a property `variables` to the wrapped component.
|
||||
* These are the variables of the parent Query.
|
||||
*/
|
||||
export default hoistStatics(WrappedComponent => {
|
||||
class WithVariables extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Subscriber channel="queryData">
|
||||
{data => (
|
||||
<WrappedComponent
|
||||
{...this.props}
|
||||
variables={get(data, 'variables')}
|
||||
/>
|
||||
)}
|
||||
</Subscriber>
|
||||
);
|
||||
}
|
||||
}
|
||||
return WithVariables;
|
||||
});
|
||||
@@ -159,6 +159,7 @@
|
||||
"query-string": "^5.0.0",
|
||||
"react": "^15.4.2",
|
||||
"react-apollo": "^1.4.12",
|
||||
"react-broadcast": "^0.6.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"react-input-autosize": "^1.1.4",
|
||||
"react-mdl": "^1.11.0",
|
||||
|
||||
@@ -13,6 +13,10 @@ export {
|
||||
withResendEmailConfirmation,
|
||||
withSetUsername,
|
||||
withEnumValues,
|
||||
withVariables,
|
||||
withFetchMore,
|
||||
withSubscribeToMore,
|
||||
withRefetch,
|
||||
} from 'coral-framework/hocs';
|
||||
export {
|
||||
withIgnoreUser,
|
||||
@@ -21,3 +25,4 @@ export {
|
||||
withStopIgnoringUser,
|
||||
withSetCommentStatus,
|
||||
} from 'coral-framework/graphql/mutations';
|
||||
export { compose } from 'recompose';
|
||||
|
||||
@@ -49,7 +49,6 @@ class AuthorNameContainer extends React.Component {
|
||||
|
||||
render() {
|
||||
const {
|
||||
data,
|
||||
root,
|
||||
asset,
|
||||
comment,
|
||||
@@ -57,7 +56,7 @@ class AuthorNameContainer extends React.Component {
|
||||
showMenuForComment,
|
||||
} = this.props;
|
||||
|
||||
const slotPassthrough = { data, root, asset, comment };
|
||||
const slotPassthrough = { root, asset, comment };
|
||||
|
||||
return (
|
||||
<AuthorName
|
||||
@@ -73,7 +72,6 @@ class AuthorNameContainer extends React.Component {
|
||||
}
|
||||
|
||||
AuthorNameContainer.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
root: PropTypes.object.isRequired,
|
||||
asset: PropTypes.object.isRequired,
|
||||
comment: PropTypes.object.isRequired,
|
||||
|
||||
@@ -18,8 +18,8 @@ class Comment extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { comment, asset, root, data } = this.props;
|
||||
const slotPassthrough = { data, comment, asset, root };
|
||||
const { comment, asset, root } = this.props;
|
||||
const slotPassthrough = { comment, asset, root };
|
||||
return (
|
||||
<div className={cn(styles.root, `${pluginName}-comment`)}>
|
||||
<Slot
|
||||
@@ -62,12 +62,7 @@ class Comment extends React.Component {
|
||||
inline
|
||||
/>
|
||||
|
||||
<FeaturedButton
|
||||
root={root}
|
||||
data={data}
|
||||
comment={comment}
|
||||
asset={asset}
|
||||
/>
|
||||
<FeaturedButton root={root} comment={comment} asset={asset} />
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
|
||||
@@ -22,7 +22,6 @@ class TabPane extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
root,
|
||||
data,
|
||||
asset: { featuredComments, ...asset },
|
||||
viewComment,
|
||||
} = this.props;
|
||||
@@ -32,7 +31,6 @@ class TabPane extends React.Component {
|
||||
<Comment
|
||||
key={comment.id}
|
||||
root={root}
|
||||
data={data}
|
||||
comment={comment}
|
||||
asset={asset}
|
||||
viewComment={viewComment}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { gql } from 'react-apollo';
|
||||
import { subscriptionFields } from 'coral-admin/src/routes/Moderation/graphql';
|
||||
import { compose, withSubscribeToMore } from 'plugin-api/beta/client/hocs';
|
||||
|
||||
class ModIndicatorSubscription extends React.Component {
|
||||
subscriptions = null;
|
||||
@@ -27,7 +28,7 @@ class ModIndicatorSubscription extends React.Component {
|
||||
},
|
||||
];
|
||||
this.subscriptions = configs.map(config =>
|
||||
this.props.data.subscribeToMore(config)
|
||||
this.props.subscribeToMore(config)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,4 +61,4 @@ const COMMENT_UNFEATURED_SUBSCRIPTION = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export default ModIndicatorSubscription;
|
||||
export default compose(withSubscribeToMore)(ModIndicatorSubscription);
|
||||
|
||||
@@ -6,6 +6,11 @@ import { getDefinitionName } from 'coral-framework/utils';
|
||||
import truncate from 'lodash/truncate';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import { subscriptionFields } from 'coral-admin/src/routes/Moderation/graphql';
|
||||
import {
|
||||
compose,
|
||||
withSubscribeToMore,
|
||||
withVariables,
|
||||
} from 'plugin-api/beta/client/hocs';
|
||||
|
||||
function prepareNotificationText(text) {
|
||||
return truncate(text, { length: 50 }).replace('\n', ' ');
|
||||
@@ -19,7 +24,7 @@ class ModSubscription extends React.Component {
|
||||
{
|
||||
document: COMMENT_FEATURED_SUBSCRIPTION,
|
||||
variables: {
|
||||
assetId: this.props.data.variables.asset_id,
|
||||
assetId: this.props.variables.asset_id,
|
||||
},
|
||||
updateQuery: (
|
||||
prev,
|
||||
@@ -39,7 +44,7 @@ class ModSubscription extends React.Component {
|
||||
{
|
||||
document: COMMENT_UNFEATURED_SUBSCRIPTION,
|
||||
variables: {
|
||||
assetId: this.props.data.variables.asset_id,
|
||||
assetId: this.props.variables.asset_id,
|
||||
},
|
||||
updateQuery: (
|
||||
prev,
|
||||
@@ -62,7 +67,7 @@ class ModSubscription extends React.Component {
|
||||
},
|
||||
];
|
||||
this.subscriptions = configs.map(config =>
|
||||
this.props.data.subscribeToMore(config)
|
||||
this.props.subscribeToMore(config)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -111,4 +116,8 @@ const mapStateToProps = state => ({
|
||||
user: state.auth.user,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(ModSubscription);
|
||||
export default compose(
|
||||
connect(mapStateToProps, null),
|
||||
withVariables,
|
||||
withSubscribeToMore
|
||||
)(ModSubscription);
|
||||
|
||||
@@ -2,7 +2,12 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { compose, gql } from 'react-apollo';
|
||||
import TabPane from '../components/TabPane';
|
||||
import { withFragments, connect } from 'plugin-api/beta/client/hocs';
|
||||
import {
|
||||
withFragments,
|
||||
connect,
|
||||
withFetchMore,
|
||||
withVariables,
|
||||
} from 'plugin-api/beta/client/hocs';
|
||||
import Comment from '../containers/Comment';
|
||||
import { viewComment } from 'coral-embed-stream/src/actions/stream';
|
||||
import {
|
||||
@@ -13,15 +18,15 @@ import update from 'immutability-helper';
|
||||
|
||||
class TabPaneContainer extends React.Component {
|
||||
loadMore = () => {
|
||||
return this.props.data.fetchMore({
|
||||
return this.props.fetchMore({
|
||||
query: LOAD_MORE_QUERY,
|
||||
variables: {
|
||||
limit: 5,
|
||||
cursor: this.props.asset.featuredComments.endCursor,
|
||||
asset_id: this.props.asset.id,
|
||||
sortOrder: this.props.data.variables.sortOrder,
|
||||
sortBy: this.props.data.variables.sortBy,
|
||||
excludeIgnored: this.props.data.variables.excludeIgnored,
|
||||
sortOrder: this.props.variables.sortOrder,
|
||||
sortBy: this.props.variables.sortBy,
|
||||
excludeIgnored: this.props.variables.excludeIgnored,
|
||||
},
|
||||
updateQuery: (previous, { fetchMoreResult: { comments } }) => {
|
||||
const updated = update(previous, {
|
||||
@@ -86,6 +91,8 @@ const mapDispatchToProps = dispatch =>
|
||||
|
||||
const enhance = compose(
|
||||
connect(null, mapDispatchToProps),
|
||||
withFetchMore,
|
||||
withVariables,
|
||||
withFragments({
|
||||
root: gql`
|
||||
fragment TalkFeaturedComments_TabPane_root on RootQuery {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
|
||||
class FlagDetails extends Component {
|
||||
render() {
|
||||
const { comment: { actions }, more, data, root, comment } = this.props;
|
||||
const { comment: { actions }, more, root, comment } = this.props;
|
||||
|
||||
const flagActions =
|
||||
actions && actions.filter(a => a.__typename === 'FlagAction');
|
||||
@@ -27,7 +27,6 @@ class FlagDetails extends Component {
|
||||
|
||||
const reasons = Object.keys(summaries);
|
||||
const slotPassthrough = {
|
||||
data,
|
||||
root,
|
||||
comment,
|
||||
};
|
||||
@@ -68,7 +67,6 @@ class FlagDetails extends Component {
|
||||
|
||||
FlagDetails.propTypes = {
|
||||
more: PropTypes.bool,
|
||||
data: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
comment: PropTypes.shape({
|
||||
actions: PropTypes.arrayOf(
|
||||
|
||||
@@ -16,7 +16,6 @@ export default class ModerationActions extends React.Component {
|
||||
comment,
|
||||
root,
|
||||
asset,
|
||||
data,
|
||||
menuVisible,
|
||||
toogleMenu,
|
||||
hideMenu,
|
||||
@@ -25,7 +24,6 @@ export default class ModerationActions extends React.Component {
|
||||
const slotPassthrough = {
|
||||
comment,
|
||||
asset,
|
||||
data,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -72,7 +70,6 @@ ModerationActions.propTypes = {
|
||||
comment: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
asset: PropTypes.object,
|
||||
data: PropTypes.object,
|
||||
menuVisible: PropTypes.bool,
|
||||
toogleMenu: PropTypes.func,
|
||||
hideMenu: PropTypes.func,
|
||||
|
||||
@@ -42,7 +42,6 @@ class ModerationActionsContainer extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<ModerationActions
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
asset={this.props.asset}
|
||||
comment={this.props.comment}
|
||||
|
||||
@@ -50,7 +50,6 @@ class SettingsContainer extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Settings
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
indicateOn={this.indicateOn}
|
||||
indicateOff={this.indicateOff}
|
||||
@@ -72,7 +71,6 @@ class SettingsContainer extends React.Component {
|
||||
}
|
||||
|
||||
SettingsContainer.propTypes = {
|
||||
data: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
updateNotificationSettings: PropTypes.func.isRequired,
|
||||
digestFrequencyValues: PropTypes.array.isRequired,
|
||||
|
||||
@@ -31,9 +31,8 @@ const withViewingOptionsFragments = withFragments({
|
||||
const enhance = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withViewingOptionsFragments,
|
||||
mapProps(({ root, asset, data, ...rest }) => ({
|
||||
mapProps(({ root, asset, ...rest }) => ({
|
||||
slotPassthrough: {
|
||||
data,
|
||||
root,
|
||||
asset,
|
||||
},
|
||||
|
||||
@@ -8677,6 +8677,13 @@ react-apollo@^1.4.12:
|
||||
object-assign "^4.0.1"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-broadcast@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-broadcast/-/react-broadcast-0.6.2.tgz#9555c73b80ca5b2673830872e54f6bb3092cf8a9"
|
||||
dependencies:
|
||||
invariant "^2.2.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-dom@>=0.14.0:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
|
||||
|
||||
Reference in New Issue
Block a user