redux-signal
Version:
A scalable solution for modals using React and Redux
112 lines (95 loc) • 3.83 kB
JavaScript
import { fromJS, List, Map } from 'immutable';
import * as ActionTypes from './constants/ActionTypes';
import * as ModalStates from './constants/ModalStates';
import { getSignalModalId } from './utils';
export var initialState = fromJS({
signal: {
data: {},
eventQueue: {},
feedbackQueue: {},
order: []
},
modals: {}
});
var emptyModal = Map({
isBusy: false,
state: ModalStates.CREATED
});
function signalCreate(state, action) {
var modalInstanceId = getSignalModalId(action.modal.get('id'));
return state.setIn(['modals', modalInstanceId], emptyModal).setIn(['signal', 'data', action.modal.get('id')], action.modal).updateIn(['signal', 'order'], function (e) {
return e.push(action.modal.get('id'));
}).update('signal', function (state) {
var eventHandlerId = action.modal.get('eventHandlerId');
if (!eventHandlerId) {
return state;
}
return state.setIn(['eventQueue', eventHandlerId], List()).setIn(['feedbackQueue', eventHandlerId], List());
});
}
function signalDestroy(state, action) {
var modalInstanceId = getSignalModalId(action.id);
return state.deleteIn(['signal', 'data', action.id]).updateIn(['signal', 'order'], function (e) {
return e.delete(e.indexOf(action.id));
}).deleteIn(['modals', modalInstanceId]);
}
function signalSetState(state, action) {
var translatedAction = {
instanceId: getSignalModalId(action.id),
value: action.value
};
return state.setIn(['modals', translatedAction.instanceId, 'state'], translatedAction.value);
}
function signalEvent(state, action) {
var eventHandlerId = state.getIn(['signal', 'data', action.id, 'eventHandlerId']);
if (eventHandlerId !== null) {
return state.updateIn(['signal', 'eventQueue', eventHandlerId], function (e) {
return e.push(action.event);
});
}
return state;
}
function signalEventQueueShift(state, action) {
var event = state.getIn(['signal', 'eventQueue', action.eventQueueId]).first();
// Move event from eventQueue to feedbackQueue
return state.updateIn(['signal', 'eventQueue', action.eventQueueId], function (e) {
return e.shift();
}).updateIn(['signal', 'feedbackQueue', action.eventQueueId], function (e) {
return e.push(event);
});
}
export default function reduxSignalReducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments[1];
switch (action.type) {
case ActionTypes.MODAL_CREATE:
case ActionTypes.MODAL_HIDE:
return state.setIn(['modals', action.instanceId], emptyModal);
case ActionTypes.MODAL_DESTROY:
return state.deleteIn(['modals', action.instanceId]);
case ActionTypes.MODAL_SHOW:
return state.updateIn(['modals', action.instanceId], function (modal) {
return modal.set('isBusy', false).set('state', ModalStates.VISIBLE).set('data', action.data);
});
case ActionTypes.MODAL_SET_BUSY:
return state.setIn(['modals', action.instanceId, 'isBusy'], action.isBusy);
case ActionTypes.SIGNAL_CREATE:
return signalCreate(state, action);
case ActionTypes.SIGNAL_DESTROY:
return signalDestroy(state, action);
case ActionTypes.MODAL_SET_STATE:
return signalSetState(state, action);
case ActionTypes.SIGNAL_EVENT:
return signalEvent(state, action);
case ActionTypes.SIGNAL_EVENT_QUEUE_SHIFT:
return signalEventQueueShift(state, action);
case ActionTypes.SIGNAL_FEEDBACK_QUEUE_SHIFT:
return state.updateIn(['signal', 'feedbackQueue', action.eventQueueId], function (e) {
return e.shift();
});
case ActionTypes.SIGNAL_QUEUE_DESTROY:
return state.deleteIn(['signal', 'eventQueue', action.eventQueueId]).deleteIn(['signal', 'feedbackQueue', action.eventQueueId]);
default:
return state;
}
}