diff options
| -rw-r--r-- | src/actions/topology/machine.js | 39 | ||||
| -rw-r--r-- | src/components/sidebars/Sidebar.sass | 2 | ||||
| -rw-r--r-- | src/components/sidebars/topology/machine/MachineSidebarComponent.js | 2 | ||||
| -rw-r--r-- | src/components/sidebars/topology/machine/UnitAddComponent.js | 37 | ||||
| -rw-r--r-- | src/components/sidebars/topology/machine/UnitComponent.js | 10 | ||||
| -rw-r--r-- | src/components/sidebars/topology/machine/UnitListComponent.js | 17 | ||||
| -rw-r--r-- | src/components/sidebars/topology/machine/UnitTabsComponent.js | 42 | ||||
| -rw-r--r-- | src/containers/sidebars/topology/machine/UnitAddContainer.js | 22 | ||||
| -rw-r--r-- | src/containers/sidebars/topology/machine/UnitContainer.js | 22 | ||||
| -rw-r--r-- | src/containers/sidebars/topology/machine/UnitListContainer.js | 15 | ||||
| -rw-r--r-- | src/sagas/index.js | 6 | ||||
| -rw-r--r-- | src/sagas/topology.js | 36 |
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); + } +} |
