connect aware "excludeIf" using our own hoc

This commit is contained in:
Chi Vinh Le
2017-07-17 18:06:51 +07:00
parent 4dd03508ee
commit d2e6a98d46
8 changed files with 54 additions and 19 deletions
@@ -75,7 +75,7 @@ class Stream extends React.Component {
viewAllComments,
auth: {loggedIn, user},
removeTag,
pluginConfig,
reduxState,
editName
} = this.props;
const {keepCommentBox} = this.state;
@@ -209,7 +209,7 @@ class Stream extends React.Component {
<Slot fill="streamFilter" />
</div>
<TabBar activeTab={activeStreamTab} onTabClick={setActiveStreamTab} sub>
{getSlotComponents('streamTabs', pluginConfig, streamTabProps).map((PluginComponent) => (
{getSlotComponents('streamTabs', reduxState, streamTabProps).map((PluginComponent) => (
<Tab tabId={PluginComponent.talkPluginName} key={PluginComponent.talkPluginName}>
<PluginComponent
{...streamTabProps}
@@ -222,7 +222,7 @@ class Stream extends React.Component {
</Tab>
</TabBar>
<TabContent activeTab={activeStreamTab} sub>
{getSlotComponents('streamTabPanes', pluginConfig, streamTabProps).map((PluginComponent) => (
{getSlotComponents('streamTabPanes', reduxState, streamTabProps).map((PluginComponent) => (
<TabPane tabId={PluginComponent.talkPluginName} key={PluginComponent.talkPluginName}>
<PluginComponent
{...streamTabProps}
@@ -25,6 +25,7 @@ import {
insertFetchedCommentsIntoEmbedQuery,
nest,
} from '../graphql/utils';
import omit from 'lodash/omit';
const {showSignInDialog} = authActions;
const {addNotification} = notificationActions;
@@ -312,6 +313,7 @@ const mapStateToProps = (state) => ({
previousStreamTab: state.stream.previousTab,
commentClassNames: state.stream.commentClassNames,
pluginConfig: state.config.plugin_config,
reduxState: omit(state, 'apollo'),
});
const mapDispatchToProps = (dispatch) =>
@@ -2,11 +2,12 @@ import React from 'react';
import {connect} from 'react-redux';
import {isSlotEmpty} from 'coral-framework/helpers/plugins';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
function IfSlotIsEmpty({slot, className, pluginConfig, component: Component = 'div', children, ...rest}) {
function IfSlotIsEmpty({slot, className, reduxState, component: Component = 'div', children, ...rest}) {
return (
<Component className={className}>
{isSlotEmpty(slot, pluginConfig, rest) ? children : null}
{isSlotEmpty(slot, reduxState, rest) ? children : null}
</Component>
);
}
@@ -16,7 +17,9 @@ IfSlotIsEmpty.propTypes = {
className: PropTypes.string,
};
const mapStateToProps = (state) => ({pluginConfig: state.config.plugin_config});
const mapStateToProps = (state) => ({
reduxState: omit(state, 'apollo'),
});
export default connect(mapStateToProps, null)(IfSlotIsEmpty);
@@ -2,11 +2,12 @@ import React from 'react';
import {connect} from 'react-redux';
import {isSlotEmpty} from 'coral-framework/helpers/plugins';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
function IfSlotIsNotEmpty({slot, className, pluginConfig, component: Component = 'div', children, ...rest}) {
function IfSlotIsNotEmpty({slot, className, reduxState, component: Component = 'div', children, ...rest}) {
return (
<Component className={className}>
{!isSlotEmpty(slot, pluginConfig, rest) ? children : null}
{!isSlotEmpty(slot, reduxState, rest) ? children : null}
</Component>
);
}
@@ -16,7 +17,9 @@ IfSlotIsNotEmpty.propTypes = {
className: PropTypes.string,
};
const mapStateToProps = (state) => ({pluginConfig: state.config.plugin_config});
const mapStateToProps = (state) => ({
reduxState: omit(state, 'apollo'),
});
export default connect(mapStateToProps, null)(IfSlotIsNotEmpty);
+7 -3
View File
@@ -3,9 +3,11 @@ import cn from 'classnames';
import styles from './Slot.css';
import {connect} from 'react-redux';
import {getSlotElements} from 'coral-framework/helpers/plugins';
import omit from 'lodash/omit';
function Slot ({fill, inline = false, className, pluginConfig = {}, defaultComponent: DefaultComponent, ...rest}) {
let children = getSlotElements(fill, pluginConfig, rest);
function Slot ({fill, inline = false, className, reduxState, defaultComponent: DefaultComponent, ...rest}) {
let children = getSlotElements(fill, reduxState, rest);
const pluginConfig = reduxState.config.pluginConfig || {};
if (children.length === 0 && DefaultComponent) {
children = <DefaultComponent {...rest} />;
}
@@ -21,7 +23,9 @@ Slot.propTypes = {
fill: React.PropTypes.string
};
const mapStateToProps = (state) => ({pluginConfig: state.config.plugin_config});
const mapStateToProps = (state) => ({
reduxState: omit(state, 'apollo'),
});
export default connect(mapStateToProps, null)(Slot);
+17 -6
View File
@@ -10,7 +10,8 @@ import {loadTranslations} from 'coral-framework/services/i18n';
import {injectReducers} from 'coral-framework/services/store';
import camelize from './camelize';
export function getSlotComponents(slot, pluginConfig, props = {}) {
export function getSlotComponents(slot, reduxState, props = {}) {
const pluginConfig = reduxState.config.pluginConfig || {};
return flatten(plugins
// Filter out components that have slots and have been disabled in `plugin_config`
@@ -19,18 +20,28 @@ export function getSlotComponents(slot, pluginConfig, props = {}) {
.filter((o) => o.module.slots[slot])
.map((o) => o.module.slots[slot])
)
.filter((component) => !component.isExcluded || !component.isExcluded({...props, config: pluginConfig}));
.filter((component) => {
if(!component.isExcluded) {
return true;
}
let resolvedProps = {...props, config: pluginConfig};
if (component.mapStateToProps) {
resolvedProps = {...resolvedProps, ...component.mapStateToProps(reduxState)};
}
return !component.isExcluded(resolvedProps);
});
}
export function isSlotEmpty(slot, pluginConfig, props) {
return getSlotComponents(slot, pluginConfig, props).length === 0;
export function isSlotEmpty(slot, reduxState, props) {
return getSlotComponents(slot, reduxState, props).length === 0;
}
/**
* Returns React Elements for given slot.
*/
export function getSlotElements(slot, pluginConfig, props = {}) {
return getSlotComponents(slot, pluginConfig, props)
export function getSlotElements(slot, reduxState, props = {}) {
const pluginConfig = reduxState.config.pluginConfig || {};
return getSlotComponents(slot, reduxState, props)
.map((component, i) => React.createElement(component, {key: i, ...props, config: pluginConfig}));
}
+6
View File
@@ -0,0 +1,6 @@
import {connect} from 'react-redux';
export default (mapStateToProps, ...rest) => (BaseComponent) => {
BaseComponent.mapStateToProps = mapStateToProps;
return connect(mapStateToProps, ...rest)(BaseComponent);
};
@@ -1,10 +1,14 @@
import {compose, gql} from 'react-apollo';
import withFragments from 'coral-framework/hocs/withFragments';
import excludeIf from 'coral-framework/hocs/excludeIf';
import connect from 'coral-framework/hocs/connect';
import Tab from '../components/Tab';
// TODO: This is just example code, and needs to replaced by an actual implementation.
const enhance = compose(
connect((state) => ({
stream: state.stream,
})),
withFragments({
asset: gql`
fragment TalkFeatured_Tab_asset on Asset {
@@ -13,7 +17,9 @@ const enhance = compose(
}
}`,
}),
excludeIf((props) => props.asset.recentComments.length === 0)
excludeIf((props) => {
return props.asset.recentComments.length === 0;
})
);
export default enhance(Tab);