UNPKG

@talend/react-containers

Version:

Provide connected components aka containers for @talend/react-cmf based on @talend/react-components.

172 lines (167 loc) 5.65 kB
import cmf, { cmfConnect } from '@talend/react-cmf'; import { ACTION_TYPE_LINK } from './constants'; import Container, { DEFAULT_STATE } from './SidePanel.container'; import { get } from "lodash"; const cache = {}; /** * return the cache structure to support one cache per componentId * @param componentId used to create entry in the cache * @param currentRoute used as cache key * @param actions the current actions used as cacheKey by reference */ function getCache(componentId = 'default', currentRoute, actions) { if (!cache[componentId]) { cache[componentId] = {}; } if (cache[componentId].route !== currentRoute || cache[componentId].actions !== actions) { // invalidate the cache cache[componentId] = { route: currentRoute, actions }; } return cache[componentId]; } /** * This function check if our current action point to a route which is the parent of the current * @param {string} actionPath the path of the action * @param {string} currentPath the pathname in the browser location */ function isBasePathOf(actionPath, currentPath) { const length = actionPath.length; if (currentPath.length + 1 === length) { return `${currentPath}/` === actionPath; } if (currentPath.length === length) { return currentPath === actionPath; } if (currentPath.length < length) { return false; } return actionPath === currentPath.slice(0, length) && ['/', '#'].includes(currentPath[length]); } /** * This function use on each action the attribute href to build the onClick * @param {Array} actions the list of all Action props you want. * @return a new actions Array ready to be used by the SidePanel */ function getActionsWrapped(actions) { return actions.map(action => { if (action.href && !action.onClick && !action.onClickDispatch && !action.onClickActionCreator) { return { ...action, onClick: event => { if (!event.metaKey && !event.ctrlKey) { event.preventDefault(); event.stopPropagation(); } }, onClickDispatch: { type: ACTION_TYPE_LINK, cmf: { routerPush: action.href } } }; } return action; }); } function getSelectedAction(currentRoute, actions) { const getFullPath = href => { if (!window.basename || window.basename === '/' || href.startsWith(window.basename)) { return href; } return `${window.basename || ''}${href}`.replaceAll('//', '/'); }; return actions.find(action => action.href && isBasePathOf(getFullPath(action.href), currentRoute)); } /** * DEPRECATED: This is kept to not create any breaking change. * This function use the deprecated api `cmf.action.getActionInfo` * @param {string} id the action id you want to get in your settings * @param {string} currentRoute the pathname in the browser location * @param {Object} state redux state to create fake context for getActionInfo * @return a new actions Array ready to be used by the SidePanel */ function getAction(id, currentRoute, state) { const action = { actionId: id }; const info = cmf.action.getActionInfo({ registry: cmf.registry.getRegistry(), store: { getState: () => state } }, id); action.label = info.label; action.id = info.id; const route = get(info, 'payload.cmf.routerReplace', get(info, 'payload.cmf.routerPush', get(info, 'href'))); if (route && isBasePathOf(route, currentRoute)) { action.active = true; } return action; } /** * This function take care of perfomance to ensure we give the same array of actions * if we are on the same route for the same component with the same props * @param {Object} state the redux state * @param {Object} ownProps the props applied to the current component instance * @param {string} currentRoute the pathname in the browser location * @return {Array} array of actions ready for the sidepanel and cached to keep good performance */ function getActions(state, ownProps, currentRoute) { if (ownProps.actions) { let actions = ownProps.actions; if (window.basename && window.basename !== '/') { actions = ownProps.actions.map(action => ({ ...action, href: `${window.basename}${action.href}`.replaceAll('//', '/') })); } const cacheAction = getCache(ownProps.componentId, currentRoute, actions); if (!cacheAction.value) { cacheAction.value = getActionsWrapped(actions); } return cacheAction.value; } else if (ownProps.actionIds) { const cacheAction = getCache(ownProps.componentId, currentRoute, ownProps.actionIds); if (!cacheAction.value) { cacheAction.value = ownProps.actionIds.map(id => getAction(id, currentRoute, state)); } return cacheAction.value; } return undefined; } export function mapStateToProps(state, ownProps) { const props = {}; const currentRoute = window.location.pathname; props.actions = getActions(state, ownProps, currentRoute); if (ownProps.actions) { props.selected = getSelectedAction(currentRoute, props.actions); } return props; } export function mergeProps(stateProps, dispatchProps, ownProps) { const props = { ...ownProps, ...stateProps, ...dispatchProps }; if (props.actionIds) { delete props.actionIds; } return props; } export default cmfConnect({ defaultState: DEFAULT_STATE, omitCMFProps: true, withComponentRegistry: true, withDispatch: true, withDispatchActionCreator: true, withComponentId: true, keepComponentState: true, mapStateToProps, mergeProps })(Container); //# sourceMappingURL=SidePanel.connect.js.map