Home Reference Source

src/reducers/widgets.js

import { omit, mapValues, isEmpty } from 'lodash';
import merge from 'deepmerge';
import {
  REGISTER,
  DATA_REQUEST,
  DATA_SUCCESS,
  DATA_FAIL,
  RESOLVE,
  REMOVE,
  SHOW,
  HIDE,
  ENABLE,
  DISABLE,
  LOADING,
  UNLOADING,
  SORT_BY,
  CHANGE_COUNT,
  CHANGE_SIZE,
  CHANGE_PAGE,
  CHANGE_FILTERS_VISIBILITY,
  TOGGLE_FILTERS_VISIBILITY,
  RESET_STATE,
  SET_TABLE_SELECTED_ID,
  SET_ACTIVE,
  DISABLE_ON_FETCH,
} from '../constants/widgets';

/**
 * Описание объекта состояния виджета в хранилище
 * @type {Object}
 * @property {boolean} isInit - инициализирован ли виджета
 * @property {boolean} isEnabled - доступен ли виджет
 * @property {boolean} isVisible - виден ли виджет
 * @property {boolean} isLoading - состояние загрузки
 * @property {string} selectedId - id выбраной записи в виджете
 * @property {number} size - размер выборки
 * @property {number} page - страница выборки
 */
export const widgetState = {
  isInit: false,
  isEnabled: true,
  isVisible: true,
  isLoading: false,
  isResolved: false,
  selectedId: null,
  isFilterVisible: true,
  isActive: false,
  type: null,
  dataProvider: {},
  sorting: {},
  filter: {
    key: null,
    type: null,
  },
  /* Query props */
  count: 0,
  /* System props */
  pageId: null,
  containerId: null,
  validation: {},
};

function resolve(state = widgetState, action) {
  switch (action.type) {
    case DATA_REQUEST:
      return Object.assign({}, state, {
        isLoading: true,
      });
    case DATA_SUCCESS:
      return Object.assign({}, state, {
        isLoading: false,
      });
    case DATA_FAIL:
      return Object.assign({}, state, {
        isLoading: false,
      });
    case RESOLVE:
      return Object.assign({}, state, {
        isResolved: true,
      });
    case SHOW:
      return Object.assign({}, state, {
        isVisible: true,
      });
    case HIDE:
      return Object.assign({}, state, {
        isVisible: false,
      });
    case ENABLE:
      return Object.assign({}, state, {
        isEnabled: true,
      });
    case DISABLE:
    case DISABLE_ON_FETCH:
      return Object.assign({}, state, {
        isEnabled: false,
      });
    case LOADING:
      return Object.assign({}, state, {
        isLoading: true,
      });
    case UNLOADING:
      return Object.assign({}, state, {
        isLoading: false,
      });
    case SORT_BY:
      if (action.payload.sortDirection == 'NONE') {
        return {
          ...state,
          sorting: {},
        };
      }
      return {
        ...state,
        sorting: { [action.payload.fieldKey]: action.payload.sortDirection },
      };
    case CHANGE_SIZE:
      return Object.assign({}, state, {
        size: action.payload.size,
      });
    case CHANGE_PAGE:
      return Object.assign({}, state, {
        page: action.payload.page,
      });
    case CHANGE_COUNT:
      return Object.assign({}, state, {
        count: action.payload.count,
      });
    case CHANGE_FILTERS_VISIBILITY:
      return Object.assign({}, state, {
        isFilterVisible: action.payload.isFilterVisible,
      });
    case TOGGLE_FILTERS_VISIBILITY:
      return Object.assign({}, state, {
        isFilterVisible: !state.isFilterVisible,
      });
    case RESET_STATE:
      return Object.assign({}, state, { isInit: false });
    case SET_TABLE_SELECTED_ID:
      return Object.assign({}, state, { selectedId: action.payload.value });
    case SET_ACTIVE:
      return Object.assign({}, state, { isActive: true });
    default:
      return state;
  }
}

/**
 * Редюсер виджета
 * @ignore
 */
export default function widgets(state = {}, action) {
  switch (action.type) {
    case REGISTER:
      let smartState = {};
      const currentState = state[action.payload.widgetId] || {};
      if (!isEmpty(currentState)) {
        smartState = {
          selectedId: currentState.selectedId ? currentState.selectedId : null,
        };
        if (!isEmpty(currentState.sorting)) {
          smartState.sorting = currentState.sorting;
        }
      }
      return {
        ...state,
        [action.payload.widgetId]: {
          ...merge.all([widgetState, action.payload.initProps, currentState]),
          ...smartState,
          isInit: true,
          type: action.payload.initProps.type,
        },
      };
      break;
    case DATA_REQUEST:
    case DATA_SUCCESS:
    case DATA_FAIL:
    case RESOLVE:
    case DISABLE:
    case DISABLE_ON_FETCH:
    case ENABLE:
    case SHOW:
    case HIDE:
    case LOADING:
    case UNLOADING:
    case SORT_BY:
    case CHANGE_SIZE:
    case CHANGE_COUNT:
    case CHANGE_PAGE:
    case CHANGE_FILTERS_VISIBILITY:
    case TOGGLE_FILTERS_VISIBILITY:
    case SET_TABLE_SELECTED_ID:
    case RESET_STATE:
      return Object.assign({}, state, {
        [action.payload.widgetId]: resolve(
          state[action.payload.widgetId],
          action
        ),
      });
      break;
    case SET_ACTIVE:
      return Object.assign(
        {},
        mapValues(state, value => ({ ...value, isActive: false })),
        {
          [action.payload.widgetId]: resolve(
            state[action.payload.widgetId],
            action
          ),
        }
      );
      break;
    case REMOVE:
      return omit(state, action.payload.widgetId);
      break;
    default:
      return state;
  }
}