summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-07-16 10:32:57 +0200
committerGitHub <noreply@github.com>2021-07-16 10:32:57 +0200
commitdb1d2c2f8c18850dedf34b5d690b6cd6a1d1f6b5 (patch)
tree263a6f9741c5ca0dd64ecf3f7f07b580331aec9d /opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack
parent1a2416043f0b877f570e89da74e0d0a4aff1d8ae (diff)
parent803e13b32cf0ff8b496649fb0a4d6e32400e98a4 (diff)
merge: Add PatternFly 4 web interface (#161)
This pull requests adds the new web interface based on the PatternFly 4 design framework. This framework enables us to develop more quickly the interfaces necessary in OpenDC. * Remove the OpenDC landing page from the web interface module * Add support for the PatternFly 4 framework in Next.js * Relax topology schema requirements * Migrate UI components to PatternFly 4
Diffstat (limited to 'opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack')
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabComponent.js8
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabContainer.js33
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/BackToRoomComponent.js18
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackContainer.js54
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/EmptySlotComponent.js24
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineComponent.js51
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.js69
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.module.scss3
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListContainer.js56
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameContainer.js22
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.js61
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.module.scss6
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarContainer.js32
13 files changed, 327 insertions, 110 deletions
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabComponent.js
index a330c302..c8543134 100644
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabComponent.js
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabComponent.js
@@ -1,12 +1,10 @@
import PropTypes from 'prop-types'
import React from 'react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faSave } from '@fortawesome/free-solid-svg-icons'
-import { Button } from 'reactstrap'
+import { SaveIcon } from '@patternfly/react-icons'
+import { Button } from '@patternfly/react-core'
const AddPrefabComponent = ({ onClick }) => (
- <Button color="primary" block onClick={onClick}>
- <FontAwesomeIcon icon={faSave} className="mr-2" />
+ <Button variant="primary" icon={<SaveIcon />} isBlock onClick={onClick} className="pf-u-mb-sm">
Save this rack to a prefab
</Button>
)
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabContainer.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabContainer.js
new file mode 100644
index 00000000..d3d9aaf5
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/AddPrefabContainer.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React from 'react'
+import { useDispatch } from 'react-redux'
+import { addPrefab } from '../../../../../redux/actions/prefabs'
+import AddPrefabComponent from './AddPrefabComponent'
+
+const AddPrefabContainer = (props) => {
+ const dispatch = useDispatch()
+ return <AddPrefabComponent {...props} onClick={() => dispatch(addPrefab('name'))} />
+}
+
+export default AddPrefabContainer
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/BackToRoomComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/BackToRoomComponent.js
deleted file mode 100644
index e0eb5979..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/BackToRoomComponent.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faAngleLeft } from '@fortawesome/free-solid-svg-icons'
-import { Button } from 'reactstrap'
-
-const BackToRoomComponent = ({ onClick }) => (
- <Button color="secondary" block className="mb-2" onClick={onClick}>
- <FontAwesomeIcon icon={faAngleLeft} className="mr-2" />
- Back to room
- </Button>
-)
-
-BackToRoomComponent.propTypes = {
- onClick: PropTypes.func,
-}
-
-export default BackToRoomComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackContainer.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackContainer.js
new file mode 100644
index 00000000..47959f03
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackContainer.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React, { useState } from 'react'
+import { useDispatch } from 'react-redux'
+import ConfirmationModal from '../../../../../components/modals/ConfirmationModal'
+import { deleteRack } from '../../../../../redux/actions/topology/rack'
+import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon'
+import { Button } from '@patternfly/react-core'
+
+const DeleteRackContainer = () => {
+ const dispatch = useDispatch()
+ const [isVisible, setVisible] = useState(false)
+ const callback = (isConfirmed) => {
+ if (isConfirmed) {
+ dispatch(deleteRack())
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <Button variant="danger" icon={<TrashIcon />} isBlock onClick={() => setVisible(true)}>
+ Delete this rack
+ </Button>
+ <ConfirmationModal
+ title="Delete this rack"
+ message="Are you sure you want to delete this rack?"
+ isOpen={isVisible}
+ callback={callback}
+ />
+ </>
+ )
+}
+
+export default DeleteRackContainer
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/EmptySlotComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/EmptySlotComponent.js
deleted file mode 100644
index 63b319e0..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/EmptySlotComponent.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faPlus } from '@fortawesome/free-solid-svg-icons'
-import { ListGroupItem, Badge, Button } from 'reactstrap'
-
-const EmptySlotComponent = ({ position, onAdd }) => (
- <ListGroupItem className="d-flex justify-content-between align-items-center">
- <Badge color="info" className="mr-1">
- {position}
- </Badge>
- <Button color="primary" outline onClick={onAdd}>
- <FontAwesomeIcon icon={faPlus} className="mr-2" />
- Add machine
- </Button>
- </ListGroupItem>
-)
-
-EmptySlotComponent.propTypes = {
- position: PropTypes.number,
- onAdd: PropTypes.func,
-}
-
-export default EmptySlotComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineComponent.js
index b71918da..1617b3bf 100644
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineComponent.js
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineComponent.js
@@ -2,18 +2,16 @@ import PropTypes from 'prop-types'
import React from 'react'
import Image from 'next/image'
import { Machine } from '../../../../../shapes'
-import { Badge, ListGroupItem } from 'reactstrap'
+import { Flex, Label } from '@patternfly/react-core'
const UnitIcon = ({ id, type }) => (
- <div className="ml-1">
- <Image
- src={'/img/topology/' + id + '-icon.png'}
- alt={'Machine contains ' + type + ' units'}
- layout="intrinsic"
- height={35}
- width={35}
- />
- </div>
+ <Image
+ src={'/img/topology/' + id + '-icon.png'}
+ alt={'Machine contains ' + type + ' units'}
+ layout="intrinsic"
+ height={24}
+ width={24}
+ />
)
UnitIcon.propTypes = {
@@ -21,34 +19,27 @@ UnitIcon.propTypes = {
type: PropTypes.string,
}
-const MachineComponent = ({ position, machine, onClick }) => {
+const MachineComponent = ({ machine, onClick }) => {
const hasNoUnits =
machine.cpus.length + machine.gpus.length + machine.memories.length + machine.storages.length === 0
return (
- <ListGroupItem
- action
- className="d-flex justify-content-between align-items-center"
- onClick={onClick}
- style={{ backgroundColor: 'white' }}
- >
- <Badge color="info" className="mr-1">
- {position}
- </Badge>
- <div className="d-inline-flex">
- {machine.cpus.length > 0 ? <UnitIcon id="cpu" type="CPU" /> : undefined}
- {machine.gpus.length > 0 ? <UnitIcon id="gpu" type="GPU" /> : undefined}
- {machine.memories.length > 0 ? <UnitIcon id="memory" type="memory" /> : undefined}
- {machine.storages.length > 0 ? <UnitIcon id="storage" type="storage" /> : undefined}
- {hasNoUnits ? <Badge color="warning">Machine with no units</Badge> : undefined}
- </div>
- </ListGroupItem>
+ <Flex onClick={() => onClick()}>
+ {machine.cpus.length > 0 ? <UnitIcon id="cpu" type="CPU" /> : undefined}
+ {machine.gpus.length > 0 ? <UnitIcon id="gpu" type="GPU" /> : undefined}
+ {machine.memories.length > 0 ? <UnitIcon id="memory" type="memory" /> : undefined}
+ {machine.storages.length > 0 ? <UnitIcon id="storage" type="storage" /> : undefined}
+ {hasNoUnits ? (
+ <Label variant="outline" color="orange">
+ Machine with no units
+ </Label>
+ ) : undefined}
+ </Flex>
)
}
MachineComponent.propTypes = {
- machine: Machine,
- position: PropTypes.number,
+ machine: Machine.isRequired,
onClick: PropTypes.func,
}
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.js
index e024a417..27834cf4 100644
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.js
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.js
@@ -1,21 +1,66 @@
import PropTypes from 'prop-types'
import React from 'react'
-import { machineList } from './MachineListComponent.module.scss'
import MachineComponent from './MachineComponent'
import { Machine } from '../../../../../shapes'
-import EmptySlotComponent from './EmptySlotComponent'
+import {
+ Badge,
+ Button,
+ DataList,
+ DataListAction,
+ DataListCell,
+ DataListItem,
+ DataListItemCells,
+ DataListItemRow,
+} from '@patternfly/react-core'
+import { AngleRightIcon, PlusIcon } from '@patternfly/react-icons'
-const MachineListComponent = ({ machines = [], onSelect, onAdd }) => {
+function MachineListComponent({ machines = [], onSelect, onAdd }) {
return (
- <ul className={`list-group ${machineList}`}>
- {machines.map((machine, index) => {
- if (machine === null) {
- return <EmptySlotComponent key={index} onAdd={() => onAdd(index + 1)} />
- } else {
- return <MachineComponent key={index} onClick={() => onSelect(index + 1)} machine={machine} />
- }
- })}
- </ul>
+ <DataList aria-label="Rack Units">
+ {machines.map((machine, index) =>
+ machine ? (
+ <DataListItem key={index} onClick={() => onSelect(index + 1)}>
+ <DataListItemRow>
+ <DataListItemCells
+ dataListCells={[
+ <DataListCell isIcon key="icon">
+ <Badge isRead>{machines.length - index}U</Badge>
+ </DataListCell>,
+ <DataListCell key="primary content">
+ <MachineComponent onClick={() => onSelect(index + 1)} machine={machine} />
+ </DataListCell>,
+ ]}
+ />
+ <DataListAction id="goto" aria-label="Goto Machine" aria-labelledby="goto">
+ <Button isSmall variant="plain" className="pf-u-p-0">
+ <AngleRightIcon />
+ </Button>
+ </DataListAction>
+ </DataListItemRow>
+ </DataListItem>
+ ) : (
+ <DataListItem key={index}>
+ <DataListItemRow>
+ <DataListItemCells
+ dataListCells={[
+ <DataListCell isIcon key="icon">
+ <Badge isRead>{machines.length - index}U</Badge>
+ </DataListCell>,
+ <DataListCell key="add" className="text-secondary">
+ Empty Slot
+ </DataListCell>,
+ ]}
+ />
+ <DataListAction id="add" aria-label="Add Machine" aria-labelledby="add">
+ <Button isSmall variant="plain" className="pf-u-p-0" onClick={() => onAdd(index + 1)}>
+ <PlusIcon />
+ </Button>
+ </DataListAction>
+ </DataListItemRow>
+ </DataListItem>
+ )
+ )}
+ </DataList>
)
}
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.module.scss b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.module.scss
deleted file mode 100644
index f075aac9..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListComponent.module.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.machineList li {
- min-height: 64px;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListContainer.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListContainer.js
new file mode 100644
index 00000000..54e6db0a
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/MachineListContainer.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import PropTypes from 'prop-types'
+import React, { useMemo } from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import MachineListComponent from './MachineListComponent'
+import { goFromRackToMachine } from '../../../../../redux/actions/interaction-level'
+import { addMachine } from '../../../../../redux/actions/topology/rack'
+
+function MachineListContainer({ tileId, ...props }) {
+ const rack = useSelector((state) => state.objects.rack[state.objects.tile[tileId].rack])
+ const machines = useSelector((state) => rack.machines.map((id) => state.objects.machine[id]))
+ const machinesNull = useMemo(() => {
+ const res = Array(rack.capacity).fill(null)
+ for (const machine of machines) {
+ res[machine.position - 1] = machine
+ }
+ return res
+ }, [rack, machines])
+ const dispatch = useDispatch()
+
+ return (
+ <MachineListComponent
+ {...props}
+ machines={machinesNull}
+ onAdd={(index) => dispatch(addMachine(index))}
+ onSelect={(index) => dispatch(goFromRackToMachine(index))}
+ />
+ )
+}
+
+MachineListContainer.propTypes = {
+ tileId: PropTypes.string.isRequired,
+}
+
+export default MachineListContainer
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameContainer.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameContainer.js
new file mode 100644
index 00000000..11529b55
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameContainer.js
@@ -0,0 +1,22 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import NameComponent from '../NameComponent'
+import { editRackName } from '../../../../../redux/actions/topology/rack'
+
+const RackNameContainer = ({ tileId }) => {
+ const rackName = useSelector((state) => state.objects.rack[state.objects.tile[tileId].rack].name)
+ const dispatch = useDispatch()
+ const callback = (name) => {
+ if (name) {
+ dispatch(editRackName(name))
+ }
+ }
+ return <NameComponent name={rackName} onEdit={callback} />
+}
+
+RackNameContainer.propTypes = {
+ tileId: PropTypes.string.isRequired,
+}
+
+export default RackNameContainer
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.js
index 74313bf7..dd5117f7 100644
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.js
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.js
@@ -1,25 +1,58 @@
+import PropTypes from 'prop-types'
import React from 'react'
-import BackToRoomContainer from '../../../../../containers/app/sidebars/topology/rack/BackToRoomContainer'
-import DeleteRackContainer from '../../../../../containers/app/sidebars/topology/rack/DeleteRackContainer'
-import MachineListContainer from '../../../../../containers/app/sidebars/topology/rack/MachineListContainer'
-import RackNameContainer from '../../../../../containers/app/sidebars/topology/rack/RackNameContainer'
-import { sidebarContainer, sidebarHeaderContainer, machineListContainer } from './RackSidebarComponent.module.scss'
-import AddPrefabContainer from '../../../../../containers/app/sidebars/topology/rack/AddPrefabContainer'
+import { machineListContainer, sidebarContainer } from './RackSidebarComponent.module.scss'
+import RackNameContainer from './RackNameContainer'
+import AddPrefabContainer from './AddPrefabContainer'
+import DeleteRackContainer from './DeleteRackContainer'
+import MachineListContainer from './MachineListContainer'
+import {
+ Skeleton,
+ TextContent,
+ TextList,
+ TextListItem,
+ TextListItemVariants,
+ TextListVariants,
+ Title,
+} from '@patternfly/react-core'
+import { useSelector } from 'react-redux'
+
+function RackSidebarComponent({ tileId }) {
+ const rack = useSelector((state) => state.objects.rack[state.objects.tile[tileId].rack])
-const RackSidebarComponent = () => {
return (
- <div className={`${sidebarContainer} flex-column`}>
- <div className={sidebarHeaderContainer}>
- <RackNameContainer />
- <BackToRoomContainer />
+ <div className={sidebarContainer}>
+ <TextContent>
+ <Title headingLevel="h2">Details</Title>
+ <TextList component={TextListVariants.dl}>
+ <TextListItem
+ component={TextListItemVariants.dt}
+ className="pf-u-display-inline-flex pf-u-align-items-center"
+ >
+ Name
+ </TextListItem>
+ <TextListItem component={TextListItemVariants.dd}>
+ <RackNameContainer tileId={tileId} />
+ </TextListItem>
+ <TextListItem component={TextListItemVariants.dt}>Capacity</TextListItem>
+ <TextListItem component={TextListItemVariants.dd}>
+ {rack?.capacity ?? <Skeleton screenreaderText="Loading rack" />}
+ </TextListItem>
+ </TextList>
+ <Title headingLevel="h2">Actions</Title>
<AddPrefabContainer />
<DeleteRackContainer />
- </div>
- <div className={`${machineListContainer} mt-2`}>
- <MachineListContainer />
+
+ <Title headingLevel="h2">Slots</Title>
+ </TextContent>
+ <div className={machineListContainer}>
+ <MachineListContainer tileId={tileId} />
</div>
</div>
)
}
+RackSidebarComponent.propTypes = {
+ tileId: PropTypes.string.isRequired,
+}
+
export default RackSidebarComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.module.scss b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.module.scss
index 8ce3836a..6f258aec 100644
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.module.scss
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarComponent.module.scss
@@ -2,13 +2,11 @@
display: flex;
height: 100%;
max-height: 100%;
-}
-
-.sidebarHeaderContainer {
- flex: 0;
+ flex-direction: column;
}
.machineListContainer {
flex: 1;
overflow-y: scroll;
+ margin-top: 10px;
}
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarContainer.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarContainer.js
new file mode 100644
index 00000000..2b31413d
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackSidebarContainer.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React from 'react'
+import { useSelector } from 'react-redux'
+import RackSidebarComponent from './RackSidebarComponent'
+
+const RackSidebarContainer = (props) => {
+ const tileId = useSelector((state) => state.interactionLevel.tileId)
+ return <RackSidebarComponent {...props} tileId={tileId} />
+}
+
+export default RackSidebarContainer