From 3d1c02e50ee619598bcd7fad4368be8b4a039e84 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 7 Mar 2022 18:19:21 +0100 Subject: refactor(web/ui): Fix compatibility with new API This change updates the web interface in React to be compatible with the new API written in Kotlin. Several changes have been made in the new API to ensure consistency. --- opendc-web/opendc-web-ui/src/api/index.js | 2 +- opendc-web/opendc-web-ui/src/api/portfolios.js | 18 +-- opendc-web/opendc-web-ui/src/api/prefabs.js | 39 ------ opendc-web/opendc-web-ui/src/api/projects.js | 6 +- opendc-web/opendc-web-ui/src/api/scenarios.js | 20 ++- opendc-web/opendc-web-ui/src/api/topologies.js | 19 ++- .../opendc-web-ui/src/components/AppNavigation.js | 30 +---- .../src/components/context/ContextSelector.js | 21 ++- .../components/context/ContextSelector.module.scss | 1 - .../src/components/context/PortfolioSelector.js | 24 ++-- .../src/components/context/ProjectSelector.js | 17 ++- .../src/components/context/TopologySelector.js | 23 ++-- .../src/components/portfolios/NewScenario.js | 20 ++- .../src/components/portfolios/NewScenarioModal.js | 48 ++++--- .../src/components/portfolios/PortfolioOverview.js | 23 ++-- .../src/components/portfolios/PortfolioResults.js | 19 +-- .../src/components/portfolios/ScenarioState.js | 6 +- .../src/components/portfolios/ScenarioTable.js | 31 ++--- .../src/components/projects/NewPortfolio.js | 6 +- .../src/components/projects/NewPortfolioModal.js | 2 +- .../src/components/projects/NewProject.js | 4 +- .../src/components/projects/NewTopology.js | 16 +-- .../src/components/projects/NewTopologyModal.js | 22 ++-- .../src/components/projects/PortfolioTable.js | 27 ++-- .../src/components/projects/ProjectOverview.js | 2 +- .../src/components/projects/ProjectTable.js | 11 +- .../src/components/projects/TopologyTable.js | 19 +-- .../src/components/topologies/RoomTable.js | 9 +- .../src/components/topologies/TopologyOverview.js | 15 ++- .../src/components/topologies/map/TileContainer.js | 2 +- .../topologies/map/elements/ImageComponent.js | 1 + .../components/topologies/map/groups/RackGroup.js | 4 +- .../components/topologies/map/groups/RoomGroup.js | 6 +- .../topologies/map/layers/RoomHoverLayer.js | 4 +- .../topologies/sidebar/machine/MachineSidebar.js | 2 +- .../topologies/sidebar/machine/UnitAddComponent.js | 2 +- .../sidebar/machine/UnitListContainer.js | 2 +- .../topologies/sidebar/rack/AddPrefab.js | 7 +- .../sidebar/rack/MachineListContainer.js | 2 +- .../topologies/sidebar/rack/RackNameContainer.js | 4 +- .../components/topologies/sidebar/room/RoomName.js | 4 +- opendc-web/opendc-web-ui/src/data/experiments.js | 8 +- opendc-web/opendc-web-ui/src/data/project.js | 114 +++++++++------- opendc-web/opendc-web-ui/src/data/topology.js | 69 ++++++---- opendc-web/opendc-web-ui/src/pages/_app.js | 14 ++ opendc-web/opendc-web-ui/src/pages/_document.js | 13 -- .../src/pages/projects/[project]/index.js | 6 +- .../projects/[project]/portfolios/[portfolio].js | 25 +++- .../projects/[project]/topologies/[topology].js | 36 +++-- .../opendc-web-ui/src/pages/projects/index.js | 16 +-- .../src/redux/actions/topology/building.js | 8 +- .../src/redux/actions/topology/index.js | 3 +- .../src/redux/actions/topology/rack.js | 2 +- .../src/redux/actions/topology/room.js | 6 +- .../src/redux/reducers/topology/machine.js | 2 +- .../src/redux/reducers/topology/rack.js | 4 +- .../src/redux/reducers/topology/room.js | 4 +- .../src/redux/reducers/topology/tile.js | 4 +- .../src/redux/reducers/topology/topology.js | 4 +- .../opendc-web-ui/src/redux/sagas/topology.js | 9 +- opendc-web/opendc-web-ui/src/shapes.js | 146 +++++++++++++-------- .../opendc-web-ui/src/util/authorizations.js | 12 +- .../opendc-web-ui/src/util/topology-schema.js | 18 +-- .../opendc-web-ui/src/util/unit-specifications.js | 26 ++-- 64 files changed, 537 insertions(+), 552 deletions(-) delete mode 100644 opendc-web/opendc-web-ui/src/api/prefabs.js (limited to 'opendc-web') diff --git a/opendc-web/opendc-web-ui/src/api/index.js b/opendc-web/opendc-web-ui/src/api/index.js index 680d49ce..1a9877d0 100644 --- a/opendc-web/opendc-web-ui/src/api/index.js +++ b/opendc-web/opendc-web-ui/src/api/index.js @@ -47,5 +47,5 @@ export async function request(auth, path, method = 'GET', body) { throw response.message } - return json.data + return json } diff --git a/opendc-web/opendc-web-ui/src/api/portfolios.js b/opendc-web/opendc-web-ui/src/api/portfolios.js index 82ac0ced..d818876f 100644 --- a/opendc-web/opendc-web-ui/src/api/portfolios.js +++ b/opendc-web/opendc-web-ui/src/api/portfolios.js @@ -22,22 +22,18 @@ import { request } from './index' -export function fetchPortfolio(auth, portfolioId) { - return request(auth, `portfolios/${portfolioId}`) +export function fetchPortfolio(auth, projectId, number) { + return request(auth, `projects/${projectId}/portfolios/${number}`) } -export function fetchPortfoliosOfProject(auth, projectId) { +export function fetchPortfolios(auth, projectId) { return request(auth, `projects/${projectId}/portfolios`) } -export function addPortfolio(auth, portfolio) { - return request(auth, `projects/${portfolio.projectId}/portfolios`, 'POST', { portfolio }) +export function addPortfolio(auth, projectId, portfolio) { + return request(auth, `projects/${projectId}/portfolios`, 'POST', portfolio) } -export function updatePortfolio(auth, portfolioId, portfolio) { - return request(auth, `portfolios/${portfolioId}`, 'PUT', { portfolio }) -} - -export function deletePortfolio(auth, portfolioId) { - return request(auth, `portfolios/${portfolioId}`, 'DELETE') +export function deletePortfolio(auth, projectId, number) { + return request(auth, `projects/${projectId}/portfolios/${number}`, 'DELETE') } diff --git a/opendc-web/opendc-web-ui/src/api/prefabs.js b/opendc-web/opendc-web-ui/src/api/prefabs.js deleted file mode 100644 index eb9aa23c..00000000 --- a/opendc-web/opendc-web-ui/src/api/prefabs.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 { request } from './index' - -export function getPrefab(auth, prefabId) { - return request(auth, `prefabs/${prefabId}`) -} - -export function addPrefab(auth, prefab) { - return request(auth, 'prefabs/', 'POST', { prefab }) -} - -export function updatePrefab(auth, prefab) { - return request(auth, `prefabs/${prefab._id}`, 'PUT', { prefab }) -} - -export function deletePrefab(auth, prefabId) { - return request(auth, `prefabs/${prefabId}`, 'DELETE') -} diff --git a/opendc-web/opendc-web-ui/src/api/projects.js b/opendc-web/opendc-web-ui/src/api/projects.js index 4123b371..e7e095da 100644 --- a/opendc-web/opendc-web-ui/src/api/projects.js +++ b/opendc-web/opendc-web-ui/src/api/projects.js @@ -31,11 +31,7 @@ export function fetchProject(auth, projectId) { } export function addProject(auth, project) { - return request(auth, 'projects/', 'POST', { project }) -} - -export function updateProject(auth, project) { - return request(auth, `projects/${project._id}`, 'PUT', { project }) + return request(auth, 'projects/', 'POST', project) } export function deleteProject(auth, projectId) { diff --git a/opendc-web/opendc-web-ui/src/api/scenarios.js b/opendc-web/opendc-web-ui/src/api/scenarios.js index 88516caa..7eeb8f28 100644 --- a/opendc-web/opendc-web-ui/src/api/scenarios.js +++ b/opendc-web/opendc-web-ui/src/api/scenarios.js @@ -22,22 +22,18 @@ import { request } from './index' -export function fetchScenario(auth, scenarioId) { - return request(auth, `scenarios/${scenarioId}`) +export function fetchScenario(auth, projectId, scenarioId) { + return request(auth, `projects/${projectId}/scenarios/${scenarioId}`) } -export function fetchScenariosOfPortfolio(auth, portfolioId) { - return request(auth, `portfolios/${portfolioId}/scenarios`) +export function fetchScenariosOfPortfolio(auth, projectId, portfolioId) { + return request(auth, `projects/${projectId}/portfolios/${portfolioId}/scenarios`) } -export function addScenario(auth, scenario) { - return request(auth, `portfolios/${scenario.portfolioId}/scenarios`, 'POST', { scenario }) +export function addScenario(auth, projectId, portfolioId, scenario) { + return request(auth, `projects/${projectId}/portfolios/${portfolioId}/scenarios`, 'POST', scenario) } -export function updateScenario(auth, scenarioId, scenario) { - return request(auth, `scenarios/${scenarioId}`, 'PUT', { scenario }) -} - -export function deleteScenario(auth, scenarioId) { - return request(auth, `scenarios/${scenarioId}`, 'DELETE') +export function deleteScenario(auth, projectId, scenarioId) { + return request(auth, `projects/${projectId}/scenarios/${scenarioId}`, 'DELETE') } diff --git a/opendc-web/opendc-web-ui/src/api/topologies.js b/opendc-web/opendc-web-ui/src/api/topologies.js index bd4e3bc4..0509c6d0 100644 --- a/opendc-web/opendc-web-ui/src/api/topologies.js +++ b/opendc-web/opendc-web-ui/src/api/topologies.js @@ -22,24 +22,23 @@ import { request } from './index' -export function fetchTopology(auth, topologyId) { - return request(auth, `topologies/${topologyId}`) +export function fetchTopology(auth, projectId, number) { + return request(auth, `projects/${projectId}/topologies/${number}`) } -export function fetchTopologiesOfProject(auth, projectId) { +export function fetchTopologies(auth, projectId) { return request(auth, `projects/${projectId}/topologies`) } -export function addTopology(auth, topology) { - return request(auth, `projects/${topology.projectId}/topologies`, 'POST', { topology }) +export function addTopology(auth, projectId, topology) { + return request(auth, `projects/${projectId}/topologies`, 'POST', topology) } export function updateTopology(auth, topology) { - // eslint-disable-next-line no-unused-vars - const { _id, ...data } = topology - return request(auth, `topologies/${topology._id}`, 'PUT', { topology: data }) + const { project, number, rooms } = topology + return request(auth, `projects/${project.id}/topologies/${number}`, 'PUT', { rooms }) } -export function deleteTopology(auth, topologyId) { - return request(auth, `topologies/${topologyId}`, 'DELETE') +export function deleteTopology(auth, projectId, number) { + return request(auth, `projects/${projectId}/topologies/${number}`, 'DELETE') } diff --git a/opendc-web/opendc-web-ui/src/components/AppNavigation.js b/opendc-web/opendc-web-ui/src/components/AppNavigation.js index 178c3ec0..77c683a2 100644 --- a/opendc-web/opendc-web-ui/src/components/AppNavigation.js +++ b/opendc-web/opendc-web-ui/src/components/AppNavigation.js @@ -23,15 +23,9 @@ import { Nav, NavItem, NavList } from '@patternfly/react-core' import { useRouter } from 'next/router' import NavItemLink from './util/NavItemLink' -import { useProject } from '../data/project' export function AppNavigation() { - const { pathname, query } = useRouter() - const { project: projectId } = query - const { data: project } = useProject(projectId) - - const nextTopologyId = project?.topologyIds?.[0] - const nextPortfolioId = project?.portfolioIds?.[0] + const { pathname } = useRouter() return ( ) diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js index 3712cfa0..a99b60c0 100644 --- a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js +++ b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js @@ -22,13 +22,11 @@ import PropTypes from 'prop-types' import { ContextSelector as PFContextSelector, ContextSelectorItem } from '@patternfly/react-core' -import { useMemo, useState, useReducer } from 'react' +import { useMemo, useState } from 'react' import { contextSelector } from './ContextSelector.module.scss' -function ContextSelector({ activeItem, items, onSelect, label }) { - const [isOpen, toggle] = useReducer((isOpen) => !isOpen, false) +function ContextSelector({ activeItem, items, onSelect, onToggle, isOpen, label }) { const [searchValue, setSearchValue] = useState('') - const filteredItems = useMemo( () => items.filter(({ name }) => name.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1) || items, [items, searchValue] @@ -36,23 +34,22 @@ function ContextSelector({ activeItem, items, onSelect, label }) { return ( setSearchValue(value)} searchInputValue={searchValue} isOpen={isOpen} - onToggle={toggle} + onToggle={(_, isOpen) => onToggle(isOpen)} onSelect={(event) => { - const targetId = event.target.value - const target = items.find((item) => item._id === targetId) + const targetId = +event.target.value + const target = items.find((item) => item.id === targetId) - toggle() onSelect(target) + onToggle(!isOpen) }} > {filteredItems.map((item) => ( - + {item.name} ))} @@ -61,7 +58,7 @@ function ContextSelector({ activeItem, items, onSelect, label }) { } const Item = PropTypes.shape({ - _id: PropTypes.string.isRequired, + id: PropTypes.any.isRequired, name: PropTypes.string.isRequired, }) @@ -69,6 +66,8 @@ ContextSelector.propTypes = { activeItem: Item, items: PropTypes.arrayOf(Item).isRequired, onSelect: PropTypes.func.isRequired, + onToggle: PropTypes.func.isRequired, + isOpen: PropTypes.bool, label: PropTypes.string, } diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.scss b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.scss index fefba41f..0aa63ee6 100644 --- a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.scss +++ b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.scss @@ -21,7 +21,6 @@ */ .contextSelector { - width: auto; margin-right: 20px; --pf-c-context-selector__toggle--PaddingTop: var(--pf-global--spacer--sm); diff --git a/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js b/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js index 694681ac..c4f2d50e 100644 --- a/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js +++ b/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js @@ -21,27 +21,31 @@ */ import { useRouter } from 'next/router' -import { useMemo } from 'react' -import { useProjectPortfolios } from '../../data/project' +import { useState } from 'react' +import { usePortfolios } from '../../data/project' +import { Portfolio } from '../../shapes' import ContextSelector from './ContextSelector' -function PortfolioSelector() { +function PortfolioSelector({ activePortfolio }) { const router = useRouter() - const { project, portfolio: activePortfolioId } = router.query - const { data: portfolios = [] } = useProjectPortfolios(project) - const activePortfolio = useMemo(() => portfolios.find((portfolio) => portfolio._id === activePortfolioId), [ - activePortfolioId, - portfolios, - ]) + + const [isOpen, setOpen] = useState(false) + const { data: portfolios = [] } = usePortfolios(activePortfolio?.project?.id, { enabled: isOpen }) return ( router.push(`/projects/${portfolio.projectId}/portfolios/${portfolio._id}`)} + onSelect={(portfolio) => router.push(`/projects/${portfolio.project.id}/portfolios/${portfolio.number}`)} + onToggle={setOpen} + isOpen={isOpen} /> ) } +PortfolioSelector.propTypes = { + activePortfolio: Portfolio, +} + export default PortfolioSelector diff --git a/opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js b/opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js index 753632ab..7721e04c 100644 --- a/opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js +++ b/opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js @@ -20,29 +20,32 @@ * SOFTWARE. */ -import PropTypes from 'prop-types' import { useRouter } from 'next/router' -import { useMemo } from 'react' +import { useState } from 'react' import { useProjects } from '../../data/project' +import { Project } from '../../shapes' import ContextSelector from './ContextSelector' -function ProjectSelector({ projectId }) { +function ProjectSelector({ activeProject }) { const router = useRouter() - const { data: projects = [] } = useProjects() - const activeProject = useMemo(() => projects.find((project) => project._id === projectId), [projectId, projects]) + + const [isOpen, setOpen] = useState(false) + const { data: projects = [] } = useProjects({ enabled: isOpen }) return ( router.push(`/projects/${project._id}`)} + onSelect={(project) => router.push(`/projects/${project.id}`)} + onToggle={setOpen} + isOpen={isOpen} /> ) } ProjectSelector.propTypes = { - projectId: PropTypes.string, + activeProject: Project, } export default ProjectSelector diff --git a/opendc-web/opendc-web-ui/src/components/context/TopologySelector.js b/opendc-web/opendc-web-ui/src/components/context/TopologySelector.js index d5e51c6c..9cae4cbf 100644 --- a/opendc-web/opendc-web-ui/src/components/context/TopologySelector.js +++ b/opendc-web/opendc-web-ui/src/components/context/TopologySelector.js @@ -20,33 +20,32 @@ * SOFTWARE. */ -import PropTypes from 'prop-types' import { useRouter } from 'next/router' -import { useMemo } from 'react' -import { useProjectTopologies } from '../../data/topology' +import { useState } from 'react' +import { useTopologies } from '../../data/topology' +import { Topology } from '../../shapes' import ContextSelector from './ContextSelector' -function TopologySelector({ projectId, topologyId }) { +function TopologySelector({ activeTopology }) { const router = useRouter() - const { data: topologies = [] } = useProjectTopologies(projectId) - const activeTopology = useMemo(() => topologies.find((topology) => topology._id === topologyId), [ - topologyId, - topologies, - ]) + + const [isOpen, setOpen] = useState(false) + const { data: topologies = [] } = useTopologies(activeTopology?.project?.id, { enabled: isOpen }) return ( router.push(`/projects/${topology.projectId}/topologies/${topology._id}`)} + onSelect={(topology) => router.push(`/projects/${topology.project.id}/topologies/${topology.number}`)} + onToggle={setOpen} + isOpen={isOpen} /> ) } TopologySelector.propTypes = { - projectId: PropTypes.string, - topologyId: PropTypes.string, + activeTopology: Topology, } export default TopologySelector diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js b/opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js index 856282a7..fd9a72d2 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js @@ -24,21 +24,15 @@ import PropTypes from 'prop-types' import { PlusIcon } from '@patternfly/react-icons' import { Button } from '@patternfly/react-core' import { useState } from 'react' -import { useMutation } from 'react-query' +import { useNewScenario } from '../../data/project' import NewScenarioModal from './NewScenarioModal' -function NewScenario({ portfolioId }) { +function NewScenario({ projectId, portfolioId }) { const [isVisible, setVisible] = useState(false) - const { mutate: addScenario } = useMutation('addScenario') + const { mutate: addScenario } = useNewScenario() - const onSubmit = (name, portfolioId, trace, topology, operational) => { - addScenario({ - portfolioId, - name, - trace, - topology, - operational, - }) + const onSubmit = (projectId, portfolioNumber, data) => { + addScenario({ projectId, portfolioNumber, data }) setVisible(false) } @@ -48,6 +42,7 @@ function NewScenario({ portfolioId }) { New Scenario { - const { data: portfolio } = usePortfolio(portfolioId) - const { data: topologies = [] } = useProjectTopologies(portfolio?.projectId) - const { data: traces = [] } = useTraces() - const { data: schedulers = [] } = useSchedulers() +function NewScenarioModal({ projectId, portfolioId, isOpen, onSubmit: onSubmitUpstream, onCancel: onCancelUpstream }) { + const { data: portfolio } = usePortfolio(projectId, portfolioId) + const { data: topologies = [] } = useTopologies(projectId, { enabled: isOpen }) + const { data: traces = [] } = useTraces({ enabled: isOpen }) + const { data: schedulers = [] } = useSchedulers({ enabled: isOpen }) // eslint-disable-next-line no-unused-vars const [isSubmitted, setSubmitted] = useState(false) @@ -51,22 +51,19 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC const name = nameInput.current.value - onSubmitUpstream( + onSubmitUpstream(portfolio.project.id, portfolio.number, { name, - portfolio._id, - { - traceId: trace || traces[0]._id, - loadSamplingFraction: traceLoad / 100, + workload: { + trace: trace || traces[0].id, + samplingFraction: traceLoad / 100, }, - { - topologyId: topology || topologies[0]._id, + topology: topology || topologies[0].number, + phenomena: { + failures: failuresEnabled, + interference: opPhenEnabled, }, - { - failuresEnabled, - performanceInterferenceEnabled: opPhenEnabled, - schedulerName: scheduler || schedulers[0].name, - } - ) + schedulerName: scheduler || schedulers[0], + }) resetState() return true @@ -84,8 +81,8 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC id="name" name="name" type="text" - isDisabled={portfolio?.scenarioIds?.length === 0} - defaultValue={portfolio?.scenarioIds?.length === 0 ? 'Base scenario' : ''} + isDisabled={portfolio?.scenarios?.length === 0} + defaultValue={portfolio?.scenarios?.length === 0 ? 'Base scenario' : ''} ref={nameInput} /> @@ -93,7 +90,7 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC {traces.map((trace) => ( - + ))} @@ -115,7 +112,7 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC {topologies.map((topology) => ( - + ))} @@ -123,7 +120,7 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC {schedulers.map((scheduler) => ( - + ))} @@ -150,7 +147,8 @@ const NewScenarioModal = ({ portfolioId, isOpen, onSubmit: onSubmitUpstream, onC } NewScenarioModal.propTypes = { - portfolioId: PropTypes.string, + projectId: PropTypes.number, + portfolioId: PropTypes.number, isOpen: PropTypes.bool.isRequired, onSubmit: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js index 580b0a29..e561b655 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js @@ -43,8 +43,8 @@ import { METRIC_NAMES } from '../../util/available-metrics' import NewScenario from './NewScenario' import ScenarioTable from './ScenarioTable' -function PortfolioOverview({ portfolioId }) { - const { data: portfolio } = usePortfolio(portfolioId) +function PortfolioOverview({ projectId, portfolioId }) { + const { status, data: portfolio } = usePortfolio(projectId, portfolioId) return ( @@ -62,16 +62,16 @@ function PortfolioOverview({ portfolioId }) { Scenarios - {portfolio?.scenarioIds.length ?? } + {portfolio?.scenarios?.length ?? } Metrics - {portfolio?.targets?.enabledMetrics ? ( - portfolio.targets.enabledMetrics.length > 0 ? ( + {portfolio ? ( + portfolio.targets.metrics.length > 0 ? ( - {portfolio.targets.enabledMetrics.map((metric) => ( + {portfolio.targets.metrics.map((metric) => ( {METRIC_NAMES[metric]} @@ -88,9 +88,7 @@ function PortfolioOverview({ portfolioId }) { Repeats per Scenario - {portfolio?.targets?.repeatsPerScenario ?? ( - - )} + {portfolio?.targets?.repeats ?? } @@ -101,12 +99,12 @@ function PortfolioOverview({ portfolioId }) { - + Scenarios - + @@ -115,7 +113,8 @@ function PortfolioOverview({ portfolioId }) { } PortfolioOverview.propTypes = { - portfolioId: PropTypes.string, + projectId: PropTypes.number, + portfolioId: PropTypes.number, } export default PortfolioOverview diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js index 00023d9e..f63f0c7f 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js @@ -42,12 +42,14 @@ import { Title, } from '@patternfly/react-core' import { ErrorCircleOIcon, CubesIcon } from '@patternfly/react-icons' -import { usePortfolioScenarios } from '../../data/project' +import { usePortfolio } from '../../data/project' import PortfolioResultInfo from './PortfolioResultInfo' import NewScenario from './NewScenario' -const PortfolioResults = ({ portfolioId }) => { - const { status, data: scenarios = [] } = usePortfolioScenarios(portfolioId) +const PortfolioResults = ({ projectId, portfolioId }) => { + const { status, data: scenarios = [] } = usePortfolio(projectId, portfolioId, { + select: (portfolio) => portfolio.scenarios, + }) if (status === 'loading') { return ( @@ -86,7 +88,7 @@ const PortfolioResults = ({ portfolioId }) => { No results are currently available for this portfolio. Run a scenario to obtain simulation results. - + ) @@ -96,11 +98,11 @@ const PortfolioResults = ({ portfolioId }) => { AVAILABLE_METRICS.forEach((metric) => { dataPerMetric[metric] = scenarios - .filter((scenario) => scenario.results) + .filter((scenario) => scenario.job?.results) .map((scenario) => ({ name: scenario.name, - value: mean(scenario.results[metric]), - errorX: std(scenario.results[metric]), + value: mean(scenario.job.results[metric]), + errorX: std(scenario.job.results[metric]), })) }) @@ -150,7 +152,8 @@ const PortfolioResults = ({ portfolioId }) => { } PortfolioResults.propTypes = { - portfolioId: PropTypes.string, + projectId: PropTypes.number, + portfolioId: PropTypes.number, } export default PortfolioResults diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js index 66691580..99d83f64 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js @@ -20,13 +20,13 @@ * SOFTWARE. */ -import PropTypes from 'prop-types' import { ClockIcon, CheckCircleIcon, ErrorCircleOIcon } from '@patternfly/react-icons' +import { JobState } from '../../shapes' function ScenarioState({ state }) { switch (state) { + case 'PENDING': case 'CLAIMED': - case 'QUEUED': return ( Queued @@ -56,7 +56,7 @@ function ScenarioState({ state }) { } ScenarioState.propTypes = { - state: PropTypes.oneOf(['QUEUED', 'CLAIMED', 'RUNNING', 'FINISHED', 'FAILED']), + state: JobState.isRequired, } export default ScenarioState diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js index 9966e3ba..68647957 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js @@ -20,44 +20,38 @@ * SOFTWARE. */ -import PropTypes from 'prop-types' import Link from 'next/link' import { Table, TableBody, TableHeader } from '@patternfly/react-table' import React from 'react' +import { Portfolio, Status } from '../../shapes' import TableEmptyState from '../util/TableEmptyState' import ScenarioState from './ScenarioState' -import { usePortfolio, usePortfolioScenarios } from '../../data/project' -import { useProjectTopologies } from '../../data/topology' -import { useMutation } from 'react-query' +import { useDeleteScenario } from '../../data/project' -const ScenarioTable = ({ portfolioId }) => { - const { data: portfolio } = usePortfolio(portfolioId) - const { status, data: scenarios = [] } = usePortfolioScenarios(portfolioId) - const { data: topologies } = useProjectTopologies(portfolio?.projectId, { - select: (topologies) => new Map(topologies.map((topology) => [topology._id, topology])), - }) - - const { mutate: deleteScenario } = useMutation('deleteScenario') +function ScenarioTable({ portfolio, status }) { + const { mutate: deleteScenario } = useDeleteScenario() + const projectId = portfolio?.project?.id + const scenarios = portfolio?.scenarios ?? [] const columns = ['Name', 'Topology', 'Trace', 'State'] const rows = scenarios.length > 0 ? scenarios.map((scenario) => { - const topology = topologies?.get(scenario.topology.topologyId) + const topology = scenario.topology return [ scenario.name, { title: topology ? ( - + {topology.name} ) : ( 'Unknown Topology' ), }, - scenario.trace.traceId, - { title: }, + `${scenario.workload.trace.name} (${scenario.workload.samplingFraction * 100}%)`, + { title: }, ] }) : [ @@ -82,7 +76,7 @@ const ScenarioTable = ({ portfolioId }) => { const actionResolver = (_, { rowIndex }) => [ { title: 'Delete Scenario', - onClick: (_, rowId) => deleteScenario(scenarios[rowId]._id), + onClick: (_, rowId) => deleteScenario({ projectId: projectId, number: scenarios[rowId].number }), isDisabled: rowIndex === 0, }, ] @@ -102,7 +96,8 @@ const ScenarioTable = ({ portfolioId }) => { } ScenarioTable.propTypes = { - portfolioId: PropTypes.string, + portfolio: Portfolio, + status: Status.isRequired, } export default ScenarioTable diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js b/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js index 87ea059d..aebcc3c9 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js +++ b/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js @@ -24,12 +24,12 @@ import PropTypes from 'prop-types' import { PlusIcon } from '@patternfly/react-icons' import { Button } from '@patternfly/react-core' import { useState } from 'react' -import { useMutation } from 'react-query' +import { useNewPortfolio } from '../../data/project' import NewPortfolioModal from './NewPortfolioModal' function NewPortfolio({ projectId }) { const [isVisible, setVisible] = useState(false) - const { mutate: addPortfolio } = useMutation('addPortfolio') + const { mutate: addPortfolio } = useNewPortfolio() const onSubmit = (name, targets) => { addPortfolio({ projectId, name, targets }) @@ -47,7 +47,7 @@ function NewPortfolio({ projectId }) { } NewPortfolio.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, } export default NewPortfolio diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js b/opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js index 4276d7d4..ba4bc819 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js +++ b/opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js @@ -67,7 +67,7 @@ const NewPortfolioModal = ({ isOpen, onSubmit: onSubmitUpstream, onCancel: onUps setErrors({ name: true }) return false } else { - onSubmitUpstream(name, { enabledMetrics: selectedMetrics, repeatsPerScenario: repeats }) + onSubmitUpstream(name, { metrics: selectedMetrics, repeats }) } clearState() diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewProject.js b/opendc-web/opendc-web-ui/src/components/projects/NewProject.js index 984264dc..bfa7c01a 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/NewProject.js +++ b/opendc-web/opendc-web-ui/src/components/projects/NewProject.js @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { Button } from '@patternfly/react-core' -import { useMutation } from 'react-query' import { PlusIcon } from '@patternfly/react-icons' +import { useNewProject } from '../../data/project' import { buttonContainer } from './NewProject.module.scss' import TextInputModal from '../util/modals/TextInputModal' @@ -10,7 +10,7 @@ import TextInputModal from '../util/modals/TextInputModal' */ const NewProject = () => { const [isVisible, setVisible] = useState(false) - const { mutate: addProject } = useMutation('addProject') + const { mutate: addProject } = useNewProject() const onSubmit = (name) => { if (name) { diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js b/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js index 77c57d26..4c569c56 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js +++ b/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js @@ -21,25 +21,17 @@ */ import PropTypes from 'prop-types' -import produce from 'immer' import { PlusIcon } from '@patternfly/react-icons' import { Button } from '@patternfly/react-core' import { useState } from 'react' -import { useMutation } from "react-query"; -import { useProjectTopologies } from "../../data/topology"; +import { useNewTopology } from '../../data/topology' import NewTopologyModal from './NewTopologyModal' function NewTopology({ projectId }) { const [isVisible, setVisible] = useState(false) - const { data: topologies = [] } = useProjectTopologies(projectId) - const { mutate: addTopology } = useMutation('addTopology') + const { mutate: addTopology } = useNewTopology() - const onSubmit = (name, duplicateId) => { - const candidate = topologies.find((topology) => topology._id === duplicateId) || { projectId, rooms: [] } - const topology = produce(candidate, (draft) => { - delete draft._id - draft.name = name - }) + const onSubmit = (topology) => { addTopology(topology) setVisible(false) } @@ -59,7 +51,7 @@ function NewTopology({ projectId }) { } NewTopology.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, } export default NewTopology diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js b/opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js index a495f73e..be4256e3 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js +++ b/opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js @@ -20,10 +20,11 @@ * SOFTWARE. */ +import produce from 'immer' import PropTypes from 'prop-types' import React, { useRef, useState } from 'react' import { Form, FormGroup, FormSelect, FormSelectOption, TextInput } from '@patternfly/react-core' -import { useProjectTopologies } from '../../data/topology' +import { useTopologies } from '../../data/topology' import Modal from '../util/modals/Modal' const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCancel: onCancelUpstream }) => { @@ -32,10 +33,12 @@ const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCan const [originTopology, setOriginTopology] = useState(-1) const [errors, setErrors] = useState({}) - const { data: topologies = [] } = useProjectTopologies(projectId) + const { data: topologies = [] } = useTopologies(projectId, { enabled: isOpen }) const clearState = () => { - nameInput.current.value = '' + if (nameInput.current) { + nameInput.current.value = '' + } setSubmitted(false) setOriginTopology(-1) setErrors({}) @@ -53,10 +56,13 @@ const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCan if (!name) { setErrors({ name: true }) return false - } else if (originTopology === -1) { - onSubmitUpstream(name) } else { - onSubmitUpstream(name, originTopology) + const candidate = topologies.find((topology) => topology.id === originTopology) || { projectId, rooms: [] } + const topology = produce(candidate, (draft) => { + delete draft.id + draft.name = name + }) + onSubmitUpstream(topology) } clearState() @@ -84,7 +90,7 @@ const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCan {topologies.map((topology) => ( - + ))} @@ -94,7 +100,7 @@ const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCan } NewTopologyModal.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, isOpen: PropTypes.bool.isRequired, onSubmit: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, diff --git a/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js b/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js index 45e399ed..aa679843 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js +++ b/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js @@ -25,12 +25,11 @@ import Link from 'next/link' import { Table, TableBody, TableHeader } from '@patternfly/react-table' import React from 'react' import TableEmptyState from '../util/TableEmptyState' -import { useProjectPortfolios } from '../../data/project' -import { useMutation } from 'react-query' +import { usePortfolios, useDeletePortfolio } from '../../data/project' const PortfolioTable = ({ projectId }) => { - const { status, data: portfolios = [] } = useProjectPortfolios(projectId) - const { mutate: deletePortfolio } = useMutation('deletePortfolio') + const { status, data: portfolios = [] } = usePortfolios(projectId) + const { mutate: deletePortfolio } = useDeletePortfolio() const columns = ['Name', 'Scenarios', 'Metrics', 'Repeats'] const rows = @@ -38,20 +37,12 @@ const PortfolioTable = ({ projectId }) => { ? portfolios.map((portfolio) => [ { title: ( - - {portfolio.name} - + {portfolio.name} ), }, - - portfolio.scenarioIds.length === 1 ? '1 scenario' : `${portfolio.scenarioIds.length} scenarios`, - - portfolio.targets.enabledMetrics.length === 1 - ? '1 metric' - : `${portfolio.targets.enabledMetrics.length} metrics`, - portfolio.targets.repeatsPerScenario === 1 - ? '1 repeat' - : `${portfolio.targets.repeatsPerScenario} repeats`, + portfolio.scenarios.length === 1 ? '1 scenario' : `${portfolio.scenarios.length} scenarios`, + portfolio.targets.metrics.length === 1 ? '1 metric' : `${portfolio.targets.metrics.length} metrics`, + portfolio.targets.repeats === 1 ? '1 repeat' : `${portfolio.targets.repeats} repeats`, ]) : [ { @@ -77,7 +68,7 @@ const PortfolioTable = ({ projectId }) => { ? [ { title: 'Delete Portfolio', - onClick: (_, rowId) => deletePortfolio(portfolios[rowId]._id), + onClick: (_, rowId) => deletePortfolio({ projectId, number: portfolios[rowId].number }), }, ] : [] @@ -91,7 +82,7 @@ const PortfolioTable = ({ projectId }) => { } PortfolioTable.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, } export default PortfolioTable diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js index 65b8f5a0..3e1656f6 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js @@ -92,7 +92,7 @@ function ProjectOverview({ projectId }) { } ProjectOverview.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, } export default ProjectOverview diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectTable.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectTable.js index a7290259..6921578c 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectTable.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectTable.js @@ -5,26 +5,23 @@ import { Project, Status } from '../../shapes' import { Table, TableBody, TableHeader } from '@patternfly/react-table' import { parseAndFormatDateTime } from '../../util/date-time' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' -import { useAuth } from '../../auth' import TableEmptyState from '../util/TableEmptyState' const ProjectTable = ({ status, projects, onDelete, isFiltering }) => { - const { user } = useAuth() const columns = ['Project name', 'Last edited', 'Access Rights'] const rows = projects.length > 0 ? projects.map((project) => { - const { level } = project.authorizations.find((auth) => auth.userId === user.sub) - const Icon = AUTH_ICON_MAP[level] + const Icon = AUTH_ICON_MAP[project.role] return [ { - title: {project.name}, + title: {project.name}, }, - parseAndFormatDateTime(project.datetimeLastEdited), + parseAndFormatDateTime(project.updatedAt), { title: ( <> - {AUTH_DESCRIPTION_MAP[level]} + {AUTH_DESCRIPTION_MAP[project.role]} ), }, diff --git a/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js b/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js index 80099ece..ced5304a 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js +++ b/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js @@ -26,26 +26,21 @@ import { Table, TableBody, TableHeader } from '@patternfly/react-table' import React from 'react' import TableEmptyState from '../util/TableEmptyState' import { parseAndFormatDateTime } from '../../util/date-time' -import { useMutation } from 'react-query' -import { useProjectTopologies } from '../../data/topology' +import { useTopologies, useDeleteTopology } from '../../data/topology' const TopologyTable = ({ projectId }) => { - const { status, data: topologies = [] } = useProjectTopologies(projectId) - const { mutate: deleteTopology } = useMutation('deleteTopology') + const { status, data: topologies = [] } = useTopologies(projectId) + const { mutate: deleteTopology } = useDeleteTopology() const columns = ['Name', 'Rooms', 'Last Edited'] const rows = topologies.length > 0 ? topologies.map((topology) => [ { - title: ( - - {topology.name} - - ), + title: {topology.name}, }, topology.rooms.length === 1 ? '1 room' : `${topology.rooms.length} rooms`, - parseAndFormatDateTime(topology.datetimeLastEdited), + parseAndFormatDateTime(topology.updatedAt), ]) : [ { @@ -69,7 +64,7 @@ const TopologyTable = ({ projectId }) => { const actionResolver = (_, { rowIndex }) => [ { title: 'Delete Topology', - onClick: (_, rowId) => deleteTopology(topologies[rowId]._id), + onClick: (_, rowId) => deleteTopology({ projectId, number: topologies[rowId].number }), isDisabled: rowIndex === 0, }, ] @@ -89,7 +84,7 @@ const TopologyTable = ({ projectId }) => { } TopologyTable.propTypes = { - projectId: PropTypes.string, + projectId: PropTypes.number, } export default TopologyTable diff --git a/opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js b/opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js index 9bf369e9..49e5f095 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js @@ -7,11 +7,11 @@ import { Table, TableBody, TableHeader } from '@patternfly/react-table' import { deleteRoom } from '../../redux/actions/topology/room' import TableEmptyState from '../util/TableEmptyState' -function RoomTable({ topologyId, onSelect }) { +function RoomTable({ projectId, topologyId, onSelect }) { const dispatch = useDispatch() - const { status, data: topology } = useTopology(topologyId) + const { status, data: topology } = useTopology(projectId, topologyId) - const onDelete = (room) => dispatch(deleteRoom(room._id)) + const onDelete = (room) => dispatch(deleteRoom(room.id)) const columns = ['Name', 'Tiles', 'Racks'] const rows = @@ -62,7 +62,8 @@ function RoomTable({ topologyId, onSelect }) { } RoomTable.propTypes = { - topologyId: PropTypes.string, + projectId: PropTypes.number, + topologyId: PropTypes.number, onSelect: PropTypes.func, } diff --git a/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js b/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js index 213a4868..f8ee4990 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js @@ -38,8 +38,8 @@ import { useTopology } from '../../data/topology' import { parseAndFormatDateTime } from '../../util/date-time' import RoomTable from './RoomTable' -function TopologyOverview({ topologyId, onSelect }) { - const { data: topology } = useTopology(topologyId) +function TopologyOverview({ projectId, topologyNumber, onSelect }) { + const { data: topology } = useTopology(projectId, topologyNumber) return ( @@ -57,7 +57,7 @@ function TopologyOverview({ topologyId, onSelect }) { Last edited {topology ? ( - parseAndFormatDateTime(topology.datetimeLastEdited) + parseAndFormatDateTime(topology.updatedAt) ) : ( )} @@ -71,7 +71,11 @@ function TopologyOverview({ topologyId, onSelect }) { Rooms - onSelect('room', room)} /> + onSelect('room', room)} + /> @@ -80,7 +84,8 @@ function TopologyOverview({ topologyId, onSelect }) { } TopologyOverview.propTypes = { - topologyId: PropTypes.string, + projectId: PropTypes.number, + topologyNumber: PropTypes.number, onSelect: PropTypes.func, } diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js index 411a5ca7..21be3c79 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js @@ -33,7 +33,7 @@ function TileContainer({ tileId, ...props }) { const dispatch = useDispatch() const onClick = (tile) => { if (tile.rack) { - dispatch(goFromRoomToRack(tile._id)) + dispatch(goFromRoomToRack(tile.id)) } } return diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js index 7d304b6b..fdae53f2 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js @@ -21,6 +21,7 @@ function ImageComponent({ src, x, y, width, height, opacity }) { } }, [src]) + // eslint-disable-next-line jsx-a11y/alt-text return } diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js index 46030135..dad2d62d 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js @@ -11,8 +11,8 @@ function RackGroup({ tile }) { - - + + ) diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js index a42e7bb7..3f8b3089 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js @@ -7,7 +7,7 @@ import TileContainer from '../TileContainer' import WallContainer from '../WallContainer' function RoomGroup({ room, interactionLevel, currentRoomInConstruction, onClick }) { - if (currentRoomInConstruction === room._id) { + if (currentRoomInConstruction === room.id) { return ( {room.tiles.map((tileId) => ( @@ -22,7 +22,7 @@ function RoomGroup({ room, interactionLevel, currentRoomInConstruction, onClick {(() => { if ( (interactionLevel.mode === 'RACK' || interactionLevel.mode === 'MACHINE') && - interactionLevel.roomId === room._id + interactionLevel.roomId === room.id ) { return [ room.tiles @@ -37,7 +37,7 @@ function RoomGroup({ room, interactionLevel, currentRoomInConstruction, onClick return room.tiles.map((tileId) => ) } })()} - + ) } diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js index 5e351691..727f4e25 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js @@ -40,8 +40,8 @@ function RoomHoverLayer() { .map((id) => ({ ...state.topology.rooms[id] })) .filter( (room) => - state.topology.root.rooms.indexOf(room._id) !== -1 && - room._id !== state.construction.currentRoomInConstruction + state.topology.root.rooms.indexOf(room.id) !== -1 && + room.id !== state.construction.currentRoomInConstruction ) ;[...oldRooms, newRoom].forEach((room) => { diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js index 9268f615..6f89e10b 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js @@ -17,7 +17,7 @@ function MachineSidebar({ tileId, position }) { const rack = topology.racks[topology.tiles[tileId].rack] return topology.machines[rack.machines[position - 1]] }) - const machineId = machine._id + const machineId = machine.id return (
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js index 88591208..4507b409 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js @@ -22,7 +22,7 @@ function UnitAddComponent({ units, onAdd }) { selections={selected} > {units.map((unit) => ( - + {unit.name} ))} diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js index 6dcc414f..25e750c4 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js @@ -33,7 +33,7 @@ function UnitListContainer({ machineId, unitType }) { return machine[unitType].map((id) => state.topology[unitType][id]) }) - const onDelete = (unit) => dispatch(deleteUnit(machineId, unitType, unit._id)) + const onDelete = (unit) => dispatch(deleteUnit(machineId, unitType, unit.id)) return } diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js index e944c2e8..6a0c3ff3 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js @@ -22,14 +22,11 @@ import PropTypes from 'prop-types' import React from 'react' -import { useDispatch } from 'react-redux' import { Button } from '@patternfly/react-core' import { SaveIcon } from '@patternfly/react-icons' -import { addPrefab } from '../../../../api/prefabs' -function AddPrefab({ tileId }) { - const dispatch = useDispatch() - const onClick = () => dispatch(addPrefab('name', tileId)) +function AddPrefab() { + const onClick = () => {} // TODO return (