react-planner-viewer
Version:
react-planner-viewer is a React Component for view plans builded with react-planner in 2D mode
336 lines (267 loc) • 8.48 kB
JavaScript
import {Seq, Map, List} from "immutable";
import {
LOAD_PROJECT,
NEW_PROJECT,
OPEN_CATALOG,
MODE_VIEWING_CATALOG,
MODE_CONFIGURING_PROJECT,
SELECT_TOOL_EDIT,
MODE_IDLE,
UNSELECT_ALL,
SET_PROPERTIES,
SET_ITEMS_ATTRIBUTES,
SET_LINES_ATTRIBUTES,
SET_HOLES_ATTRIBUTES,
REMOVE,
UNDO,
ROLLBACK,
SET_PROJECT_PROPERTIES,
OPEN_PROJECT_CONFIGURATOR,
INIT_CATALOG,
UPDATE_MOUSE_COORDS,
UPDATE_ZOOM_SCALE,
TOGGLE_SNAP,
CHANGE_CATALOG_PAGE,
GO_BACK_TO_CATALOG_PAGE,
THROW_ERROR,
THROW_WARNING,
COPY_PROPERTIES,
PASTE_PROPERTIES,
PUSH_LAST_SELECTED_CATALOG_ELEMENT_TO_HISTORY
} from '../constants';
import {State, Scene, Guide, Catalog} from "../models";
import {
removeLine,
removeHole,
detectAndUpdateAreas,
setProperties as setPropertiesOp,
setItemsAttributes as setItemsAttributesOp,
setLinesAttributes as setLinesAttributesOp,
setHolesAttributes as setHolesAttributesOp,
select,
unselect,
unselectAll as unselectAllOp,
removeItem,
loadLayerFromJSON,
setPropertiesOnSelected,
updatePropertiesOnSelected,
setAttributesOnSelected
} from '../utils/layer-operations';
export default function (state, action) {
switch (action.type) {
case NEW_PROJECT:
return newProject(state);
case LOAD_PROJECT:
return loadProject(state, action.sceneJSON);
case OPEN_CATALOG:
return openCatalog(state);
case CHANGE_CATALOG_PAGE:
return state.setIn(['catalog', 'page'], action.newPage)
.updateIn(['catalog', 'path'], path => path.push(action.oldPage));
case GO_BACK_TO_CATALOG_PAGE:
let path = state.catalog.path;
let pageIndex = state.catalog.path.findIndex(page => page === action.newPage);
return state.setIn(['catalog', 'page'], action.newPage)
.updateIn(['catalog', 'path'], path => path.take(pageIndex));
case SELECT_TOOL_EDIT:
return state.set('mode', MODE_IDLE);
case UNSELECT_ALL:
return unselectAll(state);
case SET_PROPERTIES:
return setProperties(state, action.properties);
case SET_ITEMS_ATTRIBUTES:
return setItemsAttributes(state, action.itemsAttributes);
case SET_LINES_ATTRIBUTES:
return setLinesAttributes(state, action.linesAttributes);
case SET_HOLES_ATTRIBUTES:
return setHolesAttributes(state, action.holesAttributes);
case REMOVE:
return remove(state);
case UNDO:
return undo(state);
case ROLLBACK:
return rollback(state);
case SET_PROJECT_PROPERTIES:
return setProjectProperties(state, action.properties);
case OPEN_PROJECT_CONFIGURATOR:
return openProjectConfigurator(state);
case INIT_CATALOG:
return initCatalog(state, action.catalog);
case UPDATE_MOUSE_COORDS:
return updateMouseCoord(state, action.coords);
case UPDATE_ZOOM_SCALE:
return updateZoomScale(state, action.scale);
case TOGGLE_SNAP:
return toggleSnap(state, action.mask);
case THROW_ERROR:
return throwError(state, action.error);
case THROW_WARNING:
return throwWarning(state, action.warning);
case COPY_PROPERTIES:
return copyProperties(state, action.properties);
case PASTE_PROPERTIES:
return pasteProperties(state);
case PUSH_LAST_SELECTED_CATALOG_ELEMENT_TO_HISTORY:
return pushLastSelectedCatalogElementToHistory(state, action.element);
default:
return state;
}
}
function openCatalog(state) {
return rollback(state)
.set('mode', MODE_VIEWING_CATALOG);
}
function newProject(state) {
return new State();
}
function loadProject(state, sceneJSON) {
return new State({scene: sceneJSON, catalog: state.catalog.toJS()});
}
function setProperties(state, properties) {
let scene = state.scene;
scene = scene.set('layers', scene.layers.map(layer => setPropertiesOnSelected(layer, properties)));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
})
}
function updateProperties(state, properties) {
let scene = state.scene;
scene = scene.set('layers', scene.layers.map(layer => updatePropertiesOnSelected(layer, properties)));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
})
}
function setItemsAttributes(state, attributes) {
let scene = state.scene;
scene = scene.set('layers', scene.layers.map(layer => setAttributesOnSelected(layer, attributes, state.catalog)));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
});
}
function setLinesAttributes(state, attributes) {
let scene = state.scene;
scene = scene.set('layers', scene.layers.map(layer => setAttributesOnSelected(layer, attributes, state.catalog)));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
});
}
function setHolesAttributes(state, attributes) {
let scene = state.scene;
scene = scene.set('layers', scene.layers.map(layer => setAttributesOnSelected(layer, attributes, state.catalog)));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
});
}
function unselectAll(state) {
let scene = state.scene;
scene = scene.update('layers', layer => layer.map(unselectAllOp));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
})
}
function remove(state) {
let scene = state.scene;
let catalog = state.catalog;
scene = scene.updateIn(['layers', scene.selectedLayer], layer => layer.withMutations(layer => {
let {lines: selectedLines, holes: selectedHoles, items: selectedItems} = layer.selected;
unselectAllOp(layer);
selectedLines.forEach(lineID => removeLine(layer, lineID));
selectedHoles.forEach(holeID => removeHole(layer, holeID));
selectedItems.forEach(itemID => removeItem(layer, itemID));
detectAndUpdateAreas(layer, catalog);
}));
return state.merge({
scene,
sceneHistory: state.sceneHistory.push(scene)
})
}
function undo(state) {
let sceneHistory = state.sceneHistory;
if (state.scene === sceneHistory.last() && !sceneHistory.size > 1)
sceneHistory = sceneHistory.pop();
switch (sceneHistory.size) {
case 0:
return state;
case 1:
return state.merge({
mode: MODE_IDLE,
scene: sceneHistory.last(),
});
default:
return state.merge({
mode: MODE_IDLE,
scene: sceneHistory.last(),
sceneHistory: sceneHistory.pop()
});
}
}
export function rollback(state) {
let sceneHistory = state.sceneHistory;
if (sceneHistory.isEmpty()) return state;
let scene = sceneHistory
.last()
.update('layers', layer => layer.map(unselectAllOp));
return state.merge({
mode: MODE_IDLE,
scene,
sceneHistory: state.sceneHistory.push(scene),
snapElements: new List(),
activeSnapElement: null,
drawingSupport: new Map(),
draggingSupport: new Map(),
rotatingSupport: new Map(),
});
}
function setProjectProperties(state, properties) {
let scene = state.scene.merge(properties);
return state.merge({
mode: MODE_IDLE,
scene,
sceneHistory: state.sceneHistory.push(scene)
});
}
function openProjectConfigurator(state) {
return state.merge({
mode: MODE_CONFIGURING_PROJECT,
});
}
function initCatalog(state, catalog) {
return state.set('catalog', new Catalog(catalog));
}
function updateMouseCoord(state, coords) {
return state.set('mouse', new Map(coords));
}
function updateZoomScale(state, scale) {
return state.set('zoom', scale);
}
function toggleSnap(state, mask) {
return state.set('snapMask', mask);
}
function throwError(state, error) {
return state.set('errors', state.get('errors').push({
date: Date.now(),
error
}));
}
const throwWarning = (state, warning) => state.set('warnings', state.get('warnings').push({
date: Date.now(),
warning
}));
const copyProperties = (state, properties) => state.set('clipboardProperties', properties.toJS());
const pasteProperties = (state) => updateProperties(state, state.get('clipboardProperties'));
const pushLastSelectedCatalogElementToHistory = ( state, element ) => {
let currHistory = state.selectedElementsHistory;
let previousPosition = currHistory.findIndex( el => el.name === element.name );
if( previousPosition !== -1 )
{
currHistory = currHistory.splice( previousPosition, 1 );
}
currHistory = currHistory.splice( 0, 0, element );
return state.set('selectedElementsHistory', currHistory);
};