Implement streamTabs and streamTabPanes slot

This commit is contained in:
Chi Vinh Le
2017-07-10 20:46:28 +07:00
parent aac47c4686
commit ab72995a2c
15 changed files with 161 additions and 13 deletions
+1
View File
@@ -13,4 +13,5 @@ plugins/*
!plugins/coral-plugin-viewing-options
!plugins/coral-plugin-comment-content
!plugins/talk-plugin-permalink
!plugins/talk-plugin-featured
node_modules
+1
View File
@@ -26,5 +26,6 @@ plugins/*
!plugins/coral-plugin-viewing-options
!plugins/coral-plugin-comment-content
!plugins/talk-plugin-permalink
!plugins/talk-plugin-featured
**/node_modules/*
@@ -9,6 +9,7 @@ import {ModerationLink} from 'coral-plugin-moderation';
import RestrictedMessageBox
from 'coral-framework/components/RestrictedMessageBox';
import t, {timeago} from 'coral-framework/services/i18n';
import {getSlotComponents} from 'coral-framework/helpers/plugins';
import CommentBox from 'coral-plugin-commentbox/CommentBox';
import QuestionBox from 'coral-plugin-questionbox/QuestionBox';
import {Button, TabBar, Tab, TabCount, TabContent, TabPane} from 'coral-ui';
@@ -202,17 +203,30 @@ class Stream extends React.Component {
<Slot fill="streamFilter" />
</div>
<TabBar activeTab={activeStreamTab} onTabClick={setActiveStreamTab} sub>
<Tab tabId={'featured'}>
Featured
</Tab>
{getSlotComponents('streamTabs').map((PluginComponent) => (
<Tab tabId={PluginComponent.talkPluginName} key={PluginComponent.talkPluginName}>
<PluginComponent
active={activeStreamTab === PluginComponent.talkPluginName}
data={data}
root={root}
asset={asset}
/>
</Tab>
))}
<Tab tabId={'all'}>
All Comments <TabCount active={activeStreamTab === 'all'} sub>{totalCommentCount}</TabCount>
</Tab>
</TabBar>
<TabContent activeTab={activeStreamTab} sub>
<TabPane tabId={'featured'}>
TODO
</TabPane>
{getSlotComponents('streamTabPanes').map((PluginComponent) => (
<TabPane tabId={PluginComponent.talkPluginName} key={PluginComponent.talkPluginName}>
<PluginComponent
data={data}
root={root}
asset={asset}
/>
</TabPane>
))}
<TabPane tabId={'all'}>
<AllCommentsPane
data={data}
@@ -14,6 +14,7 @@ import {setActiveReplyBox, setActiveTab, viewAllComments} from '../actions/strea
import Stream from '../components/Stream';
import Comment from './Comment';
import {withFragments} from 'coral-framework/hocs';
import {getSlotsFragments} from 'coral-framework/helpers/plugins';
import {Spinner} from 'coral-ui';
import {getDefinitionName} from 'coral-framework/utils';
import {
@@ -240,6 +241,11 @@ const LOAD_MORE_QUERY = gql`
${Comment.fragments.comment}
`;
const pluginFragments = getSlotsFragments([
'streamTabs',
'streamTabPanes',
]);
const fragments = {
root: gql`
fragment CoralEmbedStream_Stream_root on RootQuery {
@@ -281,6 +287,7 @@ const fragments = {
startCursor
endCursor
}
${pluginFragments.spreads('asset')}
}
me {
status
@@ -291,8 +298,11 @@ const fragments = {
settings {
organizationName
}
${pluginFragments.spreads('root')}
...${getDefinitionName(Comment.fragments.root)}
}
${pluginFragments.definitions('asset')}
${pluginFragments.definitions('root')}
${Comment.fragments.root}
${commentFragment}
`,
+20 -6
View File
@@ -10,17 +10,16 @@ import {loadTranslations} from 'coral-framework/services/i18n';
import {injectReducers, getStore} from 'coral-framework/services/store';
import camelize from './camelize';
function getSlotComponents(slot) {
export function getSlotComponents(slot) {
const pluginConfig = getStore().getState().config.plugin_config;
// Filter out components that have been disabled in `plugin_config`
return flatten(plugins
// Filter out components that have been disabled in `plugin_config`
.filter((o) => !pluginConfig || !pluginConfig[o.plugin] || !pluginConfig[o.plugin].disable_components)
.filter((o) => !pluginConfig || !pluginConfig[o.name] || !pluginConfig[o.name].disable_components)
.filter((o) => o.module.slots[slot])
.map((o) => o.module.slots[slot]));
.map((o) => o.module.slots[slot])
);
}
export function isSlotEmpty(slot) {
@@ -113,7 +112,22 @@ export function injectPluginsReducers() {
const reducers = merge(
...plugins
.filter((o) => o.module.reducer)
.map((o) => ({[camelize(o.plugin)] : o.module.reducer}))
.map((o) => ({[camelize(o.name)] : o.module.reducer}))
);
injectReducers(reducers);
}
function addMetaDataToSlotComponents() {
// Add talkPluginName to Slot Components.
plugins.forEach((plugin) => {
const slots = plugin.module.slots;
slots && Object.keys(slots).forEach((slot) => {
slots[slot].forEach((component) => {
component.talkPluginName = plugin.name;
});
});
});
}
addMetaDataToSlotComponents();
@@ -22,7 +22,7 @@ module.exports = function(source) {
const config = this.exec(source, this.resourcePath);
const plugins = getPluginList(config).map((plugin) => `{
module: require('${plugin}/client'),
plugin: '${plugin}'
name: '${plugin}'
}`);
return stripIndent`
+1
View File
@@ -60,6 +60,7 @@
font-weight: bold;
border-bottom: solid 3px #10589b;
margin-bottom: 0px;
padding: 6px 10px;
}
.root:only-child .button, .rootSub:only-child .buttonSub {
@@ -0,0 +1,14 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
@@ -0,0 +1,23 @@
{
"env": {
"browser": true,
"es6": true,
"mocha": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
}
},
"parser": "babel-eslint",
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
@@ -0,0 +1,8 @@
import React from 'react';
import {TabCount} from 'plugin-api/beta/client/components/ui';
export default ({active, asset: {recentComments}}) => (
<span>
Featured <TabCount active={active} sub>{recentComments.length}</TabCount>
</span>
);
@@ -0,0 +1,14 @@
import React from 'react';
export default ({asset: {recentComments}}) => (
<div>
{recentComments.map((comment) => (
<p key={comment.id}>
<div><strong>{comment.user.username}</strong></div>
<div>
{comment.body}
</div>
</p>
))}
</div>
);
@@ -0,0 +1,16 @@
import {compose, gql} from 'react-apollo';
import withFragments from 'coral-framework/hocs/withFragments';
import Tab from '../components/Tab';
const enhance = compose(
withFragments({
asset: gql`
fragment TalkFeatured_Tab_asset on Asset {
recentComments {
id
}
}`,
}),
);
export default enhance(Tab);
@@ -0,0 +1,21 @@
import {compose, gql} from 'react-apollo';
import withFragments from 'coral-framework/hocs/withFragments';
import TabPane from '../components/TabPane';
const enhance = compose(
withFragments({
asset: gql`
fragment TalkFeatured_TabPane_asset on Asset {
recentComments {
id
body
user {
id
username
}
}
}`,
}),
);
export default enhance(TabPane);
@@ -0,0 +1,9 @@
import Tab from './containers/Tab';
import TabPane from './containers/TabPane';
export default {
slots: {
streamTabs: [Tab],
streamTabPanes: [TabPane],
}
};
+2
View File
@@ -0,0 +1,2 @@
module.exports = {};