diff --git a/.gitignore b/.gitignore index 6f3104629..1235e0db0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ npm-debug.log* dump.rdb client/coral-framework/graphql/introspection.json +docs/source/_data/introspection.json .env *.cfg diff --git a/client/coral-embed-stream/src/containers/ExtendableTabPanel.js b/client/coral-embed-stream/src/containers/ExtendableTabPanel.js index 678981a8e..c2935b152 100644 --- a/client/coral-embed-stream/src/containers/ExtendableTabPanel.js +++ b/client/coral-embed-stream/src/containers/ExtendableTabPanel.js @@ -35,12 +35,9 @@ class ExtendableTabPanelContainer extends React.Component { createPluginTabFactory = (props = this.props) => el => { return ( - + {React.cloneElement(el, { - active: props.activeTab === el.type.talkPluginName, + active: props.activeTab === el.key, })} ); @@ -59,7 +56,7 @@ class ExtendableTabPanelContainer extends React.Component { createPluginTabPane(el) { return ( - + {el} ); diff --git a/client/coral-framework/services/i18n.js b/client/coral-framework/services/i18n.js index 1468f92eb..9c65c9c4e 100644 --- a/client/coral-framework/services/i18n.js +++ b/client/coral-framework/services/i18n.js @@ -136,6 +136,7 @@ export function t(key, ...replacements) { replacements.forEach((str, i) => { translation = translation.replace(new RegExp(`\\{${i}\\}`, 'g'), str); }); + return translation; } else { console.warn(`${lang}.${key} and en.${key} language key not set`); diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index bb16fc5e7..a25e27b76 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -173,11 +173,30 @@ class PluginsService { ); } + /** + * This adds a consistent keying for the slot elements. + * It uses the plugin name as the key. If the same plugin inserts + * multiple elements it will append `.${noOfOccurence}` to the + * key starting with the second element. + */ + const getKey = (() => { + const map = {}; + return component => { + if (map[component.talkPluginName] === undefined) { + map[component.talkPluginName] = 0; + } else { + map[component.talkPluginName]++; + } + const i = map[component.talkPluginName]; + return `${component.talkPluginName}${i > 0 ? `.${i}` : ''}`; + }; + })(); + return (size > 0 ? slots.slice(0, size) : slots) - .map((component, i) => ({ + .map(component => ({ component, disabled: isDisabled(component), - key: i, + key: getKey(component), })) .filter(o => !o.disabled) .map(({ component, key }) => diff --git a/plugins/talk-plugin-auth/client/login/components/SignUp.js b/plugins/talk-plugin-auth/client/login/components/SignUp.js index 61c4d0b1d..cc49e7391 100644 --- a/plugins/talk-plugin-auth/client/login/components/SignUp.js +++ b/plugins/talk-plugin-auth/client/login/components/SignUp.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Slot } from 'plugin-api/beta/client/components'; import { Button, TextField, @@ -28,6 +29,15 @@ class SignUp extends React.Component { this.props.onSubmit(); }; + childFactory = el => { + const key = el.key; + const props = { + indicateBlocker: () => this.props.indicateBlocker(key), + indicateBlockerResolved: () => this.props.indicateBlockerResolved(key), + }; + return React.cloneElement(el, props); + }; + render() { const { username, @@ -42,6 +52,7 @@ class SignUp extends React.Component { errorMessage, requireEmailConfirmation, success, + blocked, } = this.props; return ( @@ -103,6 +114,10 @@ class SignUp extends React.Component { onChange={this.handlePasswordRepeatChange} minLength="8" /> +
@@ -161,6 +177,9 @@ SignUp.propTypes = { errorMessage: PropTypes.string, requireEmailConfirmation: PropTypes.bool.isRequired, success: PropTypes.bool.isRequired, + blocked: PropTypes.bool.isRequired, + indicateBlocker: PropTypes.func.isRequired, + indicateBlockerResolved: PropTypes.func.isRequired, }; export default SignUp; diff --git a/plugins/talk-plugin-auth/client/login/containers/SignUp.js b/plugins/talk-plugin-auth/client/login/containers/SignUp.js index 609102ebc..f7fc6f2d2 100644 --- a/plugins/talk-plugin-auth/client/login/containers/SignUp.js +++ b/plugins/talk-plugin-auth/client/login/containers/SignUp.js @@ -16,8 +16,19 @@ class SignUpContainer extends Component { emailError: null, passwordError: null, passwordRepeatError: null, + blockers: [], }; + indicateBlocker = key => + this.setState(state => ({ + blockers: state.blockers.concat(key), + })); + + indicateBlockerResolved = key => + this.setState(state => ({ + blockers: state.blockers.filter(i => i !== key), + })); + validate = data => { let valid = true; const changes = {}; @@ -48,7 +59,7 @@ class SignUpContainer extends Component { passwordRepeat: this.state.passwordRepeat, }; - if (this.validate(data)) { + if (this.validate(data) && !this.state.blockers.length) { this.props.signUp(data); } }; @@ -76,6 +87,9 @@ class SignUpContainer extends Component { render() { return ( { - const pluginName = el.type.talkPluginName; + const key = el.key; const props = { - indicateOn: () => this.props.indicateOn(pluginName), - indicateOff: () => this.props.indicateOff(pluginName), + indicateOn: () => this.props.indicateOn(key), + indicateOff: () => this.props.indicateOff(key), }; return React.cloneElement(el, props); }; diff --git a/plugins/talk-plugin-notifications/client/containers/Settings.js b/plugins/talk-plugin-notifications/client/containers/Settings.js index 5862650ec..a3d9c12e0 100644 --- a/plugins/talk-plugin-notifications/client/containers/Settings.js +++ b/plugins/talk-plugin-notifications/client/containers/Settings.js @@ -20,14 +20,14 @@ class SettingsContainer extends React.Component { turnOffInput: {}, }; - indicateOn = plugin => + indicateOn = key => this.setState(state => ({ - hasNotifications: state.hasNotifications.concat(plugin), + hasNotifications: state.hasNotifications.concat(key), })); - indicateOff = plugin => + indicateOff = key => this.setState(state => ({ - hasNotifications: state.hasNotifications.filter(i => i !== plugin), + hasNotifications: state.hasNotifications.filter(i => i !== key), })); setTurnOffInputFragment = fragment =>