diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index fe63b4f30..516e23e50 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -7,6 +7,7 @@ import PropTypes from 'prop-types'; import isEqual from 'lodash/isEqual'; import get from 'lodash/get'; import { getShallowChanges } from 'coral-framework/utils'; +import omit from 'lodash/omit'; const emptyConfig = {}; @@ -32,27 +33,29 @@ class Slot extends React.Component { } getSlotProps(props = this.props) { - const { - fill: _a, - inline: _b, - className: _c, - reduxState: _d, - defaultComponent_: _e, - queryData: _f, - childFactory: _g, - component: _h, - ...rest - } = props; - return rest; + return omit(props, [ + 'fill', + 'inline', + 'className', + 'reduxState', + 'singleSlot', + 'defaultComponent_', + 'queryData', + 'childFactory', + 'component', + ]); } getChildren(props = this.props) { + const { singleSlot = false } = props; const { plugins } = this.context; + return plugins.getSlotElements( props.fill, props.reduxState, this.getSlotProps(props), - props.queryData + props.queryData, + { singleSlot } ); } @@ -109,6 +112,11 @@ Slot.propTypes = { reduxState: PropTypes.object, defaultComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * When true, only the first plugin will take the slot. + */ + singleSlot: PropTypes.bool, + /** * You may specify the component to use as the root wrapper. * Defaults to 'div'. diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 6f99a2291..03e3177e0 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -94,11 +94,19 @@ class PluginsService { }; } + getSlotElement(slot, reduxState, props = {}, queryData = {}, options = {}) { + return this.getSlotElements(slot, reduxState, props, queryData, { + ...options, + singleSlot: true, + }); + } + /** * Returns React Elements for given slot. */ - getSlotElements(slot, reduxState, props = {}, queryData = {}) { + getSlotElements(slot, reduxState, props = {}, queryData = {}, options = {}) { const pluginConfig = get(reduxState, 'config.plugin_config') || emptyConfig; + const { singleSlot = false } = options; const isDisabled = component => { if ( @@ -129,11 +137,13 @@ class PluginsService { return false; }; - return flatten( + const slots = flatten( this.plugins .filter(o => o.module.slots && o.module.slots[slot]) .map(o => o.module.slots[slot]) - ) + ); + + return (singleSlot ? slots.slice(0, 1) : slots) .map((component, i) => ({ component, disabled: isDisabled(component),