From 5e2d7cc38d127fab2539077976fea846639d0549 Mon Sep 17 00:00:00 2001 From: Jean-Michel FRANCOIS Date: Tue, 2 May 2017 16:09:22 +0200 Subject: [PATCH] chore(ActionBar): improve composition using props.renderers map (#414) this can be used as an example to let pass custom component with the renderers props --- .../src/ActionBar/ActionBar.component.js | 46 ++++++++++++++++--- .../src/ActionBar/ActionBar.test.js | 30 ++++++++++++ .../ActionBar.snapshot.test.js.snap | 10 ++++ .../__snapshots__/ActionBar.test.js.snap | 9 ++++ .../containers/src/Action/Action.component.js | 2 + .../src/ActionBar/ActionBar.container.js | 10 +++- .../__snapshots__/ActionBar.test.js.snap | 8 ++++ .../src/Actions/Actions.component.js | 2 + 8 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 packages/components/src/ActionBar/__snapshots__/ActionBar.test.js.snap diff --git a/packages/components/src/ActionBar/ActionBar.component.js b/packages/components/src/ActionBar/ActionBar.component.js index 20e973c1972..2f4b9c9168a 100644 --- a/packages/components/src/ActionBar/ActionBar.component.js +++ b/packages/components/src/ActionBar/ActionBar.component.js @@ -20,6 +20,17 @@ const actionsShape = { children: PropTypes.node, }; +function getRenderers(props) { + return Object.assign( + { + Action, + Actions, + ActionSplitDropdown, + }, + props ? props.renderers : {}, + ); +} + function getActionsToRender({ selected, actions, multiSelectActions }) { if (selected > 0) { return multiSelectActions || {}; @@ -57,7 +68,8 @@ Content.propTypes = { tag: PropTypes.oneOf(['p', 'button', 'form', 'a', 'div']), }; -function SwitchActions({ actions, left, right, selected }) { +function SwitchActions({ actions, left, right, selected, renderers }) { + const Renderers = getRenderers({ renderers }); return ( { selected > 0 && !right ? ( @@ -68,15 +80,15 @@ function SwitchActions({ actions, left, right, selected }) { switch (displayMode) { case DISPLAY_MODES.SPLIT_DROPDOWN: return ( - + ); case DISPLAY_MODES.BTN_GROUP: return ( - + ); default: return ( - + ); } }) } @@ -88,6 +100,13 @@ SwitchActions.propTypes = { left: PropTypes.bool, right: PropTypes.bool, selected: PropTypes.number, + renderers: PropTypes.shape( + { + Action: PropTypes.func, + Actions: PropTypes.func, + ActionSplitDropdown: PropTypes.func, + } + ), }; SwitchActions.defaultProps = { actions: [], @@ -118,11 +137,23 @@ function ActionBar(props) { return ( ); @@ -132,12 +163,15 @@ ActionBar.propTypes = { selected: PropTypes.number, children: PropTypes.node, className: PropTypes.string, + renderers: PropTypes.shape(SwitchActions.propTypes.renderers), }; +ActionBar.displayName = 'ActionBar'; ActionBar.DISPLAY_MODES = DISPLAY_MODES; ActionBar.Count = Count; ActionBar.SwitchActions = SwitchActions; ActionBar.getActionsToRender = getActionsToRender; ActionBar.Content = Content; ActionBar.getContentClassName = getContentClassName; +ActionBar.getRenderers = getRenderers; export default ActionBar; diff --git a/packages/components/src/ActionBar/ActionBar.test.js b/packages/components/src/ActionBar/ActionBar.test.js index c7599ae3790..977c51af7e1 100644 --- a/packages/components/src/ActionBar/ActionBar.test.js +++ b/packages/components/src/ActionBar/ActionBar.test.js @@ -26,4 +26,34 @@ describe('ActionBar', () => { // then expect(onClickMock).toHaveBeenCalled(); }); + + it('should support custom renderers', () => { + // given + function MyAction(props) { + return (
); + } + const props = { + selected: 0, + actions: { + left: [ + { label: 'Preparations', icon: 'talend-preparation' }, + ], + }, + renderers: { + Action: MyAction, + }, + }; + + // when + const actionBar = ( + + ); + const wrapper = mount(actionBar); + const render = wrapper.find('.my-custom-action').first(); + + // then + expect(render.hasClass('my-custom-action')).toBe(true); + expect(render.name()).toBe('div'); + expect(render.props()).toMatchSnapshot(); + }); }); diff --git a/packages/components/src/ActionBar/__snapshots__/ActionBar.snapshot.test.js.snap b/packages/components/src/ActionBar/__snapshots__/ActionBar.snapshot.test.js.snap index 14ea56c7f0f..397ed532c3e 100644 --- a/packages/components/src/ActionBar/__snapshots__/ActionBar.snapshot.test.js.snap +++ b/packages/components/src/ActionBar/__snapshots__/ActionBar.snapshot.test.js.snap @@ -27,6 +27,7 @@ exports[`ActionBar should render a btn-group 1`] = ` ] } left={true} + renderers={undefined} selected={undefined} /> @@ -70,6 +71,7 @@ exports[`ActionBar should render no-selected actions, all on left 1`] = ` ] } left={true} + renderers={undefined} selected={0} /> @@ -112,6 +114,7 @@ exports[`ActionBar should render no-selected actions, all on right 1`] = ` }, ] } + renderers={undefined} right={true} selected={0} /> @@ -134,6 +137,7 @@ exports[`ActionBar should render no-selected actions, some on left, the other on ] } left={true} + renderers={undefined} selected={0} /> @@ -206,6 +211,7 @@ exports[`ActionBar should render selected count and multi-selected actions, all ] } left={true} + renderers={undefined} selected={1} /> @@ -218,6 +224,7 @@ exports[`ActionBar should render selected count and multi-selected actions, all @@ -273,6 +281,7 @@ exports[`ActionBar should render selected count and multi-selected actions, coun ] } left={true} + renderers={undefined} selected={1} /> diff --git a/packages/components/src/ActionBar/__snapshots__/ActionBar.test.js.snap b/packages/components/src/ActionBar/__snapshots__/ActionBar.test.js.snap new file mode 100644 index 00000000000..af64b7c4729 --- /dev/null +++ b/packages/components/src/ActionBar/__snapshots__/ActionBar.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ActionBar should support custom renderers 1`] = ` +Object { + "className": "my-custom-action", + "icon": "talend-preparation", + "label": "Preparations", +} +`; diff --git a/packages/containers/src/Action/Action.component.js b/packages/containers/src/Action/Action.component.js index 4196c56c710..82f119d8e9f 100644 --- a/packages/containers/src/Action/Action.component.js +++ b/packages/containers/src/Action/Action.component.js @@ -28,4 +28,6 @@ Action.contextTypes = { registry: PropTypes.object, }; +Action.displayName = 'CMFContainer(Action)'; + export default Action; diff --git a/packages/containers/src/ActionBar/ActionBar.container.js b/packages/containers/src/ActionBar/ActionBar.container.js index 01f16cd19c4..cae860b6ab6 100644 --- a/packages/containers/src/ActionBar/ActionBar.container.js +++ b/packages/containers/src/ActionBar/ActionBar.container.js @@ -1,7 +1,8 @@ import React, { PropTypes } from 'react'; - import { ActionBar as Component } from 'react-talend-components'; import { getActionsProps } from '../actionAPI'; +import Action from '../Action'; +import Actions from '../Actions'; function getActions(context, idOrInfo, model) { if (typeof idOrInfo === 'string') { @@ -35,6 +36,10 @@ function ActionBar({ actions, actionIds, ...props }, context) { return ( ); @@ -49,6 +54,9 @@ const actionPropTypes = PropTypes.oneOfType([ }), ]); +Object.keys(Component).forEach((key) => { + ActionBar[key] = Component[key]; +}); ActionBar.displayName = 'CMFContainer(ActionBar)'; ActionBar.propTypes = { ...Component.propTypes, diff --git a/packages/containers/src/ActionBar/__snapshots__/ActionBar.test.js.snap b/packages/containers/src/ActionBar/__snapshots__/ActionBar.test.js.snap index 8db38692675..d64d5517d8e 100644 --- a/packages/containers/src/ActionBar/__snapshots__/ActionBar.test.js.snap +++ b/packages/containers/src/ActionBar/__snapshots__/ActionBar.test.js.snap @@ -89,6 +89,10 @@ Object { }, ], }, + "renderers": Object { + "Action": [Function], + "Actions": [Function], + }, } `; @@ -144,5 +148,9 @@ Object { }, ], }, + "renderers": Object { + "Action": [Function], + "Actions": [Function], + }, } `; diff --git a/packages/containers/src/Actions/Actions.component.js b/packages/containers/src/Actions/Actions.component.js index eb530a2575d..652398a9824 100644 --- a/packages/containers/src/Actions/Actions.component.js +++ b/packages/containers/src/Actions/Actions.component.js @@ -32,4 +32,6 @@ Actions.contextTypes = { store: React.PropTypes.object, }; +Actions.displayName = 'CMF(Actions)'; + export default Actions;