diff --git a/client/coral-admin/src/components/CommentAnimatedEdit.css b/client/coral-admin/src/components/CommentAnimatedEdit.css index 83be36c11..a03f66fc5 100644 --- a/client/coral-admin/src/components/CommentAnimatedEdit.css +++ b/client/coral-admin/src/components/CommentAnimatedEdit.css @@ -1,3 +1,7 @@ +.root { + position: relative; +} + .bodyLeave { position: absolute; width: 100%; diff --git a/client/coral-admin/src/components/CommentAnimatedEdit.js b/client/coral-admin/src/components/CommentAnimatedEdit.js index 141dc12cc..2515d7d94 100644 --- a/client/coral-admin/src/components/CommentAnimatedEdit.js +++ b/client/coral-admin/src/components/CommentAnimatedEdit.js @@ -7,6 +7,7 @@ export default ({children, body}) => { return ( cmp.talkUuid); - const nextUuid = this.getSlotComponents(next.tabSlot, next).map((cmp) => cmp.talkUuid); - return !isEqual(prevUuid, nextUuid); + const prevKeys = this.getSlotElements(this.props.tabSlot, this.props).map((el) => el.key); + const nextKeys = this.getSlotElements(next.tabSlot, next).map((el) => el.key); + return !isEqual(prevKeys, nextKeys); } // Prevent Slot from rerendering when no props has shallowly changed. @@ -37,42 +37,33 @@ class StreamTabPanelContainer extends React.Component { fallbackAllTab(props = this.props) { if (props.activeTab !== props.fallbackTab) { - const slotPlugins = this.getSlotComponents(props.tabSlot, props).map((c) => c.talkPluginName); + const slotPlugins = this.getSlotElements(props.tabSlot, props).map((el) => el.type.talkPluginName); if (slotPlugins.indexOf(props.activeTab) === -1) { props.setActiveTab(props.fallbackTab); } } } - getSlotComponents(slot, props = this.props) { + getSlotElements(slot, props = this.props) { const {plugins} = this.context; - return plugins.getSlotComponents(slot, props.reduxState, props.slotProps, props.queryData); + return plugins.getSlotElements(slot, props.reduxState, props.slotProps, props.queryData); } getPluginTabElements(props = this.props) { - const {plugins} = this.context; - return this.getSlotComponents(props.tabSlot).map((PluginComponent) => { - const pluginProps = plugins.getSlotComponentProps(PluginComponent, props.reduxState, props.slotProps, props.queryData); + return this.getSlotElements(props.tabSlot).map((el) => { return ( - - + + {React.cloneElement(el, {active: this.props.activeTab === el.type.talkPluginName})} ); }); } getPluginTabPaneElements(props = this.props) { - const {plugins} = this.context; - return this.getSlotComponents(props.tabPaneSlot).map((PluginComponent) => { - const pluginProps = plugins.getSlotComponentProps(PluginComponent, props.reduxState, props.slotProps, props.queryData); + return this.getSlotElements(props.tabPaneSlot).map((el) => { return ( - - + + {el} ); }); diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 06f1d4cb7..0fe0d8896 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -20,9 +20,9 @@ class Slot extends React.Component { // it does not result in a change of slot children. const changes = getShallowChanges(this.props, next); if (changes.length === 1 && changes[0] === 'reduxState') { - const prevChildrenUuid = this.getChildren(this.props).map((child) => child.type.talkUuid); - const nextChildrenUuid = this.getChildren(next).map((child) => child.type.talkUuid); - return !isEqual(prevChildrenUuid, nextChildrenUuid); + const prevChildrenKeys = this.getChildren(this.props).map((child) => child.key); + const nextChildrenKeys = this.getChildren(next).map((child) => child.key); + return !isEqual(prevChildrenKeys, nextChildrenKeys); } // Prevent Slot from rerendering when no props has shallowly changed. diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index dbda672ba..c8eb737fd 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -8,7 +8,6 @@ import flatten from 'lodash/flatten'; import mapValues from 'lodash/mapValues'; import {getDisplayName} from 'coral-framework/helpers/hoc'; import camelize from '../helpers/camelize'; -import uuid from 'uuid/v4'; // This is returned for pluginConfig when it is empty. const emptyConfig = {}; @@ -63,9 +62,6 @@ function addMetaDataToSlotComponents(plugins) { // Attach plugin name to the component component.talkPluginName = plugin.name; - - // Attach uuid to the component - component.talkUuid = uuid(); }); }); }); @@ -77,30 +73,8 @@ class PluginsService { addMetaDataToSlotComponents(plugins); } - getSlotComponents(slot, reduxState, props = {}, queryData = {}) { - const pluginConfig = reduxState.config.plugin_config || emptyConfig; - return flatten(this.plugins - - // Filter out components that have slots and have been disabled in `plugin_config` - .filter((o) => o.module.slots && (!pluginConfig || !pluginConfig[o.name] || !pluginConfig[o.name].disable_components)) - - .filter((o) => o.module.slots[slot]) - .map((o) => o.module.slots[slot]) - ) - .filter((component) => { - if(!component.isExcluded) { - return true; - } - let resolvedProps = this.getSlotComponentProps(component, reduxState, props, queryData); - if (component.mapStateToProps) { - resolvedProps = {...resolvedProps, ...component.mapStateToProps(reduxState)}; - } - return !component.isExcluded(resolvedProps); - }); - } - isSlotEmpty(slot, reduxState, props = {}, queryData = {}) { - return this.getSlotComponents(slot, reduxState, props, queryData).length === 0; + return this.getSlotElements(slot, reduxState, props, queryData).length === 0; } /** @@ -124,10 +98,42 @@ class PluginsService { * Returns React Elements for given slot. */ getSlotElements(slot, reduxState, props = {}, queryData = {}) { - return this.getSlotComponents(slot, reduxState, props, queryData) - .map((component, i) => { - return React.createElement(component, {key: i, ...this.getSlotComponentProps(component, reduxState, props, queryData)}); - }); + const pluginConfig = reduxState.config.plugin_config || emptyConfig; + + const isDisabled = (component) => { + if ( + pluginConfig && + pluginConfig[component.talkPluginName] && + pluginConfig[component.talkPluginName].disable_components + ) { + return true; + } + + // Check if component is excluded. + if(component.isExcluded) { + let resolvedProps = this.getSlotComponentProps(component, reduxState, props, queryData); + if (component.mapStateToProps) { + resolvedProps = {...resolvedProps, ...component.mapStateToProps(reduxState)}; + } + return component.isExcluded(resolvedProps); + } + + return false; + }; + + return flatten(this.plugins + .filter((o) => o.module.slots && o.module.slots[slot]) + .map((o) => o.module.slots[slot]) + ) + .map((component, i) => ({ + component, + disabled: isDisabled(component), + key: i, + })) + .filter((o) => !o.disabled) + .map(({component, key}) => + React.createElement(component, {key, ...this.getSlotComponentProps(component, reduxState, props, queryData)}) + ); } getSlotFragments(slot, part) {