summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/actions/map.js26
-rw-r--r--src/components/map/MapStageComponent.js (renamed from src/components/map/MapStage.js)61
-rw-r--r--src/components/map/elements/TilePlusIcon.js21
-rw-r--r--src/components/map/layers/HoverLayerComponent.js17
-rw-r--r--src/components/map/layers/MapLayerComponent.js17
-rw-r--r--src/containers/map/MapStage.js26
-rw-r--r--src/containers/map/layers/MapLayer.js15
-rw-r--r--src/containers/map/layers/ObjectHoverLayer.js2
-rw-r--r--src/containers/map/layers/RoomHoverLayer.js2
-rw-r--r--src/pages/App.js2
-rw-r--r--src/reducers/index.js2
-rw-r--r--src/reducers/map.js35
12 files changed, 166 insertions, 60 deletions
diff --git a/src/actions/map.js b/src/actions/map.js
new file mode 100644
index 00000000..ef691873
--- /dev/null
+++ b/src/actions/map.js
@@ -0,0 +1,26 @@
+export const SET_MAP_POSITION = "SET_MAP_POSITION";
+export const SET_MAP_DIMENSIONS = "SET_MAP_DIMENSIONS";
+export const SET_MAP_SCALE = "SET_MAP_SCALE";
+
+export function setMapPosition(x, y) {
+ return {
+ type: SET_MAP_POSITION,
+ x,
+ y
+ };
+}
+
+export function setMapDimensions(width, height) {
+ return {
+ type: SET_MAP_DIMENSIONS,
+ width,
+ height
+ };
+}
+
+export function setMapScale(scale) {
+ return {
+ type: SET_MAP_SCALE,
+ scale
+ };
+}
diff --git a/src/components/map/MapStage.js b/src/components/map/MapStageComponent.js
index ab2f0839..10d84948 100644
--- a/src/components/map/MapStage.js
+++ b/src/components/map/MapStageComponent.js
@@ -1,13 +1,11 @@
import React from "react";
-import {Group, Layer, Stage} from "react-konva";
+import {Stage} from "react-konva";
import {Shortcuts} from "react-shortcuts";
-import DatacenterContainer from "../../containers/map/DatacenterContainer";
+import MapLayer from "../../containers/map/layers/MapLayer";
import ObjectHoverLayer from "../../containers/map/layers/ObjectHoverLayer";
import RoomHoverLayer from "../../containers/map/layers/RoomHoverLayer";
import jQuery from "../../util/jquery";
import {NAVBAR_HEIGHT} from "../navigation/Navbar";
-import Backdrop from "./elements/Backdrop";
-import GridGroup from "./groups/GridGroup";
import {
MAP_MAX_SCALE,
MAP_MIN_SCALE,
@@ -16,13 +14,8 @@ import {
MAP_SIZE_IN_PIXELS
} from "./MapConstants";
-class MapStage extends React.Component {
+class MapStageComponent extends React.Component {
state = {
- width: 600,
- height: 400,
- x: 0,
- y: 0,
- scale: 1,
mouseX: 0,
mouseY: 0
};
@@ -42,23 +35,23 @@ class MapStage extends React.Component {
}
updateDimensions() {
- this.setState({width: jQuery(window).width(), height: jQuery(window).height() - NAVBAR_HEIGHT});
+ this.props.setMapDimensions(jQuery(window).width(), jQuery(window).height() - NAVBAR_HEIGHT);
}
updateScale(e) {
e.preventDefault();
const mousePointsTo = {
- x: this.state.mouseX / this.state.scale - this.state.x / this.state.scale,
- y: this.state.mouseY / this.state.scale - this.state.y / this.state.scale,
+ x: this.state.mouseX / this.props.mapScale - this.props.mapPosition.x / this.props.mapScale,
+ y: this.state.mouseY / this.props.mapScale - this.props.mapPosition.y / this.props.mapScale,
};
- const newScale = e.deltaY < 0 ? this.state.scale * MAP_SCALE_PER_EVENT : this.state.scale / MAP_SCALE_PER_EVENT;
+ const newScale = e.deltaY < 0 ? this.props.mapScale * MAP_SCALE_PER_EVENT : this.props.mapScale / MAP_SCALE_PER_EVENT;
const boundedScale = Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE);
const newX = -(mousePointsTo.x - this.state.mouseX / boundedScale) * boundedScale;
const newY = -(mousePointsTo.y - this.state.mouseY / boundedScale) * boundedScale;
this.setPositionWithBoundsCheck(newX, newY);
- this.setState({scale: boundedScale});
+ this.props.setMapScale(boundedScale);
}
updateMousePosition() {
@@ -86,19 +79,19 @@ class MapStage extends React.Component {
}
moveWithDelta(deltaX, deltaY) {
- this.setPositionWithBoundsCheck(this.state.x + deltaX, this.state.y + deltaY);
+ this.setPositionWithBoundsCheck(this.props.mapPosition.x + deltaX, this.props.mapPosition.y + deltaY);
}
setPositionWithBoundsCheck(newX, newY) {
- const scaledMapSize = MAP_SIZE_IN_PIXELS * this.state.scale;
- const updatedPosition = {
- x: newX > 0 ? 0 :
- (newX < -scaledMapSize + this.state.width ? -scaledMapSize + this.state.width : newX),
- y: newY > 0 ? 0 :
- (newY < -scaledMapSize + this.state.height ? -scaledMapSize + this.state.height : newY)
- };
+ const scaledMapSize = MAP_SIZE_IN_PIXELS * this.props.mapScale;
+ const updatedX = newX > 0 ? 0 :
+ (newX < -scaledMapSize + this.props.mapDimensions.width
+ ? -scaledMapSize + this.props.mapDimensions.width : newX);
+ const updatedY = newY > 0 ? 0 :
+ (newY < -scaledMapSize + this.props.mapDimensions.height
+ ? -scaledMapSize + this.props.mapDimensions.height : newY);
- this.setState(updatedPosition);
+ this.props.setMapPosition(updatedX, updatedY);
}
render() {
@@ -106,30 +99,18 @@ class MapStage extends React.Component {
<Shortcuts name="MAP" handler={this.handleShortcuts.bind(this)} targetNodeSelector="body">
<Stage
ref={(stage) => {this.stage = stage;}}
- width={this.state.width}
- height={this.state.height}
+ width={this.props.mapDimensions.width}
+ height={this.props.mapDimensions.height}
onMouseMove={this.updateMousePosition.bind(this)}
>
- <Layer>
- <Group x={this.state.x} y={this.state.y} scaleX={this.state.scale} scaleY={this.state.scale}>
- <Backdrop/>
- <DatacenterContainer/>
- <GridGroup/>
- </Group>
- </Layer>
+ <MapLayer/>
<RoomHoverLayer
- mainGroupX={this.state.x}
- mainGroupY={this.state.y}
mouseX={this.state.mouseX}
mouseY={this.state.mouseY}
- scale={this.state.scale}
/>
<ObjectHoverLayer
- mainGroupX={this.state.x}
- mainGroupY={this.state.y}
mouseX={this.state.mouseX}
mouseY={this.state.mouseY}
- scale={this.state.scale}
/>
</Stage>
</Shortcuts>
@@ -137,4 +118,4 @@ class MapStage extends React.Component {
}
}
-export default MapStage;
+export default MapStageComponent;
diff --git a/src/components/map/elements/TilePlusIcon.js b/src/components/map/elements/TilePlusIcon.js
index 3327525c..ed5ef5b5 100644
--- a/src/components/map/elements/TilePlusIcon.js
+++ b/src/components/map/elements/TilePlusIcon.js
@@ -4,19 +4,19 @@ import {Group, Line} from "react-konva";
import {TILE_PLUS_COLOR} from "../../../colors/index";
import {TILE_PLUS_MARGIN_IN_PIXELS, TILE_PLUS_WIDTH_IN_PIXELS, TILE_SIZE_IN_PIXELS} from "../MapConstants";
-const TilePlusIcon = ({pixelX, pixelY, scale}) => {
+const TilePlusIcon = ({pixelX, pixelY, mapScale}) => {
const linePoints = [
[
- pixelX + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- pixelY + TILE_PLUS_MARGIN_IN_PIXELS * scale,
- pixelX + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- pixelY + TILE_SIZE_IN_PIXELS * scale - TILE_PLUS_MARGIN_IN_PIXELS * scale,
+ pixelX + 0.5 * TILE_SIZE_IN_PIXELS * mapScale,
+ pixelY + TILE_PLUS_MARGIN_IN_PIXELS * mapScale,
+ pixelX + 0.5 * TILE_SIZE_IN_PIXELS * mapScale,
+ pixelY + TILE_SIZE_IN_PIXELS * mapScale - TILE_PLUS_MARGIN_IN_PIXELS * mapScale,
],
[
- pixelX + TILE_PLUS_MARGIN_IN_PIXELS * scale,
- pixelY + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- pixelX + TILE_SIZE_IN_PIXELS * scale - TILE_PLUS_MARGIN_IN_PIXELS * scale,
- pixelY + 0.5 * TILE_SIZE_IN_PIXELS * scale,
+ pixelX + TILE_PLUS_MARGIN_IN_PIXELS * mapScale,
+ pixelY + 0.5 * TILE_SIZE_IN_PIXELS * mapScale,
+ pixelX + TILE_SIZE_IN_PIXELS * mapScale - TILE_PLUS_MARGIN_IN_PIXELS * mapScale,
+ pixelY + 0.5 * TILE_SIZE_IN_PIXELS * mapScale,
],
];
return (
@@ -27,7 +27,7 @@ const TilePlusIcon = ({pixelX, pixelY, scale}) => {
points={points}
lineCap="round"
stroke={TILE_PLUS_COLOR}
- strokeWidth={TILE_PLUS_WIDTH_IN_PIXELS * scale}
+ strokeWidth={TILE_PLUS_WIDTH_IN_PIXELS * mapScale}
listening={false}
/>
))}
@@ -38,6 +38,7 @@ const TilePlusIcon = ({pixelX, pixelY, scale}) => {
TilePlusIcon.propTypes = {
pixelX: PropTypes.number,
pixelY: PropTypes.number,
+ mapScale: PropTypes.number,
};
export default TilePlusIcon;
diff --git a/src/components/map/layers/HoverLayerComponent.js b/src/components/map/layers/HoverLayerComponent.js
index 54a63383..aa2e8313 100644
--- a/src/components/map/layers/HoverLayerComponent.js
+++ b/src/components/map/layers/HoverLayerComponent.js
@@ -8,9 +8,8 @@ class HoverLayerComponent extends React.Component {
static propTypes = {
mouseX: PropTypes.number.isRequired,
mouseY: PropTypes.number.isRequired,
- mainGroupX: PropTypes.number.isRequired,
- mainGroupY: PropTypes.number.isRequired,
- scale: PropTypes.number.isRequired,
+ mapPosition: PropTypes.object.isRequired,
+ mapScale: PropTypes.number.isRequired,
isEnabled: PropTypes.func.isRequired,
onClick: PropTypes.func.isRequired,
};
@@ -26,8 +25,8 @@ class HoverLayerComponent extends React.Component {
return;
}
- const positionX = Math.floor((this.props.mouseX - this.props.mainGroupX) / (this.props.scale * TILE_SIZE_IN_PIXELS));
- const positionY = Math.floor((this.props.mouseY - this.props.mainGroupY) / (this.props.scale * TILE_SIZE_IN_PIXELS));
+ const positionX = Math.floor((this.props.mouseX - this.props.mapPosition.x) / (this.props.mapScale * TILE_SIZE_IN_PIXELS));
+ const positionY = Math.floor((this.props.mouseY - this.props.mapPosition.y) / (this.props.mapScale * TILE_SIZE_IN_PIXELS));
if (positionX !== this.state.positionX || positionY !== this.state.positionY) {
this.setState({positionX, positionY, validity: this.props.isValid(positionX, positionY)});
@@ -39,21 +38,21 @@ class HoverLayerComponent extends React.Component {
return <Layer/>;
}
- const pixelX = this.props.scale * this.state.positionX * TILE_SIZE_IN_PIXELS + this.props.mainGroupX;
- const pixelY = this.props.scale * this.state.positionY * TILE_SIZE_IN_PIXELS + this.props.mainGroupY;
+ const pixelX = this.props.mapScale * this.state.positionX * TILE_SIZE_IN_PIXELS + this.props.mapPosition.x;
+ const pixelY = this.props.mapScale * this.state.positionY * TILE_SIZE_IN_PIXELS + this.props.mapPosition.y;
return (
<Layer opacity={0.6}>
<HoverTile
pixelX={pixelX}
pixelY={pixelY}
- scale={this.props.scale}
+ scale={this.props.mapScale}
isValid={this.state.validity}
onClick={() => this.state.validity ?
this.props.onClick(this.state.positionX, this.state.positionY) : undefined}
/>
{this.props.children ?
- React.cloneElement(this.props.children, {pixelX, pixelY, scale: this.props.scale}) :
+ React.cloneElement(this.props.children, {pixelX, pixelY, scale: this.props.mapScale}) :
undefined
}
</Layer>
diff --git a/src/components/map/layers/MapLayerComponent.js b/src/components/map/layers/MapLayerComponent.js
new file mode 100644
index 00000000..3476bbc9
--- /dev/null
+++ b/src/components/map/layers/MapLayerComponent.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import {Group, Layer} from "react-konva";
+import DatacenterContainer from "../../../containers/map/DatacenterContainer";
+import Backdrop from "../elements/Backdrop";
+import GridGroup from "../groups/GridGroup";
+
+const MapLayerComponent = ({mapPosition, mapScale}) => (
+ <Layer>
+ <Group x={mapPosition.x} y={mapPosition.y} scaleX={mapScale} scaleY={mapScale}>
+ <Backdrop/>
+ <DatacenterContainer/>
+ <GridGroup/>
+ </Group>
+ </Layer>
+);
+
+export default MapLayerComponent;
diff --git a/src/containers/map/MapStage.js b/src/containers/map/MapStage.js
new file mode 100644
index 00000000..62dd7463
--- /dev/null
+++ b/src/containers/map/MapStage.js
@@ -0,0 +1,26 @@
+import {connect} from "react-redux";
+import {setMapDimensions, setMapPosition, setMapScale} from "../../actions/map";
+import MapStageComponent from "../../components/map/MapStageComponent";
+
+const mapStateToProps = state => {
+ return {
+ mapPosition: state.map.position,
+ mapDimensions: state.map.dimensions,
+ mapScale: state.map.scale,
+ };
+};
+
+const mapDispatchToProps = dispatch => {
+ return {
+ setMapPosition: (x, y) => dispatch(setMapPosition(x, y)),
+ setMapDimensions: (width, height) => dispatch(setMapDimensions(width, height)),
+ setMapScale: (scale) => dispatch(setMapScale(scale)),
+ };
+};
+
+const MapStage = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(MapStageComponent);
+
+export default MapStage;
diff --git a/src/containers/map/layers/MapLayer.js b/src/containers/map/layers/MapLayer.js
new file mode 100644
index 00000000..9ef5c662
--- /dev/null
+++ b/src/containers/map/layers/MapLayer.js
@@ -0,0 +1,15 @@
+import {connect} from "react-redux";
+import MapLayerComponent from "../../../components/map/layers/MapLayerComponent";
+
+const mapStateToProps = state => {
+ return {
+ mapPosition: state.map.position,
+ mapScale: state.map.scale,
+ };
+};
+
+const MapLayer = connect(
+ mapStateToProps
+)(MapLayerComponent);
+
+export default MapLayer;
diff --git a/src/containers/map/layers/ObjectHoverLayer.js b/src/containers/map/layers/ObjectHoverLayer.js
index d0cc35fd..b0201257 100644
--- a/src/containers/map/layers/ObjectHoverLayer.js
+++ b/src/containers/map/layers/ObjectHoverLayer.js
@@ -5,6 +5,8 @@ import {findTileWithPosition} from "../../../util/tile-calculations";
const mapStateToProps = state => {
return {
+ mapPosition: state.map.position,
+ mapScale: state.map.scale,
isEnabled: () => state.construction.inRackConstructionMode,
isValid: (x, y) => {
if (state.interactionLevel.mode !== "ROOM") {
diff --git a/src/containers/map/layers/RoomHoverLayer.js b/src/containers/map/layers/RoomHoverLayer.js
index 23f590d5..528e45d3 100644
--- a/src/containers/map/layers/RoomHoverLayer.js
+++ b/src/containers/map/layers/RoomHoverLayer.js
@@ -9,6 +9,8 @@ import {
const mapStateToProps = state => {
return {
+ mapPosition: state.map.position,
+ mapScale: state.map.scale,
isEnabled: () => state.construction.currentRoomInConstruction !== -1,
isValid: (x, y) => {
if (state.interactionLevel.mode !== "BUILDING") {
diff --git a/src/pages/App.js b/src/pages/App.js
index 317442f6..21b3c445 100644
--- a/src/pages/App.js
+++ b/src/pages/App.js
@@ -5,8 +5,8 @@ import {ShortcutManager} from "react-shortcuts";
import {openSimulationSucceeded} from "../actions/simulations";
import {fetchLatestDatacenter, resetCurrentDatacenter} from "../actions/topology/building";
import LoadingScreen from "../components/map/LoadingScreen";
-import MapStage from "../components/map/MapStage";
import AppNavbar from "../components/navigation/AppNavbar";
+import MapStage from "../containers/map/MapStage";
import DeleteMachineModal from "../containers/modals/DeleteMachineModal";
import DeleteRackModal from "../containers/modals/DeleteRackModal";
import DeleteRoomModal from "../containers/modals/DeleteRoomModal";
diff --git a/src/reducers/index.js b/src/reducers/index.js
index f1f51337..1f3aa8f2 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -2,6 +2,7 @@ import {combineReducers} from "redux";
import {auth} from "./auth";
import {construction} from "./construction";
import {interactionLevel} from "./interaction-level";
+import {map} from "./map";
import {modals} from "./modals";
import {objects} from "./objects";
import {simulationList} from "./simulation-list";
@@ -17,6 +18,7 @@ const rootReducer = combineReducers({
currentDatacenterId,
interactionLevel,
construction,
+ map,
});
export default rootReducer;
diff --git a/src/reducers/map.js b/src/reducers/map.js
new file mode 100644
index 00000000..c36916b6
--- /dev/null
+++ b/src/reducers/map.js
@@ -0,0 +1,35 @@
+import {combineReducers} from "redux";
+import {SET_MAP_DIMENSIONS, SET_MAP_POSITION, SET_MAP_SCALE} from "../actions/map";
+
+export function position(state = {x: 0, y: 0}, action) {
+ switch (action.type) {
+ case SET_MAP_POSITION:
+ return {x: action.x, y: action.y};
+ default:
+ return state;
+ }
+}
+
+export function dimensions(state = {width: 600, height: 400}, action) {
+ switch (action.type) {
+ case SET_MAP_DIMENSIONS:
+ return {width: action.width, height: action.height};
+ default:
+ return state;
+ }
+}
+
+export function scale(state = 1, action) {
+ switch (action.type) {
+ case SET_MAP_SCALE:
+ return action.scale;
+ default:
+ return state;
+ }
+}
+
+export const map = combineReducers({
+ position,
+ dimensions,
+ scale
+});