Home Reference Source

src/components/regions/Tabs/TabsRegion.jsx

import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty, filter, map, isUndefined, pull } from 'lodash';
import { compose } from 'recompose';
import Tabs from './Tabs';
import Tab from './Tab';
import WidgetFactory from '../../widgets/WidgetFactory';
import withWidgetProps from '../withWidgetProps';
import { WIDGETS } from '../../../core/factory/factoryLevels';

import Factory from '../../../core/factory/Factory';
import SecurityCheck from '../../../core/auth/SecurityCheck';

/**
 * Регион Таб
 * @reactProps {array} tabs - массив из объектов, которые описывают виджет {id, name, opened, pageId, fetchOnInit, widget}
 * @reactProps {function} getWidget - функция получения виджета
 * @reactProps {string} pageId - идентификатор страницы
 * @reactProps {function} resolveVisibleDependency - резол видимости таба
 */
class TabRegion extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      readyTabs: this.findReadyTabs(),
      visibleTabs: {},
    };
    this.handleChangeActive = this.handleChangeActive.bind(this);
  }

  handleChangeActive(widgetId, prevWidgetId) {
    const { lazy, alwaysRefresh, getWidgetProps, fetchWidget } = this.props;
    const { readyTabs } = this.state;
    const widgetProps = getWidgetProps(widgetId);

    if (lazy) {
      if (alwaysRefresh) {
        pull(readyTabs, prevWidgetId);
      }
      readyTabs.push(widgetId);
      this.setState(() => ({
        readyTabs: [...readyTabs],
      }));
    } else if (alwaysRefresh || isEmpty(widgetProps.datasource)) {
      widgetProps.dataProvider && fetchWidget(widgetId);
    }
  }

  findReadyTabs() {
    return filter(
      map(this.props.tabs, tab => {
        if (tab.opened) {
          return tab.widgetId;
        }
      }),
      item => item
    );
  }

  render() {
    const { tabs, getWidget, getWidgetProps, pageId, lazy } = this.props;
    const { readyTabs, visibleTabs } = this.state;
    return (
      <Tabs onChangeActive={this.handleChangeActive}>
        {tabs.map(tab => {
          const { security } = tab;
          const widgetProps = getWidgetProps(tab.widgetId);
          const widgetMeta = getWidget(pageId, tab.widgetId);
          const tabProps = {
            key: tab.widgetId,
            id: tab.widgetId,
            title: tab.label || tab.widgetId,
            icon: tab.icon,
            active: tab.opened,
            visible:
              (!isEmpty(widgetProps) ? widgetProps.isVisible : true) &&
              (!isUndefined(visibleTabs[tab.widgetId])
                ? visibleTabs[tab.widgetId]
                : true),
          };

          const tabEl = (
            <Tab {...tabProps}>
              {lazy ? (
                readyTabs.includes(tab.widgetId) && (
                  <Factory id={tab.widgetId} level={WIDGETS} {...widgetMeta} />
                )
              ) : (
                <Factory id={tab.widgetId} level={WIDGETS} {...widgetMeta} />
              )}
            </Tab>
          );

          const onPermissionsSet = permissions => {
            this.setState({
              visibleTabs: {
                ...visibleTabs,
                [tab.widgetId]: !!permissions,
              },
            });
          };

          return isEmpty(security) ? (
            tabEl
          ) : (
            <SecurityCheck
              {...tabProps}
              config={security}
              onPermissionsSet={onPermissionsSet}
              render={({ permissions, active, visible }) => {
                return permissions
                  ? React.cloneElement(tabEl, { active, visible })
                  : null;
              }}
            />
          );
        })}
      </Tabs>
    );
  }
}

TabRegion.propTypes = {
  tabs: PropTypes.array.isRequired,
  getWidget: PropTypes.func.isRequired,
  pageId: PropTypes.string.isRequired,
  alwaysRefresh: PropTypes.bool,
  mode: PropTypes.oneOf(['single', 'all']),
  lazy: PropTypes.bool,
  resolveVisibleDependency: PropTypes.func,
};

TabRegion.defaultProps = {
  alwaysRefresh: false,
  lazy: false,
  mode: 'single',
};

export default compose(withWidgetProps)(TabRegion);