Merge branch 'extendable-embed-stream-tab' into refactor-configure

This commit is contained in:
Chi Vinh Le
2017-11-16 10:42:15 +01:00
8 changed files with 108 additions and 70 deletions
@@ -5,7 +5,8 @@ import Slot from 'coral-framework/components/Slot';
import {can} from 'coral-framework/services/perms';
import t from 'coral-framework/services/i18n';
import {TabBar, Tab, TabContent, TabPane} from 'coral-ui';
import ExtendableTabPanel from '../containers/ExtendableTabPanel';
import {Tab, TabPane} from 'coral-ui';
import ProfileContainer from 'coral-settings/containers/ProfileContainer';
import Popup from 'coral-framework/components/Popup';
import IfSlotIsNotEmpty from 'coral-framework/components/IfSlotIsNotEmpty';
@@ -28,9 +29,28 @@ export default class Embed extends React.Component {
this.props.setActiveTab(tab);
};
getTabs() {
const {user} = this.props.auth;
const tabs = [
<Tab key='stream' tabId='stream' className='talk-embed-stream-comments-tab'>
{t('embed_comments_tab')}
</Tab>,
<Tab key='profile' tabId='profile' className='talk-embed-stream-profile-tab'>
{t('framework.my_profile')}
</Tab>,
];
if (can(user, 'UPDATE_CONFIG')) {
tabs.push(
<Tab key='config' tabId='config' className='talk-embed-stream-configuration-tab'>
{t('framework.configure_stream')}
</Tab>
);
}
return tabs;
}
render() {
const {activeTab, commentId, root, data, auth: {showSignInDialog, signInDialogFocus}, blurSignInDialog, focusSignInDialog, hideSignInDialog, router: {location: {query: {parentUrl}}}} = this.props;
const {user} = this.props.auth;
const hasHighlightedComment = !!commentId;
return (
@@ -47,44 +67,36 @@ export default class Embed extends React.Component {
onClose={hideSignInDialog}
/>
</IfSlotIsNotEmpty>
<TabBar
onTabClick={this.changeTab}
activeTab={activeTab}
className='talk-embed-stream-tab-bar'
aria-controls='talk-embed-stream-tab-content'
>
<Tab tabId={'stream'} className={'talk-embed-stream-comments-tab'}>
{t('embed_comments_tab')}
</Tab>
<Tab tabId={'profile'} className={'talk-embed-stream-profile-tab'}>
{t('framework.my_profile')}
</Tab>
{can(user, 'UPDATE_CONFIG') &&
<Tab tabId={'config'} className={'talk-embed-stream-configuration-tab'}>
{t('framework.configure_stream')}
</Tab>
}
</TabBar>
<Slot
data={data}
queryData={{root}}
fill="embed"
/>
<TabContent
<ExtendableTabPanel
className='talk-embed-stream-tab-bar'
activeTab={activeTab}
id='talk-embed-stream-tab-content'
>
<TabPane tabId={'stream'} className={'talk-embed-stream-comments-tab-pane'}>
<Stream data={data} root={root} />
</TabPane>
<TabPane tabId={'profile'} className={'talk-embed-stream-profile-tab-pane'}>
<ProfileContainer />
</TabPane>
<TabPane tabId={'config'} className={'talk-embed-stream-configuration-tab-pane'}>
<ConfigureStreamContainer />
</TabPane>
</TabContent>
setActiveTab={this.changeTab}
fallbackTab='stream'
tabSlot='embedStreamTabs'
tabSlotPrepend='embedStreamTabsPrepend'
tabPaneSlot='embedStreamTabPanes'
slotProps={{data}}
queryData={{root}}
tabs={this.getTabs()}
tabPanes={[
<TabPane key='stream' tabId='stream' className='talk-embed-stream-comments-tab-pane'>
<Stream data={data} root={root} />
</TabPane>,
<TabPane key='profile' tabId='profile' className='talk-embed-stream-profile-tab-pane'>
<ProfileContainer />
</TabPane>,
<TabPane key='config' tabId='config' className='talk-embed-stream-configuration-tab-pane'>
<ConfigureStreamContainer />
</TabPane>,
]}
/>
</div>
);
}
@@ -1,9 +1,9 @@
import React from 'react';
import {Spinner, TabBar, TabContent} from 'coral-ui';
import PropTypes from 'prop-types';
import styles from './StreamTabPanel.css';
import styles from './ExtendableTabPanel.css';
class StreamTabPanel extends React.Component {
class ExtendableTabPanel extends React.Component {
render() {
const {activeTab, setActiveTab, tabs, tabPanes, sub, loading, ...rest} = this.props;
@@ -23,7 +23,7 @@ class StreamTabPanel extends React.Component {
}
}
StreamTabPanel.propTypes = {
ExtendableTabPanel.propTypes = {
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
loading: PropTypes.bool,
@@ -39,4 +39,4 @@ StreamTabPanel.propTypes = {
sub: PropTypes.bool,
};
export default StreamTabPanel;
export default ExtendableTabPanel;
@@ -19,7 +19,7 @@ import cn from 'classnames';
import {getTopLevelParent, attachCommentToParent} from '../graphql/utils';
import AllCommentsPane from './AllCommentsPane';
import AutomaticAssetClosure from '../containers/AutomaticAssetClosure';
import StreamTabPanel from '../containers/StreamTabPanel';
import ExtendableTabPanel from '../containers/ExtendableTabPanel';
import styles from './Stream.css';
@@ -106,7 +106,7 @@ class Stream extends React.Component {
);
}
renderTabPanel() {
renderExtendableTabPanel() {
const {
data,
root,
@@ -135,7 +135,7 @@ class Stream extends React.Component {
const slotProps = {data};
const slotQueryData = {root, asset};
// `key` of `StreamTabPanel` depends on sorting so that we always reset
// `key` of `ExtendableTabPanel` depends on sorting so that we always reset
// the state when changing sorting.
return (
<div className={cn('talk-stream-tab-container', styles.tabContainer)}>
@@ -148,23 +148,24 @@ class Stream extends React.Component {
{...slotProps}
/>
</div>
<StreamTabPanel
<ExtendableTabPanel
key={`${sortBy}_${sortOrder}`}
activeTab={activeStreamTab}
setActiveTab={setActiveStreamTab}
fallbackTab={'all'}
tabSlot={'streamTabs'}
tabPaneSlot={'streamTabPanes'}
fallbackTab='all'
tabSlot='streamTabs'
tabSlotPrepend='streamTabsPrepend'
tabPaneSlot='streamTabPanes'
slotProps={slotProps}
queryData={slotQueryData}
loading={loading}
appendTabs={
tabs={
<Tab tabId={'all'} key='all'>
{t('stream.all_comments')} <TabCount active={activeStreamTab === 'all'} sub>{totalCommentCount}</TabCount>
</Tab>
}
appendTabPanes={
<TabPane tabId={'all'} key='all'>
tabPanes={
<TabPane tabId='all' key='all'>
<AllCommentsPane
data={data}
root={root}
@@ -297,7 +298,7 @@ class Stream extends React.Component {
{highlightedComment
? this.renderHighlightedComment()
: this.renderTabPanel()
: this.renderExtendableTabPanel()
}
</div>
);
@@ -325,7 +326,7 @@ Stream.propTypes = {
loading: PropTypes.bool,
editName: PropTypes.func,
appendItemArray: PropTypes.func,
updateItem: PropTypes.func,
updateItem: PropTypes.func,
viewAllComments: PropTypes.func,
notify: PropTypes.func.isRequired,
postComment: PropTypes.func.isRequired,
@@ -151,6 +151,9 @@ const USERNAME_REJECTED_SUBSCRIPTION = gql`
const slots = [
'embed',
'embedStreamTabs',
'embedStreamTabsPrepend',
'embedStreamTabPanes',
];
const EMBED_QUERY = gql`
@@ -1,5 +1,5 @@
import React from 'react';
import StreamTabPanel from '../components/StreamTabPanel';
import ExtendableTabPanel from '../components/ExtendableTabPanel';
import {connect} from 'react-redux';
import omit from 'lodash/omit';
import {Tab, TabPane} from 'coral-ui';
@@ -7,17 +7,17 @@ import {getShallowChanges} from 'coral-framework/utils';
import isEqual from 'lodash/isEqual';
import PropTypes from 'prop-types';
class StreamTabPanelContainer extends React.Component {
class ExtendableTabPanelContainer extends React.Component {
static contextTypes = {
plugins: PropTypes.object,
};
componentDidMount() {
this.fallbackAllTab();
this.handleFallback();
}
componentWillReceiveProps(next) {
this.fallbackAllTab(next);
this.handleFallback(next);
}
shouldComponentUpdate(next) {
@@ -35,22 +35,31 @@ class StreamTabPanelContainer extends React.Component {
return changes.length !== 0;
}
fallbackAllTab(props = this.props) {
if (props.activeTab !== props.fallbackTab) {
const slotPlugins = this.getSlotElements(props.tabSlot, props).map((el) => el.type.talkPluginName);
if (slotPlugins.indexOf(props.activeTab) === -1) {
props.setActiveTab(props.fallbackTab);
}
handleFallback(props = this.props) {
if (this.getTabNames(props).indexOf(props.activeTab) === -1) {
props.setActiveTab(props.fallbackTab);
}
}
getTabNames(props = this.props) {
return this.getTabElements(props).map((el) => el.props.tabId);
}
getSlotElements(slot, props = this.props) {
const {plugins} = this.context;
return plugins.getSlotElements(slot, props.reduxState, props.slotProps, props.queryData);
}
getPluginTabElements(props = this.props) {
return this.getSlotElements(props.tabSlot).map((el) => {
return this.getSlotTabElements(props.tabSlot);
}
getPluginTabElementsPrepend(props = this.props) {
return this.getSlotTabElements(props.tabSlotPrepend);
}
getSlotTabElements(slot) {
return this.getSlotElements(slot).map((el) => {
return (
<Tab tabId={el.type.talkPluginName} key={el.type.talkPluginName}>
{React.cloneElement(el, {active: this.props.activeTab === el.type.talkPluginName})}
@@ -59,6 +68,17 @@ class StreamTabPanelContainer extends React.Component {
});
}
getTabElements(props = this.props) {
const elements = [...this.getPluginTabElementsPrepend(props)];
if (Array.isArray(props.tabs)) {
elements.push(...props.tabs);
} else {
elements.push(props.tabs);
}
elements.push(...this.getPluginTabElements(props));
return elements;
}
getPluginTabPaneElements(props = this.props) {
return this.getSlotElements(props.tabPaneSlot).map((el) => {
return (
@@ -71,12 +91,12 @@ class StreamTabPanelContainer extends React.Component {
render() {
return (
<StreamTabPanel
<ExtendableTabPanel
className={this.props.className}
activeTab={this.props.activeTab}
setActiveTab={this.props.setActiveTab}
tabs={this.getPluginTabElements().concat(this.props.appendTabs)}
tabPanes={this.getPluginTabPaneElements().concat(this.props.appendTabPanes)}
tabs={this.getTabElements()}
tabPanes={this.getPluginTabPaneElements().concat(this.props.tabPanes)}
loading={this.props.loading}
sub={this.props.sub}
/>
@@ -84,19 +104,20 @@ class StreamTabPanelContainer extends React.Component {
}
}
StreamTabPanelContainer.propTypes = {
ExtendableTabPanelContainer.propTypes = {
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
appendTabs: PropTypes.oneOfType([
tabs: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element)
]),
appendTabPanes: PropTypes.oneOfType([
tabPanes: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element)
]),
fallbackTab: PropTypes.string.isRequired,
tabSlot: PropTypes.string.isRequired,
tabSlotPrepend: PropTypes.string.isRequired,
tabPaneSlot: PropTypes.string.isRequired,
slotProps: PropTypes.object.isRequired,
queryData: PropTypes.object,
@@ -109,4 +130,4 @@ const mapStateToProps = (state) => ({
reduxState: omit(state, 'apollo'),
});
export default connect(mapStateToProps, null)(StreamTabPanelContainer);
export default connect(mapStateToProps, null)(ExtendableTabPanelContainer);
@@ -271,6 +271,7 @@ const LOAD_MORE_QUERY = gql`
const slots = [
'streamTabs',
'streamTabsPrepend',
'streamTabPanes',
'streamFilter',
];
@@ -16,7 +16,7 @@ export default {
reducer,
translations,
slots: {
streamTabs: [Tab],
streamTabsPrepend: [Tab],
streamTabPanes: [TabPane],
commentInfoBar: [Tag],
moderationActions: [ModActionButton],
@@ -57,7 +57,7 @@ export default {
}
const comment = findCommentInEmbedQuery(previous, variables.id);
if (previous.asset.comments) {
updated = update(previous, {
asset: {
@@ -101,7 +101,7 @@ export default {
updateQueries: {
CoralEmbedStream_Embed: (previous) => {
let updated = previous;
if (variables.name !== 'FEATURED') {
return;
}