From fc9c52a8f102202bd0e1a8a9dc4d8d68babe2304 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Fri, 8 Sep 2017 10:27:00 +0200 Subject: Implement UI for unit addition and removal --- src/actions/topology/machine.js | 39 ++++++++++++++++++++ src/components/sidebars/Sidebar.sass | 2 +- .../topology/machine/MachineSidebarComponent.js | 2 ++ .../sidebars/topology/machine/UnitAddComponent.js | 37 +++++++++++++++++++ .../sidebars/topology/machine/UnitComponent.js | 10 ++++++ .../sidebars/topology/machine/UnitListComponent.js | 17 +++++++++ .../sidebars/topology/machine/UnitTabsComponent.js | 42 ++++++++++++++++++++++ .../sidebars/topology/machine/UnitAddContainer.js | 22 ++++++++++++ .../sidebars/topology/machine/UnitContainer.js | 22 ++++++++++++ .../sidebars/topology/machine/UnitListContainer.js | 15 ++++++++ src/sagas/index.js | 6 +++- src/sagas/topology.js | 36 ++++++++++++++++++- 12 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 src/components/sidebars/topology/machine/UnitAddComponent.js create mode 100644 src/components/sidebars/topology/machine/UnitComponent.js create mode 100644 src/components/sidebars/topology/machine/UnitListComponent.js create mode 100644 src/components/sidebars/topology/machine/UnitTabsComponent.js create mode 100644 src/containers/sidebars/topology/machine/UnitAddContainer.js create mode 100644 src/containers/sidebars/topology/machine/UnitContainer.js create mode 100644 src/containers/sidebars/topology/machine/UnitListContainer.js 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 = () => { + ); }; 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 ( +
+
+ + +
+
+ ); + } +} + +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}) => ( +
  • + {unit.manufacturer + " " + unit.family + " " + unit.model + " " + unit.generation} + Delete +
  • +); + +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}) => ( +
      + {unitIds.length !== 0 ? + unitIds.map((unitId, index) => ( + + )) : +
      + No units... Add some with the menu above! +
      + } +
    +); + +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 = () => ( +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +); + +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); + } +} -- cgit v1.2.3