summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgios Andreadis <g.andreadis@student.tudelft.nl>2017-09-08 10:27:00 +0200
committerGeorgios Andreadis <g.andreadis@student.tudelft.nl>2017-09-23 10:05:59 +0200
commitfc9c52a8f102202bd0e1a8a9dc4d8d68babe2304 (patch)
tree0025827d791a3eeb5416bb89d4c36e777feabdd7
parent1b5d2658f9ec06308b2a5ed062f6f5b4798ed733 (diff)
Implement UI for unit addition and removal
-rw-r--r--src/actions/topology/machine.js39
-rw-r--r--src/components/sidebars/Sidebar.sass2
-rw-r--r--src/components/sidebars/topology/machine/MachineSidebarComponent.js2
-rw-r--r--src/components/sidebars/topology/machine/UnitAddComponent.js37
-rw-r--r--src/components/sidebars/topology/machine/UnitComponent.js10
-rw-r--r--src/components/sidebars/topology/machine/UnitListComponent.js17
-rw-r--r--src/components/sidebars/topology/machine/UnitTabsComponent.js42
-rw-r--r--src/containers/sidebars/topology/machine/UnitAddContainer.js22
-rw-r--r--src/containers/sidebars/topology/machine/UnitContainer.js22
-rw-r--r--src/containers/sidebars/topology/machine/UnitListContainer.js15
-rw-r--r--src/sagas/index.js6
-rw-r--r--src/sagas/topology.js36
12 files changed, 247 insertions, 3 deletions
diff --git a/src/actions/topology/machine.js b/src/actions/topology/machine.js
index af258a6f..e11c7d1d 100644
--- a/src/actions/topology/machine.js
+++ b/src/actions/topology/machine.js
@@ -2,6 +2,8 @@ import {goDownOneInteractionLevel} from "../interaction-level";
import {addPropToStoreObject} from "../objects";
export const DELETE_MACHINE = "DELETE_MACHINE";
+export const ADD_UNIT = "ADD_UNIT";
+export const DELETE_UNIT = "DELETE_UNIT";
export function deleteMachine() {
return {
@@ -19,3 +21,40 @@ export function deleteMachineSucceeded() {
dispatch(addPropToStoreObject("rack", rack.id, {machineIds}));
};
}
+
+export function addUnit(unitType, id) {
+ return {
+ type: ADD_UNIT,
+ unitType,
+ id
+ };
+}
+
+export function addUnitSucceeded(unitType, id) {
+ return (dispatch, getState) => {
+ const {objects, interactionLevel} = getState();
+ const machine = objects.machine[objects.rack[objects.tile[interactionLevel.tileId].objectId]
+ .machineIds[interactionLevel.position - 1]];
+ const units = [...machine[unitType + "Ids"], id];
+ dispatch(addPropToStoreObject("machine", machine.id, {[unitType + "Ids"]: units}));
+ };
+}
+
+export function deleteUnit(unitType, index) {
+ return {
+ type: DELETE_UNIT,
+ unitType,
+ index
+ };
+}
+
+export function deleteUnitSucceeded(unitType, index) {
+ return (dispatch, getState) => {
+ const {objects, interactionLevel} = getState();
+ const machine = objects.machine[objects.rack[objects.tile[interactionLevel.tileId].objectId]
+ .machineIds[interactionLevel.position - 1]];
+ const unitIds = machine[unitType + "Ids"].slice();
+ unitIds.splice(index, 1);
+ dispatch(addPropToStoreObject("machine", machine.id, {[unitType + "Ids"]: unitIds}));
+ };
+}
diff --git a/src/components/sidebars/Sidebar.sass b/src/components/sidebars/Sidebar.sass
index 16a6d48f..c3796d59 100644
--- a/src/components/sidebars/Sidebar.sass
+++ b/src/components/sidebars/Sidebar.sass
@@ -4,7 +4,7 @@
position: absolute
top: 0
left: 0
- width: 300px
+ width: 350px
z-index: 100
background: white
diff --git a/src/components/sidebars/topology/machine/MachineSidebarComponent.js b/src/components/sidebars/topology/machine/MachineSidebarComponent.js
index 117db784..218e4f41 100644
--- a/src/components/sidebars/topology/machine/MachineSidebarComponent.js
+++ b/src/components/sidebars/topology/machine/MachineSidebarComponent.js
@@ -2,6 +2,7 @@ import React from "react";
import BackToRackContainer from "../../../../containers/sidebars/topology/machine/BackToRackContainer";
import DeleteMachineContainer from "../../../../containers/sidebars/topology/machine/DeleteMachineContainer";
import MachineNameContainer from "../../../../containers/sidebars/topology/machine/MachineNameContainer";
+import UnitTabsComponent from "./UnitTabsComponent";
const MachineSidebarComponent = () => {
return (
@@ -9,6 +10,7 @@ const MachineSidebarComponent = () => {
<MachineNameContainer/>
<BackToRackContainer/>
<DeleteMachineContainer/>
+ <UnitTabsComponent/>
</div>
);
};
diff --git a/src/components/sidebars/topology/machine/UnitAddComponent.js b/src/components/sidebars/topology/machine/UnitAddComponent.js
new file mode 100644
index 00000000..a1c9eb76
--- /dev/null
+++ b/src/components/sidebars/topology/machine/UnitAddComponent.js
@@ -0,0 +1,37 @@
+import PropTypes from "prop-types";
+import React from "react";
+
+class UnitAddComponent extends React.Component {
+ static propTypes = {
+ units: PropTypes.array.isRequired,
+ onAdd: PropTypes.func.isRequired,
+ };
+
+ render() {
+ return (
+ <div className="form-inline">
+ <div className="form-group w-100">
+ <select
+ className="form-control w-75 mr-1"
+ ref={unitSelect => this.unitSelect = unitSelect}
+ >
+ {this.props.units.map(unit => (
+ <option value={unit.id} key={unit.id}>
+ {unit.manufacturer + " " + unit.family + " " + unit.model + " " + unit.generation}
+ </option>
+ ))}
+ </select>
+ <button
+ type="submit"
+ className="btn btn-primary"
+ onClick={() => this.props.onAdd(parseInt(this.unitSelect.value, 10))}
+ >
+ Add
+ </button>
+ </div>
+ </div>
+ );
+ }
+}
+
+export default UnitAddComponent;
diff --git a/src/components/sidebars/topology/machine/UnitComponent.js b/src/components/sidebars/topology/machine/UnitComponent.js
new file mode 100644
index 00000000..20cdad1e
--- /dev/null
+++ b/src/components/sidebars/topology/machine/UnitComponent.js
@@ -0,0 +1,10 @@
+import React from "react";
+
+const UnitComponent = ({unit, onDelete}) => (
+ <li className="d-flex list-group-item justify-content-between align-items-center">
+ {unit.manufacturer + " " + unit.family + " " + unit.model + " " + unit.generation}
+ <span className="btn btn-outline-danger" onClick={onDelete}>Delete</span>
+ </li>
+);
+
+export default UnitComponent;
diff --git a/src/components/sidebars/topology/machine/UnitListComponent.js b/src/components/sidebars/topology/machine/UnitListComponent.js
new file mode 100644
index 00000000..288d1428
--- /dev/null
+++ b/src/components/sidebars/topology/machine/UnitListComponent.js
@@ -0,0 +1,17 @@
+import React from "react";
+import UnitContainer from "../../../../containers/sidebars/topology/machine/UnitContainer";
+
+const UnitListComponent = ({unitType, unitIds}) => (
+ <ul className="list-group mt-1">
+ {unitIds.length !== 0 ?
+ unitIds.map((unitId, index) => (
+ <UnitContainer unitType={unitType} unitId={unitId} index={index} key={index}/>
+ )) :
+ <div className="alert alert-info">
+ <strong>No units...</strong> Add some with the menu above!
+ </div>
+ }
+ </ul>
+);
+
+export default UnitListComponent;
diff --git a/src/components/sidebars/topology/machine/UnitTabsComponent.js b/src/components/sidebars/topology/machine/UnitTabsComponent.js
new file mode 100644
index 00000000..cd068442
--- /dev/null
+++ b/src/components/sidebars/topology/machine/UnitTabsComponent.js
@@ -0,0 +1,42 @@
+import React from "react";
+import UnitAddContainer from "../../../../containers/sidebars/topology/machine/UnitAddContainer";
+import UnitListContainer from "../../../../containers/sidebars/topology/machine/UnitListContainer";
+
+const UnitTabsComponent = () => (
+ <div>
+ <ul className="nav nav-tabs mt-2 mb-1" role="tablist">
+ <li className="nav-item">
+ <a className="nav-link active" data-toggle="tab" href="#cpu-units" role="tab">CPU</a>
+ </li>
+ <li className="nav-item">
+ <a className="nav-link" data-toggle="tab" href="#gpu-units" role="tab">GPU</a>
+ </li>
+ <li className="nav-item">
+ <a className="nav-link" data-toggle="tab" href="#memory-units" role="tab">Memory</a>
+ </li>
+ <li className="nav-item">
+ <a className="nav-link" data-toggle="tab" href="#storage-units" role="tab">Storage</a>
+ </li>
+ </ul>
+ <div className="tab-content">
+ <div className="tab-pane active" id="cpu-units" role="tabpanel">
+ <UnitAddContainer unitType="cpu"/>
+ <UnitListContainer unitType="cpu"/>
+ </div>
+ <div className="tab-pane" id="gpu-units" role="tabpanel">
+ <UnitAddContainer unitType="gpu"/>
+ <UnitListContainer unitType="gpu"/>
+ </div>
+ <div className="tab-pane" id="memory-units" role="tabpanel">
+ <UnitAddContainer unitType="memory"/>
+ <UnitListContainer unitType="memory"/>
+ </div>
+ <div className="tab-pane" id="storage-units" role="tabpanel">
+ <UnitAddContainer unitType="storage"/>
+ <UnitListContainer unitType="storage"/>
+ </div>
+ </div>
+ </div>
+);
+
+export default UnitTabsComponent;
diff --git a/src/containers/sidebars/topology/machine/UnitAddContainer.js b/src/containers/sidebars/topology/machine/UnitAddContainer.js
new file mode 100644
index 00000000..66e35030
--- /dev/null
+++ b/src/containers/sidebars/topology/machine/UnitAddContainer.js
@@ -0,0 +1,22 @@
+import {connect} from "react-redux";
+import {addUnit} from "../../../../actions/topology/machine";
+import UnitAddComponent from "../../../../components/sidebars/topology/machine/UnitAddComponent";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ units: Object.values(state.objects[ownProps.unitType]),
+ };
+};
+
+const mapDispatchToProps = (dispatch, ownProps) => {
+ return {
+ onAdd: (id) => dispatch(addUnit(ownProps.unitType, id)),
+ };
+};
+
+const UnitAddContainer = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(UnitAddComponent);
+
+export default UnitAddContainer;
diff --git a/src/containers/sidebars/topology/machine/UnitContainer.js b/src/containers/sidebars/topology/machine/UnitContainer.js
new file mode 100644
index 00000000..712d3eef
--- /dev/null
+++ b/src/containers/sidebars/topology/machine/UnitContainer.js
@@ -0,0 +1,22 @@
+import {connect} from "react-redux";
+import {deleteUnit} from "../../../../actions/topology/machine";
+import UnitComponent from "../../../../components/sidebars/topology/machine/UnitComponent";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ unit: state.objects[ownProps.unitType][ownProps.unitId],
+ };
+};
+
+const mapDispatchToProps = (dispatch, ownProps) => {
+ return {
+ onDelete: () => dispatch(deleteUnit(ownProps.unitType, ownProps.index)),
+ };
+};
+
+const UnitContainer = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(UnitComponent);
+
+export default UnitContainer;
diff --git a/src/containers/sidebars/topology/machine/UnitListContainer.js b/src/containers/sidebars/topology/machine/UnitListContainer.js
new file mode 100644
index 00000000..cf3a2639
--- /dev/null
+++ b/src/containers/sidebars/topology/machine/UnitListContainer.js
@@ -0,0 +1,15 @@
+import {connect} from "react-redux";
+import UnitListComponent from "../../../../components/sidebars/topology/machine/UnitListComponent";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ unitIds: state.objects.machine[state.objects.rack[state.objects.tile[state.interactionLevel.tileId].objectId]
+ .machineIds[state.interactionLevel.position - 1]][ownProps.unitType + "Ids"],
+ };
+};
+
+const UnitListContainer = connect(
+ mapStateToProps
+)(UnitListComponent);
+
+export default UnitListContainer;
diff --git a/src/sagas/index.js b/src/sagas/index.js
index a064de33..5cb25202 100644
--- a/src/sagas/index.js
+++ b/src/sagas/index.js
@@ -8,7 +8,7 @@ import {
FETCH_LATEST_DATACENTER,
START_NEW_ROOM_CONSTRUCTION
} from "../actions/topology/building";
-import {DELETE_MACHINE} from "../actions/topology/machine";
+import {ADD_UNIT, DELETE_MACHINE, DELETE_UNIT} from "../actions/topology/machine";
import {ADD_MACHINE, DELETE_RACK, EDIT_RACK_NAME} from "../actions/topology/rack";
import {ADD_RACK_TO_TILE, DELETE_ROOM, EDIT_ROOM_NAME} from "../actions/topology/room";
import {DELETE_CURRENT_USER, FETCH_AUTHORIZATIONS_OF_CURRENT_USER} from "../actions/users";
@@ -18,11 +18,13 @@ import {
onAddMachine,
onAddRackToTile,
onAddTile,
+ onAddUnit,
onCancelNewRoomConstruction,
onDeleteMachine,
onDeleteRack,
onDeleteRoom,
onDeleteTile,
+ onDeleteUnit,
onEditRackName,
onEditRoomName,
onFetchLatestDatacenter,
@@ -48,4 +50,6 @@ export default function* rootSaga() {
yield takeEvery(ADD_RACK_TO_TILE, onAddRackToTile);
yield takeEvery(ADD_MACHINE, onAddMachine);
yield takeEvery(DELETE_MACHINE, onDeleteMachine);
+ yield takeEvery(ADD_UNIT, onAddUnit);
+ yield takeEvery(DELETE_UNIT, onDeleteUnit);
}
diff --git a/src/sagas/topology.js b/src/sagas/topology.js
index 9eab4368..f507b2ad 100644
--- a/src/sagas/topology.js
+++ b/src/sagas/topology.js
@@ -7,7 +7,7 @@ import {
fetchLatestDatacenterSucceeded,
startNewRoomConstructionSucceeded
} from "../actions/topology/building";
-import {deleteMachineSucceeded} from "../actions/topology/machine";
+import {addUnitSucceeded, deleteMachineSucceeded, deleteUnitSucceeded} from "../actions/topology/machine";
import {addMachineSucceeded, deleteRackSucceeded, editRackNameSucceeded} from "../actions/topology/rack";
import {addRackToTileSucceeded, deleteRoomSucceeded, editRoomNameSucceeded} from "../actions/topology/room";
import {addRoomToDatacenter} from "../api/routes/datacenters";
@@ -18,6 +18,7 @@ import {
deleteMachineInRackOnTile,
deleteRackFromTile,
deleteTile,
+ updateMachineInRackOnTile,
updateRackOnTile
} from "../api/routes/tiles";
import {
@@ -262,3 +263,36 @@ export function* onDeleteMachine() {
console.log(error);
}
}
+
+export function* onAddUnit(action) {
+ try {
+ const tileId = yield select(state => state.interactionLevel.tileId);
+ const position = yield select(state => state.interactionLevel.position);
+ const machine = yield select(state => state.objects.machine[state.objects.rack[
+ state.objects.tile[tileId].objectId].machineIds[position - 1]]);
+ const updatedMachine = Object.assign({}, machine,
+ {[action.unitType + "Ids"]: [...machine[action.unitType + "Ids"], action.id]});
+
+ yield call(updateMachineInRackOnTile, tileId, position, updatedMachine);
+ yield put(addUnitSucceeded(action.unitType, action.id));
+ } catch (error) {
+ console.log(error);
+ }
+}
+
+export function* onDeleteUnit(action) {
+ try {
+ const tileId = yield select(state => state.interactionLevel.tileId);
+ const position = yield select(state => state.interactionLevel.position);
+ const machine = yield select(state => state.objects.machine[state.objects.rack[
+ state.objects.tile[tileId].objectId].machineIds[position - 1]]);
+ const unitIds = machine[action.unitType + "Ids"].slice();
+ unitIds.splice(action.index, 1);
+ const updatedMachine = Object.assign({}, machine, {[action.unitType + "Ids"]: unitIds});
+
+ yield call(updateMachineInRackOnTile, tileId, position, updatedMachine);
+ yield put(deleteUnitSucceeded(action.unitType, action.index));
+ } catch (error) {
+ console.log(error);
+ }
+}