Source: app/actions/components/modalActions.js

import createAction from 'redux-actions/lib/createAction';
import { push as historyPush } from 'react-router-redux';

export const OPEN_MODAL = 'modalActions/OPEN_MODAL';
export const IS_OPENED_MODAL = 'modalActions/IS_OPENED_MODAL';
export const CLOSE_MODAL = 'modalActions/CLOSE_MODAL';

export const isOpenedModal = createAction(IS_OPENED_MODAL);
// Define a counter and a map to be able to store non-serializable props outside of the redux store.
// Instead we store the index of the map, and use the map as store and lookup in the ModalRoot.
let modalCountId = 0;
export const modalPropsMap = {};

/**
 * Opens a modal window
 * @function openModal
 * @param {string} component The name of the modal component to display. Should
 * be one of the components in /atoms/modals/ use Modal type enum
 * @param {object} props The props to pass to the modal component. Should be
 * serializable as these are stored in redux state
 * @param {boolean} [showCloseButton=true] Shows a close button in the modal window
 * @param {boolean} [enableCloseOnBackdrop=true] Allows the user to close
 * @param {boolean} [isFullBleed=true] Shows the modal full bleed
 * the modal window by clicking on the backdrop behind the modal
 */
export const openModal = createAction(
  OPEN_MODAL,
  (component, props, showCloseButton = true, enableCloseOnBackdrop = true, isFullBleed = false) => {
    // store the props in a map to access them later on
    modalPropsMap[++modalCountId] = props; // eslint-disable-line no-plusplus
    return {
      component,
      props: {
        modalCountId,
      },
      showCloseButton,
      enableCloseOnBackdrop,
      isFullBleed,
    };
  },
);

const closeModalReduxAction = createAction(CLOSE_MODAL);

/**
 * Closes the active modal window. If a 'modal' query parameter is defined, remove that
 * query parameter instead of dispatching the CLOSE_MODAL action. This will close any modals
 * that are opened through query routing.
 *
 * @function closeModal
 */
export const closeModal = () => (dispatch, getState) => {
  const { locationBeforeTransitions: location } = getState().routing;
  if (location && location.query && location.query.modal) {
    const {
      modal, // eslint-disable-line no-unused-vars
      ...newQuery
    } = location.query;

    return dispatch(
      historyPush({
        ...location,
        query: newQuery,
      }),
    );
  }

  return dispatch(closeModalReduxAction());
};