2017-11-09 17:10:30 -08:00
|
|
|
import _ from 'lodash';
|
|
|
|
import {
|
|
|
|
composeReducers,
|
|
|
|
createAction,
|
|
|
|
createTypes,
|
|
|
|
handleActions
|
|
|
|
} from 'berkeleys-redux-utils';
|
2017-07-31 20:04:01 -07:00
|
|
|
|
2018-01-05 16:31:13 -08:00
|
|
|
import * as utils from './utils.js';
|
2017-07-31 20:04:01 -07:00
|
|
|
import windowEpic from './window-epic.js';
|
|
|
|
import dividerEpic from './divider-epic.js';
|
2018-01-05 16:31:13 -08:00
|
|
|
import ns from '../ns.json';
|
2017-07-31 20:04:01 -07:00
|
|
|
|
|
|
|
export const epics = [
|
|
|
|
windowEpic,
|
|
|
|
dividerEpic
|
|
|
|
];
|
|
|
|
|
|
|
|
export const types = createTypes([
|
2017-11-29 15:44:51 -08:00
|
|
|
'panesMapUpdated',
|
2017-07-31 20:04:01 -07:00
|
|
|
'panesMounted',
|
|
|
|
'panesUpdated',
|
|
|
|
'panesWillMount',
|
|
|
|
'panesWillUnmount',
|
|
|
|
'updateSize',
|
|
|
|
|
|
|
|
'dividerClicked',
|
|
|
|
'dividerMoved',
|
|
|
|
'mouseReleased',
|
2018-01-08 12:00:56 -08:00
|
|
|
'windowResized'
|
2017-07-31 20:04:01 -07:00
|
|
|
], ns);
|
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
export const panesMapUpdated = createAction(
|
|
|
|
types.panesMapUpdated,
|
2017-11-09 17:10:30 -08:00
|
|
|
null,
|
2017-11-29 15:44:51 -08:00
|
|
|
(type, panesMap) => ({ trigger: type, panesMap })
|
2017-11-09 17:10:30 -08:00
|
|
|
);
|
2017-07-31 20:04:01 -07:00
|
|
|
export const panesMounted = createAction(types.panesMounted);
|
|
|
|
export const panesUpdated = createAction(types.panesUpdated);
|
|
|
|
export const panesWillMount = createAction(types.panesWillMount);
|
|
|
|
export const panesWillUnmount = createAction(types.panesWillUnmount);
|
|
|
|
|
|
|
|
export const dividerClicked = createAction(types.dividerClicked);
|
|
|
|
export const dividerMoved = createAction(types.dividerMoved);
|
|
|
|
export const mouseReleased = createAction(types.mouseReleased);
|
|
|
|
export const windowResized = createAction(types.windowResized);
|
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
const defaultState = {
|
2017-07-31 20:04:01 -07:00
|
|
|
width: 800,
|
|
|
|
panes: [],
|
|
|
|
panesByName: {},
|
2018-01-09 23:43:38 -05:00
|
|
|
panesMap: {},
|
|
|
|
pressedDivider: null
|
2017-07-31 20:04:01 -07:00
|
|
|
};
|
|
|
|
export const getNS = state => state[ns];
|
|
|
|
|
|
|
|
export const panesSelector = state => getNS(state).panes;
|
|
|
|
export const panesByNameSelector = state => getNS(state).panesByName;
|
|
|
|
export const pressedDividerSelector =
|
|
|
|
state => getNS(state).pressedDivider;
|
|
|
|
export const widthSelector = state => getNS(state).width;
|
2017-11-29 15:44:51 -08:00
|
|
|
export const panesMapSelector = state => getNS(state).panesMap;
|
2017-07-31 20:04:01 -07:00
|
|
|
|
2017-11-29 15:44:51 -08:00
|
|
|
export default function createPanesAspects({ createPanesMap }) {
|
2018-01-05 16:31:13 -08:00
|
|
|
createPanesMap = utils.normalizePanesMapCreator(createPanesMap);
|
2017-07-31 20:04:01 -07:00
|
|
|
|
2017-11-09 17:10:30 -08:00
|
|
|
function middleware({ getState }) {
|
2017-07-31 20:04:01 -07:00
|
|
|
return next => action => {
|
|
|
|
let finalAction = action;
|
2017-11-29 15:44:51 -08:00
|
|
|
const panesMap = panesMapSelector(getState());
|
2018-01-05 16:31:13 -08:00
|
|
|
if (utils.isPanesAction(action, panesMap)) {
|
2017-07-31 20:04:01 -07:00
|
|
|
finalAction = {
|
|
|
|
...action,
|
|
|
|
meta: {
|
|
|
|
...action.meta,
|
2017-11-09 17:10:30 -08:00
|
|
|
isPaneAction: true,
|
2017-11-29 15:44:51 -08:00
|
|
|
paneName: panesMap[action.type]
|
2017-07-31 20:04:01 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2017-11-09 17:10:30 -08:00
|
|
|
const result = next(finalAction);
|
2017-11-29 15:44:51 -08:00
|
|
|
const nextPanesMap = createPanesMap(getState(), action);
|
|
|
|
if (nextPanesMap) {
|
2018-01-05 16:31:13 -08:00
|
|
|
utils.checkForTypeKeys(nextPanesMap);
|
2017-11-29 15:44:51 -08:00
|
|
|
next(panesMapUpdated(action.type, nextPanesMap));
|
2017-11-09 17:10:30 -08:00
|
|
|
}
|
|
|
|
return result;
|
2017-07-31 20:04:01 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-11-09 17:10:30 -08:00
|
|
|
const reducer = composeReducers(
|
|
|
|
ns,
|
|
|
|
handleActions(
|
|
|
|
() => ({
|
|
|
|
[types.dividerClicked]: (state, { payload: name }) => ({
|
|
|
|
...state,
|
|
|
|
pressedDivider: name
|
|
|
|
}),
|
|
|
|
[types.dividerMoved]: (state, { payload: clientX }) => {
|
2018-01-05 15:45:17 -08:00
|
|
|
const {
|
|
|
|
panes,
|
|
|
|
panesByName,
|
|
|
|
pressedDivider: paneName,
|
|
|
|
width
|
|
|
|
} = state;
|
2017-11-09 17:10:30 -08:00
|
|
|
const dividerBuffer = (200 / width) * 100;
|
|
|
|
const paneIndex =
|
|
|
|
_.findIndex(state.panes, ({ name }) => paneName === name);
|
2018-01-05 15:45:17 -08:00
|
|
|
const currentPane = panesByName[paneName];
|
2018-01-05 16:31:13 -08:00
|
|
|
const rightPane = utils.getPane(panesByName, panes, paneIndex + 1);
|
|
|
|
const leftPane = utils.getPane(panesByName, panes, paneIndex - 1);
|
|
|
|
const rightBound = utils.getRightBound(rightPane, dividerBuffer);
|
|
|
|
const leftBound = utils.getLeftBound(leftPane, dividerBuffer);
|
2017-11-09 17:10:30 -08:00
|
|
|
const newPosition = _.clamp(
|
|
|
|
(clientX / width) * 100,
|
|
|
|
leftBound,
|
|
|
|
rightBound
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
panesByName: {
|
|
|
|
...state.panesByName,
|
|
|
|
[currentPane.name]: {
|
|
|
|
...currentPane,
|
|
|
|
dividerLeft: newPosition
|
|
|
|
}
|
2017-07-31 20:04:01 -07:00
|
|
|
}
|
2017-11-09 17:10:30 -08:00
|
|
|
};
|
|
|
|
},
|
|
|
|
[types.mouseReleased]: state => ({ ...state, pressedDivider: null }),
|
2018-01-08 12:00:56 -08:00
|
|
|
[types.windowResized]: (state, { payload: { width } }) => ({
|
2017-11-09 17:10:30 -08:00
|
|
|
...state,
|
|
|
|
width
|
|
|
|
}),
|
|
|
|
// used to clear bin buttons
|
|
|
|
[types.panesWillUnmount]: state => ({
|
|
|
|
...state,
|
|
|
|
panes: [],
|
|
|
|
panesByName: {},
|
|
|
|
pressedDivider: null
|
|
|
|
})
|
|
|
|
}),
|
2017-12-31 14:07:42 -08:00
|
|
|
defaultState
|
2017-11-09 17:10:30 -08:00
|
|
|
),
|
2017-11-29 15:44:51 -08:00
|
|
|
function metaReducer(state = defaultState, action) {
|
|
|
|
if (action.meta && action.meta.panesMap) {
|
|
|
|
const panesMap = action.meta.panesMap;
|
|
|
|
const panes = _.map(panesMap, (name, type) => ({ name, type }));
|
2017-11-09 17:10:30 -08:00
|
|
|
const numOfPanes = Object.keys(panes).length;
|
2018-01-16 09:49:36 -08:00
|
|
|
if (_.isEqual(state.panes, panes)) {
|
|
|
|
return state;
|
|
|
|
}
|
2017-11-09 17:10:30 -08:00
|
|
|
return {
|
|
|
|
...state,
|
2017-11-29 15:44:51 -08:00
|
|
|
panesMap,
|
2017-11-09 17:10:30 -08:00
|
|
|
panes,
|
2018-01-16 09:49:36 -08:00
|
|
|
panesByName: panes.reduce((panes, { name }, index) => {
|
|
|
|
const dividerLeft = utils.getDividerLeft(numOfPanes, index);
|
|
|
|
panes[name] = {
|
|
|
|
name,
|
|
|
|
dividerLeft,
|
|
|
|
isHidden: false
|
|
|
|
};
|
|
|
|
return panes;
|
|
|
|
}, {})
|
2017-11-09 17:10:30 -08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
if (action.meta && action.meta.isPaneAction) {
|
|
|
|
const name = action.meta.paneName;
|
|
|
|
const oldPane = state.panesByName[name];
|
|
|
|
const pane = {
|
|
|
|
...oldPane,
|
|
|
|
isHidden: !oldPane.isHidden
|
|
|
|
};
|
|
|
|
const panesByName = {
|
|
|
|
...state.panesByName,
|
|
|
|
[name]: pane
|
|
|
|
};
|
|
|
|
const numOfPanes = state.panes.reduce((sum, { name }) => {
|
|
|
|
return panesByName[name].isHidden ? sum : sum + 1;
|
|
|
|
}, 0);
|
|
|
|
let numOfHidden = 0;
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
panesByName: state.panes.reduce(
|
|
|
|
(panesByName, { name }, index) => {
|
|
|
|
if (!panesByName[name].isHidden) {
|
2018-01-05 16:31:13 -08:00
|
|
|
const dividerLeft = utils.getDividerLeft(
|
2017-11-09 17:10:30 -08:00
|
|
|
numOfPanes,
|
|
|
|
index - numOfHidden
|
|
|
|
);
|
|
|
|
panesByName[name] = {
|
|
|
|
...panesByName[name],
|
|
|
|
dividerLeft
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
numOfHidden = numOfHidden + 1;
|
|
|
|
}
|
|
|
|
return panesByName;
|
|
|
|
},
|
|
|
|
panesByName
|
|
|
|
)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return state;
|
2017-07-31 20:04:01 -07:00
|
|
|
}
|
2017-11-09 17:10:30 -08:00
|
|
|
);
|
2017-07-31 20:04:01 -07:00
|
|
|
|
|
|
|
return {
|
2017-11-09 17:10:30 -08:00
|
|
|
reducer,
|
2017-07-31 20:04:01 -07:00
|
|
|
middleware
|
|
|
|
};
|
|
|
|
}
|