summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-ui/src
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-ui/src')
-rw-r--r--opendc-web/opendc-web-ui/src/api/index.js56
-rw-r--r--opendc-web/opendc-web-ui/src/api/portfolios.js39
-rw-r--r--opendc-web/opendc-web-ui/src/api/projects.js39
-rw-r--r--opendc-web/opendc-web-ui/src/api/scenarios.js39
-rw-r--r--opendc-web/opendc-web-ui/src/api/schedulers.js27
-rw-r--r--opendc-web/opendc-web-ui/src/api/topologies.js44
-rw-r--r--opendc-web/opendc-web-ui/src/api/traces.js27
-rw-r--r--opendc-web/opendc-web-ui/src/api/users.js32
-rw-r--r--opendc-web/opendc-web-ui/src/auth.js97
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppHeader.js69
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppHeader.module.css42
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppHeaderTools.js93
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppHeaderUser.js99
-rw-r--r--opendc-web/opendc-web-ui/src/components/AppPage.js44
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.js34
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.module.css28
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/ContextSelector.js79
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.css44
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js52
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js55
-rw-r--r--opendc-web/opendc-web-ui/src/components/context/TopologySelector.js52
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js60
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/NewScenarioModal.js157
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js120
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResultInfo.js40
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js180
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js62
-rw-r--r--opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js103
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js26
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.css7
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js53
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js161
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/NewTopology.js57
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js115
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js99
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js137
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js98
-rw-r--r--opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js115
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js74
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/TopologyMap.js69
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js92
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/GrayContainer.js34
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/MapConstants.js25
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.js83
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.module.css29
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RackContainer.js37
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js36
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js42
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js54
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js50
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/TopologyContainer.js34
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js39
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.js42
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.module.css55
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.js18
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.module.css10
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js33
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.module.css27
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/Backdrop.js10
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/GrayLayer.js24
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/HoverTile.js30
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js37
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/RackFillBar.js68
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/RoomTile.js24
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/TileObject.js27
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/TilePlusIcon.js44
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/elements/WallSegment.js32
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/GridGroup.js36
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js25
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js52
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/TileGroup.js36
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/TopologyGroup.js44
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/WallGroup.js22
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/layers/HoverLayerComponent.js55
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/layers/MapLayer.js41
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/layers/ObjectHoverLayer.js51
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js59
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/NameComponent.js69
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.js83
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.module.css35
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/BuildingSidebar.js8
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionComponent.js46
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionContainer.js46
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/DeleteMachine.js59
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js55
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js42
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddContainer.js44
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListComponent.js113
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js47
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitTabsComponent.js36
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitType.js25
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js41
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/DeleteRackContainer.js60
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineComponent.js40
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListComponent.js80
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListContainer.js56
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackNameContainer.js22
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.js58
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.module.css14
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/DeleteRoomContainer.js59
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/EditRoomContainer.js61
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionComponent.js35
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionContainer.js46
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomName.js44
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomSidebar.js43
-rw-r--r--opendc-web/opendc-web-ui/src/components/util/TableEmptyState.js103
-rw-r--r--opendc-web/opendc-web-ui/src/components/util/modals/ConfirmationModal.js27
-rw-r--r--opendc-web/opendc-web-ui/src/components/util/modals/Modal.js38
-rw-r--r--opendc-web/opendc-web-ui/src/components/util/modals/TextInputModal.js70
-rw-r--r--opendc-web/opendc-web-ui/src/config.js41
-rw-r--r--opendc-web/opendc-web-ui/src/data/experiments.js47
-rw-r--r--opendc-web/opendc-web-ui/src/data/project.js166
-rw-r--r--opendc-web/opendc-web-ui/src/data/query.js59
-rw-r--r--opendc-web/opendc-web-ui/src/data/topology.js88
-rw-r--r--opendc-web/opendc-web-ui/src/data/user.js40
-rw-r--r--opendc-web/opendc-web-ui/src/pages/404.js38
-rw-r--r--opendc-web/opendc-web-ui/src/pages/_app.js108
-rw-r--r--opendc-web/opendc-web-ui/src/pages/_document.js76
-rw-r--r--opendc-web/opendc-web-ui/src/pages/logout.js39
-rw-r--r--opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js75
-rw-r--r--opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js121
-rw-r--r--opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js142
-rw-r--r--opendc-web/opendc-web-ui/src/pages/projects/index.js116
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/interaction-level.js57
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/topology/building.js113
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/topology/index.js40
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/topology/machine.js28
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/topology/rack.js36
-rw-r--r--opendc-web/opendc-web-ui/src/redux/actions/topology/room.js74
-rw-r--r--opendc-web/opendc-web-ui/src/redux/index.js59
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/construction-mode.js43
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/index.js12
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/interaction-level.js68
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/index.js44
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/machine.js47
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/rack.js66
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/room.js65
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/tile.js58
-rw-r--r--opendc-web/opendc-web-ui/src/redux/reducers/topology/topology.js47
-rw-r--r--opendc-web/opendc-web-ui/src/redux/sagas/index.js7
-rw-r--r--opendc-web/opendc-web-ui/src/redux/sagas/topology.js76
-rw-r--r--opendc-web/opendc-web-ui/src/shapes.js187
-rw-r--r--opendc-web/opendc-web-ui/src/style/index.css28
-rw-r--r--opendc-web/opendc-web-ui/src/util/authorizations.js21
-rw-r--r--opendc-web/opendc-web-ui/src/util/available-metrics.js101
-rw-r--r--opendc-web/opendc-web-ui/src/util/colors.js29
-rw-r--r--opendc-web/opendc-web-ui/src/util/date-time.js81
-rw-r--r--opendc-web/opendc-web-ui/src/util/date-time.test.js21
-rw-r--r--opendc-web/opendc-web-ui/src/util/effect-ref.js41
-rw-r--r--opendc-web/opendc-web-ui/src/util/tile-calculations.js255
-rw-r--r--opendc-web/opendc-web-ui/src/util/topology-schema.js47
-rw-r--r--opendc-web/opendc-web-ui/src/util/unit-specifications.js102
152 files changed, 0 insertions, 8895 deletions
diff --git a/opendc-web/opendc-web-ui/src/api/index.js b/opendc-web/opendc-web-ui/src/api/index.js
deleted file mode 100644
index 3411b96e..00000000
--- a/opendc-web/opendc-web-ui/src/api/index.js
+++ /dev/null
@@ -1,56 +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 { apiUrl } from '../config'
-
-/**
- * Send the specified request to the OpenDC API.
- *
- * @param auth The authentication context.
- * @param path Relative path for the API.
- * @param method The method to use for the request.
- * @param body The body of the request.
- */
-export async function request(auth, path, method = 'GET', body) {
- const headers = {
- 'Content-Type': 'application/json',
- }
-
- const { getAccessTokenSilently } = auth
- if (getAccessTokenSilently) {
- const token = await getAccessTokenSilently()
- headers['Authorization'] = `Bearer ${token}`
- }
-
- const response = await fetch(`${apiUrl}/${path}`, {
- method: method,
- headers: headers,
- body: body && JSON.stringify(body),
- })
- const json = await response.json()
-
- if (!response.ok) {
- throw json.message
- }
-
- return json
-}
diff --git a/opendc-web/opendc-web-ui/src/api/portfolios.js b/opendc-web/opendc-web-ui/src/api/portfolios.js
deleted file mode 100644
index d818876f..00000000
--- a/opendc-web/opendc-web-ui/src/api/portfolios.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 fetchPortfolio(auth, projectId, number) {
- return request(auth, `projects/${projectId}/portfolios/${number}`)
-}
-
-export function fetchPortfolios(auth, projectId) {
- return request(auth, `projects/${projectId}/portfolios`)
-}
-
-export function addPortfolio(auth, projectId, portfolio) {
- return request(auth, `projects/${projectId}/portfolios`, 'POST', portfolio)
-}
-
-export function deletePortfolio(auth, projectId, number) {
- return request(auth, `projects/${projectId}/portfolios/${number}`, 'DELETE')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/projects.js b/opendc-web/opendc-web-ui/src/api/projects.js
deleted file mode 100644
index e7e095da..00000000
--- a/opendc-web/opendc-web-ui/src/api/projects.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 fetchProjects(auth) {
- return request(auth, `projects/`)
-}
-
-export function fetchProject(auth, projectId) {
- return request(auth, `projects/${projectId}`)
-}
-
-export function addProject(auth, project) {
- return request(auth, 'projects/', 'POST', project)
-}
-
-export function deleteProject(auth, projectId) {
- return request(auth, `projects/${projectId}`, 'DELETE')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/scenarios.js b/opendc-web/opendc-web-ui/src/api/scenarios.js
deleted file mode 100644
index 7eeb8f28..00000000
--- a/opendc-web/opendc-web-ui/src/api/scenarios.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 fetchScenario(auth, projectId, scenarioId) {
- return request(auth, `projects/${projectId}/scenarios/${scenarioId}`)
-}
-
-export function fetchScenariosOfPortfolio(auth, projectId, portfolioId) {
- return request(auth, `projects/${projectId}/portfolios/${portfolioId}/scenarios`)
-}
-
-export function addScenario(auth, projectId, portfolioId, scenario) {
- return request(auth, `projects/${projectId}/portfolios/${portfolioId}/scenarios`, 'POST', scenario)
-}
-
-export function deleteScenario(auth, projectId, scenarioId) {
- return request(auth, `projects/${projectId}/scenarios/${scenarioId}`, 'DELETE')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/schedulers.js b/opendc-web/opendc-web-ui/src/api/schedulers.js
deleted file mode 100644
index 0b8b8153..00000000
--- a/opendc-web/opendc-web-ui/src/api/schedulers.js
+++ /dev/null
@@ -1,27 +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 fetchSchedulers(auth) {
- return request(auth, 'schedulers/')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/topologies.js b/opendc-web/opendc-web-ui/src/api/topologies.js
deleted file mode 100644
index 0509c6d0..00000000
--- a/opendc-web/opendc-web-ui/src/api/topologies.js
+++ /dev/null
@@ -1,44 +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 fetchTopology(auth, projectId, number) {
- return request(auth, `projects/${projectId}/topologies/${number}`)
-}
-
-export function fetchTopologies(auth, projectId) {
- return request(auth, `projects/${projectId}/topologies`)
-}
-
-export function addTopology(auth, projectId, topology) {
- return request(auth, `projects/${projectId}/topologies`, 'POST', topology)
-}
-
-export function updateTopology(auth, topology) {
- const { project, number, rooms } = topology
- return request(auth, `projects/${project.id}/topologies/${number}`, 'PUT', { rooms })
-}
-
-export function deleteTopology(auth, projectId, number) {
- return request(auth, `projects/${projectId}/topologies/${number}`, 'DELETE')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/traces.js b/opendc-web/opendc-web-ui/src/api/traces.js
deleted file mode 100644
index fd637ac3..00000000
--- a/opendc-web/opendc-web-ui/src/api/traces.js
+++ /dev/null
@@ -1,27 +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 fetchTraces(auth) {
- return request(auth, 'traces/')
-}
diff --git a/opendc-web/opendc-web-ui/src/api/users.js b/opendc-web/opendc-web-ui/src/api/users.js
deleted file mode 100644
index 12a9be05..00000000
--- a/opendc-web/opendc-web-ui/src/api/users.js
+++ /dev/null
@@ -1,32 +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'
-
-/**
- * Fetch information about the user from the web server.
- *
- * @param auth The authentication object.
- */
-export function fetchUser(auth) {
- return request(auth, `users/me`)
-}
diff --git a/opendc-web/opendc-web-ui/src/auth.js b/opendc-web/opendc-web-ui/src/auth.js
deleted file mode 100644
index 8c88f526..00000000
--- a/opendc-web/opendc-web-ui/src/auth.js
+++ /dev/null
@@ -1,97 +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 PropTypes from 'prop-types'
-import { Auth0Provider, useAuth0 } from '@auth0/auth0-react'
-import { useEffect } from 'react'
-import { auth } from './config'
-
-/**
- * Helper function to provide the authentication context in case Auth0 is not
- * configured and the user is anonymous.
- */
-function useAnonymousAuth() {
- return {
- isAnonymous: true,
- isAuthenticated: false,
- isLoading: false,
- logout: () => {},
- loginWithRedirect: () => {},
- }
-}
-
-/**
- * Determine whether the auth domain is anonymous.
- */
-function isAnonymousDomain(config) {
- return !config.domain || config.domain === '%%NEXT_PUBLIC_AUTH0_DOMAIN%%'
-}
-
-/**
- * Force the user to be authenticated or redirect to the homepage.
- */
-function useRequireAuth0() {
- const auth = useAuth0()
- const { loginWithRedirect, isLoading, isAuthenticated } = auth
-
- useEffect(() => {
- if (!isLoading && !isAuthenticated) {
- loginWithRedirect()
- }
- }, [loginWithRedirect, isLoading, isAuthenticated])
-}
-
-/**
- * Obtain the authentication context.
- */
-export const useAuth = isAnonymousDomain(auth) ? useAnonymousAuth : useAuth0
-
-/**
- * Force the user to be authenticated or redirect to the homepage.
- */
-export const useRequireAuth = isAnonymousDomain(auth) ? () => {} : useRequireAuth0
-
-/**
- * AuthProvider which provides an authentication context.
- */
-export function AuthProvider({ children }) {
- const authConfig = auth
-
- if (!isAnonymousDomain(authConfig)) {
- return (
- <Auth0Provider
- domain={authConfig.domain}
- clientId={authConfig.clientId}
- redirectUri={authConfig.redirectUri}
- audience={authConfig.audience}
- >
- {children}
- </Auth0Provider>
- )
- }
-
- return children
-}
-
-AuthProvider.propTypes = {
- children: PropTypes.node,
-}
diff --git a/opendc-web/opendc-web-ui/src/components/AppHeader.js b/opendc-web/opendc-web-ui/src/components/AppHeader.js
deleted file mode 100644
index 514dce2a..00000000
--- a/opendc-web/opendc-web-ui/src/components/AppHeader.js
+++ /dev/null
@@ -1,69 +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 Image from 'next/image'
-import PropTypes from 'prop-types'
-import React from 'react'
-import {
- Masthead,
- MastheadMain,
- MastheadBrand,
- MastheadContent,
- Toolbar,
- ToolbarContent,
- ToolbarItem,
-} from '@patternfly/react-core'
-import Link from 'next/link'
-import AppHeaderTools from './AppHeaderTools'
-import AppHeaderUser from './AppHeaderUser'
-import ProjectSelector from './context/ProjectSelector'
-
-import styles from './AppHeader.module.css'
-
-export default function AppHeader({ nav }) {
- return (
- <Masthead id="app-header" className={styles.header}>
- <MastheadMain>
- <MastheadBrand className={styles.logo} component={(props) => <Link href="/projects" {...props} />}>
- <Image src="/img/logo.svg" alt="OpenDC logo" width={25} height={25} />
- <span>OpenDC</span>
- </MastheadBrand>
- </MastheadMain>
- <MastheadContent>
- <Toolbar id="toolbar" isFullHeight isStatic>
- <ToolbarContent>
- <ToolbarItem>
- <ProjectSelector />
- </ToolbarItem>
- {nav && <ToolbarItem>{nav}</ToolbarItem>}
- <AppHeaderTools />
- <AppHeaderUser />
- </ToolbarContent>
- </Toolbar>
- </MastheadContent>
- </Masthead>
- )
-}
-
-AppHeader.propTypes = {
- nav: PropTypes.node,
-}
diff --git a/opendc-web/opendc-web-ui/src/components/AppHeader.module.css b/opendc-web/opendc-web-ui/src/components/AppHeader.module.css
deleted file mode 100644
index 9d5dbed1..00000000
--- a/opendc-web/opendc-web-ui/src/components/AppHeader.module.css
+++ /dev/null
@@ -1,42 +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.
- */
-
-.header.header {
- /* Increase precedence */
- --pf-c-masthead--m-display-inline__content--MinHeight: 3rem;
- --pf-c-masthead--m-display-inline__main--MinHeight: 3rem;
-
- --pf-c-masthead--c-context-selector--Width: 200px;
-}
-
-.logo > span {
- margin-left: 8px;
- color: #fff;
- align-self: center;
- font-weight: 600;
- font-size: 0.9rem;
-}
-
-.logo:hover,
-.logo:focus > span {
- --pf-global--link--TextDecoration: none;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/AppHeaderTools.js b/opendc-web/opendc-web-ui/src/components/AppHeaderTools.js
deleted file mode 100644
index 499bceef..00000000
--- a/opendc-web/opendc-web-ui/src/components/AppHeaderTools.js
+++ /dev/null
@@ -1,93 +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 {
- Button,
- ButtonVariant,
- Dropdown,
- DropdownItem,
- KebabToggle,
- ToolbarGroup,
- ToolbarItem,
-} from '@patternfly/react-core'
-import { useReducer } from 'react'
-import { GithubIcon, HelpIcon } from '@patternfly/react-icons'
-
-function AppHeaderTools() {
- const [isKebabDropdownOpen, toggleKebabDropdown] = useReducer((t) => !t, false)
- const kebabDropdownItems = [
- <DropdownItem
- key={0}
- component={
- <a href="https://opendc.org" target="_blank" rel="noreferrer">
- <HelpIcon /> Help
- </a>
- }
- />,
- ]
-
- return (
- <ToolbarGroup
- variant="icon-button-group"
- alignment={{ default: 'alignRight' }}
- spacer={{ default: 'spacerNone', md: 'spacerMd' }}
- >
- <ToolbarGroup variant="icon-button-group" visibility={{ default: 'hidden', lg: 'visible' }}>
- <ToolbarItem>
- <Button
- component="a"
- href="https://github.com/atlarge-research/opendc"
- target="_blank"
- aria-label="Source code"
- variant={ButtonVariant.plain}
- >
- <GithubIcon />
- </Button>
- </ToolbarItem>
- <ToolbarItem>
- <Button
- component="a"
- href="https://opendc.org/"
- target="_blank"
- aria-label="Help actions"
- variant={ButtonVariant.plain}
- >
- <HelpIcon />
- </Button>
- </ToolbarItem>
- </ToolbarGroup>
- <ToolbarItem visibility={{ lg: 'hidden' }}>
- <Dropdown
- isPlain
- position="right"
- toggle={<KebabToggle onToggle={toggleKebabDropdown} />}
- isOpen={isKebabDropdownOpen}
- dropdownItems={kebabDropdownItems}
- />
- </ToolbarItem>
- </ToolbarGroup>
- )
-}
-
-AppHeaderTools.propTypes = {}
-
-export default AppHeaderTools
diff --git a/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js b/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js
deleted file mode 100644
index 3a73d9ba..00000000
--- a/opendc-web/opendc-web-ui/src/components/AppHeaderUser.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2022 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 {
- Dropdown,
- DropdownToggle,
- Skeleton,
- ToolbarItem,
- DropdownItem,
- DropdownGroup,
- Avatar,
- Progress,
- ProgressSize,
- DropdownSeparator,
-} from '@patternfly/react-core'
-import { useReducer } from 'react'
-import { useAuth } from '../auth'
-import useUser from '../data/user'
-
-export default function AppHeaderUser() {
- const { logout, user, isAuthenticated, isLoading } = useAuth()
- const username = isAuthenticated || isLoading ? user?.name : 'Anonymous'
- const avatar = isAuthenticated || isLoading ? user?.picture : '/img/avatar.svg'
-
- const { data } = useUser()
- const simulationBudget = data?.accounting?.simulationTimeBudget ?? 3600
- const simulationTime = data?.accounting?.simulationTime | 0
-
- const [isDropdownOpen, toggleDropdown] = useReducer((t) => !t, false)
- const userDropdownItems = [
- <DropdownGroup key="budget" label="Monthly Simulation Budget">
- <DropdownItem isDisabled>
- <Progress
- min={0}
- max={simulationBudget}
- value={simulationTime}
- title={`${Math.ceil(simulationTime / 60)} of ${Math.ceil(simulationBudget / 60)} minutes`}
- size={ProgressSize.sm}
- />
- </DropdownItem>
- </DropdownGroup>,
- <DropdownSeparator key="separator" />,
- <DropdownItem
- key="group 2 logout"
- isDisabled={!isAuthenticated}
- onClick={() => logout({ returnTo: window.location.origin })}
- >
- Logout
- </DropdownItem>,
- ]
-
- const avatarComponent = avatar ? (
- <Avatar src={avatar} alt="Avatar image" size="sm" />
- ) : (
- <Skeleton className="pf-c-avatar" shape="circle" width="24px" screenreaderText="Loading avatar" />
- )
-
- return (
- <ToolbarItem visibility={{ default: 'hidden', md: 'visible' }}>
- <Dropdown
- isFullHeight
- position="right"
- isOpen={isDropdownOpen}
- toggle={
- <DropdownToggle onToggle={toggleDropdown} icon={avatarComponent}>
- {username ?? (
- <Skeleton
- fontSize="xs"
- width="150px"
- className="pf-u-display-inline-flex"
- screenreaderText="Loading username"
- />
- )}
- </DropdownToggle>
- }
- dropdownItems={userDropdownItems}
- />
- </ToolbarItem>
- )
-}
diff --git a/opendc-web/opendc-web-ui/src/components/AppPage.js b/opendc-web/opendc-web-ui/src/components/AppPage.js
deleted file mode 100644
index 2893146e..00000000
--- a/opendc-web/opendc-web-ui/src/components/AppPage.js
+++ /dev/null
@@ -1,44 +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 PropTypes from 'prop-types'
-import AppHeader from './AppHeader'
-import React from 'react'
-import { Page, PageGroup, PageBreadcrumb } from '@patternfly/react-core'
-
-export function AppPage({ children, breadcrumb, contextSelectors }) {
- return (
- <Page header={<AppHeader />}>
- <PageGroup>
- {contextSelectors}
- {breadcrumb && <PageBreadcrumb>{breadcrumb}</PageBreadcrumb>}
- </PageGroup>
- {children}
- </Page>
- )
-}
-
-AppPage.propTypes = {
- breadcrumb: PropTypes.node,
- contextSelectors: PropTypes.node,
- children: PropTypes.node,
-}
diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.js b/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.js
deleted file mode 100644
index f3c25b79..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.js
+++ /dev/null
@@ -1,34 +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 PropTypes from 'prop-types'
-import { contextSelectionSection } from './ContextSelectionSection.module.css'
-
-function ContextSelectionSection({ children }) {
- return <section className={contextSelectionSection}>{children}</section>
-}
-
-ContextSelectionSection.propTypes = {
- children: PropTypes.node,
-}
-
-export default ContextSelectionSection
diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.module.css b/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.module.css
deleted file mode 100644
index 0e902af0..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/ContextSelectionSection.module.css
+++ /dev/null
@@ -1,28 +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.
- */
-
-.contextSelectionSection {
- padding-left: var(--pf-c-page__main-breadcrumb--PaddingLeft);
- flex-shrink: 0;
- border-bottom: var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--100);
- background-color: var(--pf-c-page__main-breadcrumb--BackgroundColor);
-}
diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js
deleted file mode 100644
index d2601008..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.js
+++ /dev/null
@@ -1,79 +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 PropTypes from 'prop-types'
-import { ContextSelector as PFContextSelector, ContextSelectorItem } from '@patternfly/react-core'
-import { useMemo, useState } from 'react'
-
-import styles from './ContextSelector.module.css'
-
-function ContextSelector({ id, type = 'page', toggleText, items, onSelect, onToggle, isOpen, isFullHeight }) {
- const [searchValue, setSearchValue] = useState('')
- const filteredItems = useMemo(
- () => items.filter(({ name }) => name.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1) || items,
- [items, searchValue]
- )
-
- return (
- <PFContextSelector
- id={id}
- className={type === 'page' && styles.pageSelector}
- toggleText={toggleText}
- onSearchInputChange={(value) => setSearchValue(value)}
- searchInputValue={searchValue}
- onToggle={(_, isOpen) => onToggle(isOpen)}
- onSelect={(event) => {
- const targetId = +event.target.value
- const target = items.find((item) => item.id === targetId)
-
- onSelect(target)
- onToggle(!isOpen)
- }}
- isOpen={isOpen}
- isFullHeight={isFullHeight}
- >
- {filteredItems.map((item) => (
- <ContextSelectorItem key={item.id} value={item.id}>
- {item.name}
- </ContextSelectorItem>
- ))}
- </PFContextSelector>
- )
-}
-
-const Item = PropTypes.shape({
- id: PropTypes.any.isRequired,
- name: PropTypes.string.isRequired,
-})
-
-ContextSelector.propTypes = {
- id: PropTypes.string,
- type: PropTypes.oneOf(['app', 'page']),
- items: PropTypes.arrayOf(Item).isRequired,
- toggleText: PropTypes.string,
- onSelect: PropTypes.func.isRequired,
- onToggle: PropTypes.func.isRequired,
- isOpen: PropTypes.bool,
- isFullHeight: PropTypes.bool,
-}
-
-export default ContextSelector
diff --git a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.css b/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.css
deleted file mode 100644
index 7662d00c..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/ContextSelector.module.css
+++ /dev/null
@@ -1,44 +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.
- */
-
-.pageSelector.pageSelector {
- /* Ensure this selector has precedence over the default one */
- margin-right: 20px;
-
- --pf-c-context-selector__menu--ZIndex: var(--pf-global--ZIndex--lg);
- --pf-c-context-selector__toggle--PaddingTop: var(--pf-global--spacer--sm);
- --pf-c-context-selector__toggle--PaddingRight: 0;
- --pf-c-context-selector__toggle--PaddingBottom: var(--pf-global--spacer--sm);
- --pf-c-context-selector__toggle--PaddingLeft: 0;
- --pf-c-context-selector__toggle--BorderWidth: 0;
- --pf-c-context-selector__toggle-text--FontSize: var(--pf-global--FontSize--sm);
-}
-
-.pageSelector.pageSelector :global(.pf-c-context-selector__toggle):active,
-.pageSelector.pageSelector :global(.pf-c-context-selector__toggle):focus-within,
-.pageSelector.pageSelector :global(.pf-c-context-selector__toggle):global(.pf-m-active) {
- --pf-c-context-selector__toggle--after--BorderBottomWidth: 0;
-}
-
-.pageSelector.pageSelector:global(.pf-m-expanded) > :global(.pf-c-context-selector__toggle) {
- --pf-c-context-selector__toggle--after--BorderBottomWidth: 0;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js b/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js
deleted file mode 100644
index e401e6fc..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/PortfolioSelector.js
+++ /dev/null
@@ -1,52 +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 { useRouter } from 'next/router'
-import { useState } from 'react'
-import { usePortfolios } from '../../data/project'
-import { Portfolio } from '../../shapes'
-import ContextSelector from './ContextSelector'
-
-function PortfolioSelector({ activePortfolio }) {
- const router = useRouter()
-
- const [isOpen, setOpen] = useState(false)
- const { data: portfolios = [] } = usePortfolios(activePortfolio?.project?.id, { enabled: isOpen })
-
- return (
- <ContextSelector
- id="portfolio"
- toggleText={activePortfolio ? `Portfolio: ${activePortfolio.name}` : 'Select portfolio'}
- activeItem={activePortfolio}
- items={portfolios}
- 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
deleted file mode 100644
index f2791b38..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/ProjectSelector.js
+++ /dev/null
@@ -1,55 +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 { useRouter } from 'next/router'
-import { useState } from 'react'
-import { useProjects, useProject } from '../../data/project'
-import { Project } from '../../shapes'
-import ContextSelector from './ContextSelector'
-
-function ProjectSelector() {
- const router = useRouter()
- const projectId = +router.query['project']
-
- const [isOpen, setOpen] = useState(false)
- const { data: activeProject } = useProject(+projectId)
- const { data: projects = [] } = useProjects({ enabled: isOpen })
-
- return (
- <ContextSelector
- id="project"
- type="app"
- toggleText={activeProject ? activeProject.name : 'Select project'}
- items={projects}
- onSelect={(project) => router.push(`/projects/${project.id}`)}
- onToggle={setOpen}
- isOpen={isOpen}
- isFullHeight
- />
- )
-}
-
-ProjectSelector.propTypes = {
- 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
deleted file mode 100644
index 355d9f4b..00000000
--- a/opendc-web/opendc-web-ui/src/components/context/TopologySelector.js
+++ /dev/null
@@ -1,52 +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 { useRouter } from 'next/router'
-import { useState } from 'react'
-import { useTopologies } from '../../data/topology'
-import { Topology } from '../../shapes'
-import ContextSelector from './ContextSelector'
-
-function TopologySelector({ activeTopology }) {
- const router = useRouter()
-
- const [isOpen, setOpen] = useState(false)
- const { data: topologies = [] } = useTopologies(activeTopology?.project?.id, { enabled: isOpen })
-
- return (
- <ContextSelector
- id="topology"
- toggleText={activeTopology ? `Topology: ${activeTopology.name}` : 'Select topology'}
- activeItem={activeTopology}
- items={topologies}
- onSelect={(topology) => router.push(`/projects/${topology.project.id}/topologies/${topology.number}`)}
- onToggle={setOpen}
- isOpen={isOpen}
- />
- )
-}
-
-TopologySelector.propTypes = {
- 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
deleted file mode 100644
index fd9a72d2..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/NewScenario.js
+++ /dev/null
@@ -1,60 +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 PropTypes from 'prop-types'
-import { PlusIcon } from '@patternfly/react-icons'
-import { Button } from '@patternfly/react-core'
-import { useState } from 'react'
-import { useNewScenario } from '../../data/project'
-import NewScenarioModal from './NewScenarioModal'
-
-function NewScenario({ projectId, portfolioId }) {
- const [isVisible, setVisible] = useState(false)
- const { mutate: addScenario } = useNewScenario()
-
- const onSubmit = (projectId, portfolioNumber, data) => {
- addScenario({ projectId, portfolioNumber, data })
- setVisible(false)
- }
-
- return (
- <>
- <Button icon={<PlusIcon />} isSmall onClick={() => setVisible(true)}>
- New Scenario
- </Button>
- <NewScenarioModal
- projectId={projectId}
- portfolioId={portfolioId}
- isOpen={isVisible}
- onSubmit={onSubmit}
- onCancel={() => setVisible(false)}
- />
- </>
- )
-}
-
-NewScenario.propTypes = {
- projectId: PropTypes.number,
- portfolioId: PropTypes.number,
-}
-
-export default NewScenario
diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/NewScenarioModal.js b/opendc-web/opendc-web-ui/src/components/portfolios/NewScenarioModal.js
deleted file mode 100644
index ed35c163..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/NewScenarioModal.js
+++ /dev/null
@@ -1,157 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useRef, useState } from 'react'
-import Modal from '../util/modals/Modal'
-import {
- Checkbox,
- Form,
- FormGroup,
- FormSection,
- FormSelect,
- FormSelectOption,
- NumberInput,
- TextInput,
-} from '@patternfly/react-core'
-import { useSchedulers, useTraces } from '../../data/experiments'
-import { useTopologies } from '../../data/topology'
-import { usePortfolio } from '../../data/project'
-
-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)
- const [traceLoad, setTraceLoad] = useState(100)
- const [trace, setTrace] = useState(undefined)
- const [topology, setTopology] = useState(undefined)
- const [scheduler, setScheduler] = useState(undefined)
- const [failuresEnabled, setFailuresEnabled] = useState(false)
- const [opPhenEnabled, setOpPhenEnabled] = useState(false)
- const nameInput = useRef(null)
-
- const resetState = () => {
- setSubmitted(false)
- setTraceLoad(100)
- setTrace(undefined)
- setTopology(undefined)
- setScheduler(undefined)
- setFailuresEnabled(false)
- setOpPhenEnabled(false)
- nameInput.current.value = ''
- }
-
- const onSubmit = (event) => {
- setSubmitted(true)
-
- if (event) {
- event.preventDefault()
- }
-
- const name = nameInput.current.value
-
- onSubmitUpstream(portfolio.project.id, portfolio.number, {
- name,
- workload: {
- trace: trace || traces[0].id,
- samplingFraction: traceLoad / 100,
- },
- topology: topology || topologies[0].number,
- phenomena: {
- failures: failuresEnabled,
- interference: opPhenEnabled,
- },
- schedulerName: scheduler || schedulers[0],
- })
-
- resetState()
- return true
- }
- const onCancel = () => {
- onCancelUpstream()
- resetState()
- }
-
- return (
- <Modal title="New Scenario" isOpen={isOpen} onSubmit={onSubmit} onCancel={onCancel}>
- <Form onSubmit={onSubmit}>
- <FormGroup label="Name" fieldId="name" isRequired>
- <TextInput
- id="name"
- name="name"
- type="text"
- isDisabled={portfolio?.scenarios?.length === 0}
- defaultValue={portfolio?.scenarios?.length === 0 ? 'Base scenario' : ''}
- ref={nameInput}
- />
- </FormGroup>
- <FormSection title="Workload">
- <FormGroup label="Trace" fieldId="trace" isRequired>
- <FormSelect id="trace" name="trace" value={trace} onChange={setTrace}>
- {traces.map((trace) => (
- <FormSelectOption value={trace.id} key={trace.id} label={trace.name} />
- ))}
- </FormSelect>
- </FormGroup>
- <FormGroup label="Load Sampling Fraction" fieldId="trace-load" isRequired>
- <NumberInput
- name="trace-load"
- type="number"
- min={0}
- max={100}
- value={traceLoad}
- onMinus={() => setTraceLoad((load) => load - 1)}
- onPlus={() => setTraceLoad((load) => load + 1)}
- onChange={(e) => setTraceLoad(Number(e.target.value))}
- unit="%"
- />
- </FormGroup>
- </FormSection>
- <FormSection title="Topology">
- <FormGroup label="Topology" fieldId="topology" isRequired>
- <FormSelect id="topology" name="topology" value={topology} onChange={setTopology}>
- {topologies.map((topology) => (
- <FormSelectOption value={topology.number} key={topology.number} label={topology.name} />
- ))}
- </FormSelect>
- </FormGroup>
-
- <FormGroup label="Scheduler" fieldId="scheduler" isRequired>
- <FormSelect id="scheduler" name="scheduler" value={scheduler} onChange={setScheduler}>
- {schedulers.map((scheduler) => (
- <FormSelectOption value={scheduler} key={scheduler} label={scheduler} />
- ))}
- </FormSelect>
- </FormGroup>
- </FormSection>
- <FormSection title="Operational Phenomena">
- <Checkbox
- label="Failures"
- id="failures"
- name="failures"
- isChecked={failuresEnabled}
- onChange={() => setFailuresEnabled((e) => !e)}
- />
- <Checkbox
- label="Performance Interference"
- id="perf-interference"
- name="perf-interference"
- isChecked={opPhenEnabled}
- onChange={() => setOpPhenEnabled((e) => !e)}
- />
- </FormSection>
- </Form>
- </Modal>
- )
-}
-
-NewScenarioModal.propTypes = {
- projectId: PropTypes.number,
- portfolioId: PropTypes.number,
- isOpen: PropTypes.bool.isRequired,
- onSubmit: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired,
-}
-
-export default NewScenarioModal
diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js
deleted file mode 100644
index e561b655..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioOverview.js
+++ /dev/null
@@ -1,120 +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 PropTypes from 'prop-types'
-import {
- Card,
- CardActions,
- CardBody,
- CardHeader,
- CardTitle,
- Chip,
- ChipGroup,
- DescriptionList,
- DescriptionListDescription,
- DescriptionListGroup,
- DescriptionListTerm,
- Grid,
- GridItem,
- Skeleton,
-} from '@patternfly/react-core'
-import React from 'react'
-import { usePortfolio } from '../../data/project'
-import { METRIC_NAMES } from '../../util/available-metrics'
-import NewScenario from './NewScenario'
-import ScenarioTable from './ScenarioTable'
-
-function PortfolioOverview({ projectId, portfolioId }) {
- const { status, data: portfolio } = usePortfolio(projectId, portfolioId)
-
- return (
- <Grid hasGutter>
- <GridItem md={2}>
- <Card>
- <CardTitle>Details</CardTitle>
- <CardBody>
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Name</DescriptionListTerm>
- <DescriptionListDescription>
- {portfolio?.name ?? <Skeleton screenreaderText="Loading portfolio" />}
- </DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Scenarios</DescriptionListTerm>
- <DescriptionListDescription>
- {portfolio?.scenarios?.length ?? <Skeleton screenreaderText="Loading portfolio" />}
- </DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Metrics</DescriptionListTerm>
- <DescriptionListDescription>
- {portfolio ? (
- portfolio.targets.metrics.length > 0 ? (
- <ChipGroup>
- {portfolio.targets.metrics.map((metric) => (
- <Chip isReadOnly key={metric}>
- {METRIC_NAMES[metric]}
- </Chip>
- ))}
- </ChipGroup>
- ) : (
- 'No metrics enabled'
- )
- ) : (
- <Skeleton screenreaderText="Loading portfolio" />
- )}
- </DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Repeats per Scenario</DescriptionListTerm>
- <DescriptionListDescription>
- {portfolio?.targets?.repeats ?? <Skeleton screenreaderText="Loading portfolio" />}
- </DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- </CardBody>
- </Card>
- </GridItem>
- <GridItem md={6}>
- <Card>
- <CardHeader>
- <CardActions>
- <NewScenario projectId={projectId} portfolioId={portfolioId} />
- </CardActions>
- <CardTitle>Scenarios</CardTitle>
- </CardHeader>
- <CardBody>
- <ScenarioTable portfolio={portfolio} status={status} />
- </CardBody>
- </Card>
- </GridItem>
- </Grid>
- )
-}
-
-PortfolioOverview.propTypes = {
- projectId: PropTypes.number,
- portfolioId: PropTypes.number,
-}
-
-export default PortfolioOverview
diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResultInfo.js b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResultInfo.js
deleted file mode 100644
index dbfa928f..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResultInfo.js
+++ /dev/null
@@ -1,40 +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 PropTypes from 'prop-types'
-import { Tooltip } from '@patternfly/react-core'
-import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'
-import { METRIC_DESCRIPTIONS } from '../../util/available-metrics'
-
-function PortfolioResultInfo({ metric }) {
- return (
- <Tooltip position="top" content={<div>{METRIC_DESCRIPTIONS[metric]}</div>}>
- <OutlinedQuestionCircleIcon title="Metric information" />
- </Tooltip>
- )
-}
-
-PortfolioResultInfo.propTypes = {
- metric: PropTypes.string.isRequired,
-}
-
-export default PortfolioResultInfo
diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js b/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js
deleted file mode 100644
index 62150fa7..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/PortfolioResults.js
+++ /dev/null
@@ -1,180 +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 { mean, std } from 'mathjs'
-import React, { useMemo } from 'react'
-import PropTypes from 'prop-types'
-import { VictoryErrorBar } from 'victory-errorbar'
-import { METRIC_NAMES, METRIC_UNITS, AVAILABLE_METRICS } from '../../util/available-metrics'
-import {
- Bullseye,
- Card,
- CardActions,
- CardBody,
- CardHeader,
- CardTitle,
- EmptyState,
- EmptyStateBody,
- EmptyStateIcon,
- Grid,
- GridItem,
- Spinner,
- Title,
-} from '@patternfly/react-core'
-import { Chart, ChartAxis, ChartBar, ChartTooltip } from '@patternfly/react-charts'
-import { ErrorCircleOIcon, CubesIcon } from '@patternfly/react-icons'
-import { usePortfolio } from '../../data/project'
-import PortfolioResultInfo from './PortfolioResultInfo'
-import NewScenario from './NewScenario'
-
-function PortfolioResults({ projectId, portfolioId }) {
- const { status, data: portfolio } = usePortfolio(projectId, portfolioId)
- const scenarios = useMemo(() => portfolio?.scenarios ?? [], [portfolio])
-
- const label = ({ datum }) =>
- `${datum.x}: ${datum.y.toLocaleString()} ± ${datum.errorY.toLocaleString()} ${METRIC_UNITS[datum.metric]}`
- const selectedMetrics = new Set(portfolio?.targets?.metrics ?? [])
- const dataPerMetric = useMemo(() => {
- const dataPerMetric = {}
- AVAILABLE_METRICS.forEach((metric) => {
- dataPerMetric[metric] = scenarios
- .filter((scenario) => scenario.jobs && scenario.jobs[scenario.jobs.length - 1].results)
- .map((scenario) => {
- const job = scenario.jobs[scenario.jobs.length - 1]
- return {
- metric,
- x: scenario.name,
- y: mean(job.results[metric]),
- errorY: std(job.results[metric]),
- label,
- }
- })
- })
- return dataPerMetric
- }, [scenarios])
-
- const categories = useMemo(() => ({ x: scenarios.map((s) => s.name).reverse() }), [scenarios])
-
- if (status === 'loading') {
- return (
- <Bullseye>
- <EmptyState>
- <EmptyStateIcon variant="container" component={Spinner} />
- <Title size="lg" headingLevel="h4">
- Loading Results
- </Title>
- </EmptyState>
- </Bullseye>
- )
- } else if (status === 'error') {
- return (
- <Bullseye>
- <EmptyState>
- <EmptyStateIcon variant="container" component={ErrorCircleOIcon} />
- <Title size="lg" headingLevel="h4">
- Unable to connect
- </Title>
- <EmptyStateBody>
- There was an error retrieving data. Check your connection and try again.
- </EmptyStateBody>
- </EmptyState>
- </Bullseye>
- )
- } else if (scenarios.length === 0) {
- return (
- <Bullseye>
- <EmptyState>
- <EmptyStateIcon variant="container" component={CubesIcon} />
- <Title size="lg" headingLevel="h4">
- No results
- </Title>
- <EmptyStateBody>
- No results are currently available for this portfolio. Run a scenario to obtain simulation
- results.
- </EmptyStateBody>
- <NewScenario projectId={projectId} portfolioId={portfolioId} />
- </EmptyState>
- </Bullseye>
- )
- }
-
- return (
- <Grid hasGutter>
- {AVAILABLE_METRICS.map(
- (metric) =>
- selectedMetrics.has(metric) && (
- <GridItem xl={6} lg={12} key={metric}>
- <Card>
- <CardHeader>
- <CardActions>
- <PortfolioResultInfo metric={metric} />
- </CardActions>
- <CardTitle>{METRIC_NAMES[metric]}</CardTitle>
- </CardHeader>
- <CardBody>
- <Chart
- width={650}
- height={250}
- padding={{
- top: 10,
- bottom: 60,
- left: 130,
- }}
- domainPadding={25}
- >
- <ChartAxis />
- <ChartAxis
- dependentAxis
- showGrid
- label={METRIC_UNITS[metric]}
- fixLabelOverlap
- />
- <ChartBar
- categories={categories}
- data={dataPerMetric[metric]}
- labelComponent={<ChartTooltip constrainToVisibleArea />}
- barWidth={25}
- horizontal
- />
- <VictoryErrorBar
- categories={categories}
- data={dataPerMetric[metric]}
- errorY={(d) => d.errorY}
- labelComponent={<></>}
- horizontal
- />
- </Chart>
- </CardBody>
- </Card>
- </GridItem>
- )
- )}
- </Grid>
- )
-}
-
-PortfolioResults.propTypes = {
- 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
deleted file mode 100644
index 99d83f64..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioState.js
+++ /dev/null
@@ -1,62 +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 { ClockIcon, CheckCircleIcon, ErrorCircleOIcon } from '@patternfly/react-icons'
-import { JobState } from '../../shapes'
-
-function ScenarioState({ state }) {
- switch (state) {
- case 'PENDING':
- case 'CLAIMED':
- return (
- <span>
- <ClockIcon color="blue" /> Queued
- </span>
- )
- case 'RUNNING':
- return (
- <span>
- <ClockIcon color="green" /> Running
- </span>
- )
- case 'FINISHED':
- return (
- <span>
- <CheckCircleIcon color="green" /> Finished
- </span>
- )
- case 'FAILED':
- return (
- <span>
- <ErrorCircleOIcon color="red" /> Failed
- </span>
- )
- }
-
- return 'Unknown'
-}
-
-ScenarioState.propTypes = {
- 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
deleted file mode 100644
index b068d045..00000000
--- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js
+++ /dev/null
@@ -1,103 +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 { Bullseye } from '@patternfly/react-core'
-import Link from 'next/link'
-import { TableComposable, Thead, Tr, Th, Tbody, Td, ActionsColumn } from '@patternfly/react-table'
-import React from 'react'
-import { Portfolio, Status } from '../../shapes'
-import TableEmptyState from '../util/TableEmptyState'
-import ScenarioState from './ScenarioState'
-import { useDeleteScenario } from '../../data/project'
-
-function ScenarioTable({ portfolio, status }) {
- const { mutate: deleteScenario } = useDeleteScenario()
- const projectId = portfolio?.project?.id
- const scenarios = portfolio?.scenarios ?? []
-
- const actions = ({ number }) => [
- {
- title: 'Delete Scenario',
- onClick: () => deleteScenario({ projectId: projectId, number }),
- isDisabled: number === 0,
- },
- ]
-
- return (
- <TableComposable aria-label="Scenario List" variant="compact">
- <Thead>
- <Tr>
- <Th>Name</Th>
- <Th>Topology</Th>
- <Th>Trace</Th>
- <Th>State</Th>
- </Tr>
- </Thead>
- <Tbody>
- {scenarios.map((scenario) => (
- <Tr key={scenario.id}>
- <Td dataLabel="Name">{scenario.name}</Td>
- <Td dataLabel="Topology">
- {scenario.topology ? (
- <Link href={`/projects/${projectId}/topologies/${scenario.topology.number}`}>
- {scenario.topology.name}
- </Link>
- ) : (
- 'Unknown Topology'
- )}
- </Td>
- <Td dataLabel="Workload">{`${scenario.workload.trace.name} (${
- scenario.workload.samplingFraction * 100
- }%)`}</Td>
- <Td dataLabel="State">
- <ScenarioState state={scenario.jobs[scenario.jobs.length - 1].state} />
- </Td>
- <Td isActionCell>
- <ActionsColumn items={actions(scenario)} />
- </Td>
- </Tr>
- ))}
- {scenarios.length === 0 && (
- <Tr>
- <Td colSpan={4}>
- <Bullseye>
- <TableEmptyState
- status={status}
- loadingTitle="Loading Scenarios"
- emptyTitle="No scenarios"
- emptyText="You have not created any scenario for this portfolio yet. Click the New Scenario button to create one."
- />
- </Bullseye>
- </Td>
- </Tr>
- )}
- </Tbody>
- </TableComposable>
- )
-}
-
-ScenarioTable.propTypes = {
- portfolio: Portfolio,
- status: Status.isRequired,
-}
-
-export default ScenarioTable
diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js
deleted file mode 100644
index 5aaa56ac..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { ToggleGroup, ToggleGroupItem } from '@patternfly/react-core'
-import { filterPanel } from './FilterPanel.module.css'
-
-export const FILTERS = { SHOW_ALL: 'All Projects', SHOW_OWN: 'My Projects', SHOW_SHARED: 'Shared with me' }
-
-const FilterPanel = ({ onSelect, activeFilter = 'SHOW_ALL' }) => (
- <ToggleGroup className={`${filterPanel} pf-u-mb-sm`}>
- {Object.keys(FILTERS).map((filter) => (
- <ToggleGroupItem
- key={filter}
- onChange={() => activeFilter === filter || onSelect(filter)}
- isSelected={activeFilter === filter}
- text={FILTERS[filter]}
- />
- ))}
- </ToggleGroup>
-)
-
-FilterPanel.propTypes = {
- onSelect: PropTypes.func.isRequired,
- activeFilter: PropTypes.string,
-}
-
-export default FilterPanel
diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.css b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.css
deleted file mode 100644
index 15c36821..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.filterPanel {
- display: flex;
-}
-
-.filterPanel > button {
- flex: 1 !important;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js b/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js
deleted file mode 100644
index aebcc3c9..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolio.js
+++ /dev/null
@@ -1,53 +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 PropTypes from 'prop-types'
-import { PlusIcon } from '@patternfly/react-icons'
-import { Button } from '@patternfly/react-core'
-import { useState } from 'react'
-import { useNewPortfolio } from '../../data/project'
-import NewPortfolioModal from './NewPortfolioModal'
-
-function NewPortfolio({ projectId }) {
- const [isVisible, setVisible] = useState(false)
- const { mutate: addPortfolio } = useNewPortfolio()
-
- const onSubmit = (name, targets) => {
- addPortfolio({ projectId, name, targets })
- setVisible(false)
- }
-
- return (
- <>
- <Button icon={<PlusIcon />} isSmall onClick={() => setVisible(true)}>
- New Portfolio
- </Button>
- <NewPortfolioModal isOpen={isVisible} onSubmit={onSubmit} onCancel={() => setVisible(false)} />
- </>
- )
-}
-
-NewPortfolio.propTypes = {
- 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
deleted file mode 100644
index ba4bc819..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/NewPortfolioModal.js
+++ /dev/null
@@ -1,161 +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 PropTypes from 'prop-types'
-import React, { useRef, useState } from 'react'
-import {
- Form,
- FormGroup,
- FormSection,
- NumberInput,
- Select,
- SelectGroup,
- SelectOption,
- SelectVariant,
- TextInput,
-} from '@patternfly/react-core'
-import Modal from '../util/modals/Modal'
-import { METRIC_GROUPS, METRIC_NAMES } from '../../util/available-metrics'
-
-const NewPortfolioModal = ({ isOpen, onSubmit: onSubmitUpstream, onCancel: onUpstreamCancel }) => {
- const nameInput = useRef(null)
- const [repeats, setRepeats] = useState(1)
- const [isSelectOpen, setSelectOpen] = useState(false)
- const [selectedMetrics, setSelectedMetrics] = useState([])
-
- const [isSubmitted, setSubmitted] = useState(false)
- const [errors, setErrors] = useState({})
-
- const clearState = () => {
- setSubmitted(false)
- setErrors({})
- nameInput.current.value = ''
- setRepeats(1)
- setSelectOpen(false)
- setSelectedMetrics([])
- }
-
- const onSubmit = (event) => {
- setSubmitted(true)
-
- if (event) {
- event.preventDefault()
- }
-
- const name = nameInput.current.value
-
- if (!name) {
- setErrors({ name: true })
- return false
- } else {
- onSubmitUpstream(name, { metrics: selectedMetrics, repeats })
- }
-
- clearState()
- return false
- }
- const onCancel = () => {
- onUpstreamCancel()
- clearState()
- }
-
- const onSelect = (event, selection) => {
- if (selectedMetrics.includes(selection)) {
- setSelectedMetrics((metrics) => metrics.filter((item) => item !== selection))
- } else {
- setSelectedMetrics((metrics) => [...metrics, selection])
- }
- }
-
- return (
- <Modal title="New Portfolio" isOpen={isOpen} onSubmit={onSubmit} onCancel={onCancel}>
- <Form onSubmit={onSubmit}>
- <FormSection>
- <FormGroup
- label="Name"
- fieldId="name"
- isRequired
- validated={isSubmitted && errors.name ? 'error' : 'default'}
- helperTextInvalid="This field cannot be empty"
- >
- <TextInput
- name="name"
- id="name"
- type="text"
- isRequired
- ref={nameInput}
- placeholder="My Portfolio"
- />
- </FormGroup>
- </FormSection>
- <FormSection title="Targets" titleElement="h4">
- <FormGroup label="Metrics" fieldId="metrics">
- <Select
- variant={SelectVariant.typeaheadMulti}
- typeAheadAriaLabel="Select a metric"
- onToggle={() => setSelectOpen(!isSelectOpen)}
- onSelect={onSelect}
- onClear={() => setSelectedMetrics([])}
- selections={selectedMetrics}
- isOpen={isSelectOpen}
- placeholderText="Select a metric"
- menuAppendTo="parent"
- maxHeight="300px"
- chipGroupProps={{ numChips: 1 }}
- isGrouped
- >
- {Object.entries(METRIC_GROUPS).map(([group, metrics]) => (
- <SelectGroup label={group} key={group}>
- {metrics.map((metric) => (
- <SelectOption key={metric} value={metric}>
- {METRIC_NAMES[metric]}
- </SelectOption>
- ))}
- </SelectGroup>
- ))}
- </Select>
- </FormGroup>
- <FormGroup label="Repeats per Scenario" fieldId="repeats">
- <NumberInput
- id="repeats"
- inputName="repeats"
- type="number"
- value={repeats}
- onChange={(e) => setRepeats(Number(e.target.value))}
- onPlus={() => setRepeats((r) => r + 1)}
- onMinus={() => setRepeats((r) => r - 1)}
- min={1}
- />
- </FormGroup>
- </FormSection>
- </Form>
- </Modal>
- )
-}
-
-NewPortfolioModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onSubmit: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired,
-}
-
-export default NewPortfolioModal
diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js b/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js
deleted file mode 100644
index 4c569c56..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/NewTopology.js
+++ /dev/null
@@ -1,57 +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 PropTypes from 'prop-types'
-import { PlusIcon } from '@patternfly/react-icons'
-import { Button } from '@patternfly/react-core'
-import { useState } from 'react'
-import { useNewTopology } from '../../data/topology'
-import NewTopologyModal from './NewTopologyModal'
-
-function NewTopology({ projectId }) {
- const [isVisible, setVisible] = useState(false)
- const { mutate: addTopology } = useNewTopology()
-
- const onSubmit = (topology) => {
- addTopology(topology)
- setVisible(false)
- }
- return (
- <>
- <Button icon={<PlusIcon />} isSmall onClick={() => setVisible(true)}>
- New Topology
- </Button>
- <NewTopologyModal
- projectId={projectId}
- isOpen={isVisible}
- onSubmit={onSubmit}
- onCancel={() => setVisible(false)}
- />
- </>
- )
-}
-
-NewTopology.propTypes = {
- 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
deleted file mode 100644
index 780ec034..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/NewTopologyModal.js
+++ /dev/null
@@ -1,115 +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 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 { useTopologies } from '../../data/topology'
-import Modal from '../util/modals/Modal'
-
-const NewTopologyModal = ({ projectId, isOpen, onSubmit: onSubmitUpstream, onCancel: onCancelUpstream }) => {
- const nameInput = useRef(null)
- const [isSubmitted, setSubmitted] = useState(false)
- const [originTopology, setOriginTopology] = useState(-1)
- const [errors, setErrors] = useState({})
-
- const { data: topologies = [] } = useTopologies(projectId, { enabled: isOpen })
-
- const clearState = () => {
- if (nameInput.current) {
- nameInput.current.value = ''
- }
- setSubmitted(false)
- setOriginTopology(-1)
- setErrors({})
- }
-
- const onSubmit = (event) => {
- setSubmitted(true)
-
- if (event) {
- event.preventDefault()
- }
-
- const name = nameInput.current.value
-
- if (!name) {
- setErrors({ name: true })
- return false
- } else {
- const candidate = topologies.find((topology) => topology.id === originTopology) || { rooms: [] }
- const topology = produce(candidate, (draft) => {
- delete draft.project
- draft.projectId = projectId
- draft.name = name
- })
- onSubmitUpstream(topology)
- }
-
- clearState()
- return true
- }
-
- const onCancel = () => {
- onCancelUpstream()
- clearState()
- }
-
- return (
- <Modal title="New Topology" isOpen={isOpen} onSubmit={onSubmit} onCancel={onCancel}>
- <Form onSubmit={onSubmit}>
- <FormGroup
- label="Name"
- fieldId="name"
- isRequired
- validated={isSubmitted && errors.name ? 'error' : 'default'}
- helperTextInvalid="This field cannot be empty"
- >
- <TextInput id="name" name="name" type="text" isRequired ref={nameInput} />
- </FormGroup>
- <FormGroup label="Topology to duplicate" fieldId="origin" isRequired>
- <FormSelect
- id="origin"
- name="origin"
- value={originTopology}
- onChange={(v) => setOriginTopology(+v)}
- >
- <FormSelectOption value={-1} key={-1} label="None - start from scratch" />
- {topologies.map((topology) => (
- <FormSelectOption value={topology.id} key={topology.id} label={topology.name} />
- ))}
- </FormSelect>
- </FormGroup>
- </Form>
- </Modal>
- )
-}
-
-NewTopologyModal.propTypes = {
- projectId: PropTypes.number,
- isOpen: PropTypes.bool.isRequired,
- onSubmit: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired,
-}
-
-export default NewTopologyModal
diff --git a/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js b/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js
deleted file mode 100644
index 0afeaeaf..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/PortfolioTable.js
+++ /dev/null
@@ -1,99 +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 { Bullseye } from '@patternfly/react-core'
-import PropTypes from 'prop-types'
-import Link from 'next/link'
-import { TableComposable, Thead, Tbody, Tr, Th, Td, ActionsColumn } from '@patternfly/react-table'
-import React from 'react'
-import TableEmptyState from '../util/TableEmptyState'
-import { usePortfolios, useDeletePortfolio } from '../../data/project'
-
-function PortfolioTable({ projectId }) {
- const { status, data: portfolios = [] } = usePortfolios(projectId)
- const { mutate: deletePortfolio } = useDeletePortfolio()
-
- const actions = (portfolio) => [
- {
- title: 'Delete Portfolio',
- onClick: () => deletePortfolio({ projectId, number: portfolio.number }),
- },
- ]
-
- return (
- <TableComposable aria-label="Portfolio List" variant="compact">
- <Thead>
- <Tr>
- <Th>Name</Th>
- <Th>Scenarios</Th>
- <Th>Metrics</Th>
- <Th>Repeats</Th>
- </Tr>
- </Thead>
- <Tbody>
- {portfolios.map((portfolio) => (
- <Tr key={portfolio.id}>
- <Td dataLabel="Name">
- <Link href={`/projects/${projectId}/portfolios/${portfolio.number}`}>{portfolio.name}</Link>
- </Td>
- <Td dataLabel="Scenarios">
- {portfolio.scenarios.length === 1
- ? '1 scenario'
- : `${portfolio.scenarios.length} scenarios`}
- </Td>
- <Td dataLabel="Metrics">
- {portfolio.targets.metrics.length === 1
- ? '1 metric'
- : `${portfolio.targets.metrics.length} metrics`}
- </Td>
- <Td dataLabel="Repeats">
- {portfolio.targets.repeats === 1 ? '1 repeat' : `${portfolio.targets.repeats} repeats`}
- </Td>
- <Td isActionCell>
- <ActionsColumn items={actions(portfolio)} />
- </Td>
- </Tr>
- ))}
- {portfolios.length === 0 && (
- <Tr>
- <Td colSpan={4}>
- <Bullseye>
- <TableEmptyState
- status={status}
- loadingTitle="Loading portfolios"
- emptyTitle="No portfolios"
- emptyText="You have not created any portfolio for this project yet. Click the New Portfolio button to create one."
- />
- </Bullseye>
- </Td>
- </Tr>
- )}
- </Tbody>
- </TableComposable>
- )
-}
-
-PortfolioTable.propTypes = {
- projectId: PropTypes.number,
-}
-
-export default PortfolioTable
diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js
deleted file mode 100644
index a26fed46..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import Link from 'next/link'
-import {
- Gallery,
- Bullseye,
- EmptyState,
- EmptyStateIcon,
- Card,
- CardTitle,
- CardActions,
- DropdownItem,
- CardHeader,
- Dropdown,
- KebabToggle,
- CardBody,
- CardHeaderMain,
- TextVariants,
- Text,
- TextContent,
- Tooltip,
- Button,
- Label,
-} from '@patternfly/react-core'
-import { PlusIcon, FolderIcon, TrashIcon } from '@patternfly/react-icons'
-import PropTypes from 'prop-types'
-import React, { useReducer, useMemo } from 'react'
-import { Project, Status } from '../../shapes'
-import { parseAndFormatDateTime } from '../../util/date-time'
-import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP, AUTH_NAME_MAP } from '../../util/authorizations'
-import TableEmptyState from '../util/TableEmptyState'
-
-function ProjectCard({ project, onDelete }) {
- const [isKebabOpen, toggleKebab] = useReducer((t) => !t, false)
- const { id, role, name, updatedAt } = project
- const Icon = AUTH_ICON_MAP[role]
-
- return (
- <Card
- isCompact
- isRounded
- isFlat
- className="pf-u-min-height"
- style={{ '--pf-u-min-height--MinHeight': '175px' }}
- >
- <CardHeader className="pf-u-flex-grow-1">
- <CardHeaderMain className="pf-u-align-self-flex-start">
- <FolderIcon />
- </CardHeaderMain>
- <CardActions>
- <Tooltip content={AUTH_DESCRIPTION_MAP[role]}>
- <Label icon={<Icon />}>{AUTH_NAME_MAP[role]}</Label>
- </Tooltip>
- <Dropdown
- isPlain
- position="right"
- toggle={<KebabToggle className="pf-u-px-0" onToggle={toggleKebab} />}
- isOpen={isKebabOpen}
- dropdownItems={[
- <DropdownItem
- key="trash"
- onClick={() => {
- onDelete()
- toggleKebab()
- }}
- position="right"
- icon={<TrashIcon />}
- >
- Delete
- </DropdownItem>,
- ]}
- />
- </CardActions>
- </CardHeader>
- <CardTitle component={Link} className="pf-u-pb-0" href={`/projects/${id}`}>
- {name}
- </CardTitle>
- <CardBody isFilled={false}>
- <TextContent>
- <Text component={TextVariants.small}>Last modified {parseAndFormatDateTime(updatedAt)}</Text>
- </TextContent>
- </CardBody>
- </Card>
- )
-}
-
-function ProjectCollection({ status, projects, onDelete, onCreate, isFiltering }) {
- const sortedProjects = useMemo(() => {
- const res = [...projects]
- res.sort((a, b) => (new Date(a.updatedAt) < new Date(b.updatedAt) ? 1 : -1))
- return res
- }, [projects])
-
- if (sortedProjects.length === 0) {
- return (
- <TableEmptyState
- status={status}
- isFiltering={isFiltering}
- loadingTitle="Loading Projects"
- emptyTitle="No projects"
- emptyText="You have not created any projects yet. Create a new project to get started quickly."
- emptyAction={
- <Button icon={<PlusIcon />} onClick={onCreate}>
- Create Project
- </Button>
- }
- />
- )
- }
-
- return (
- <Gallery hasGutter aria-label="Available projects">
- {sortedProjects.map((project) => (
- <ProjectCard key={project.id} project={project} onDelete={() => onDelete(project)} />
- ))}
- <Card isCompact isFlat isRounded style={{ borderStyle: 'dotted' }}>
- <Bullseye>
- <EmptyState>
- <Button isBlock variant="link" onClick={onCreate}>
- <EmptyStateIcon icon={PlusIcon} />
- <br />
- Create Project
- </Button>
- </EmptyState>
- </Bullseye>
- </Card>
- </Gallery>
- )
-}
-
-ProjectCollection.propTypes = {
- status: Status.isRequired,
- isFiltering: PropTypes.bool,
- projects: PropTypes.arrayOf(Project).isRequired,
- onDelete: PropTypes.func,
- onCreate: PropTypes.func,
-}
-
-export default ProjectCollection
diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js
deleted file mode 100644
index 3e1656f6..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/ProjectOverview.js
+++ /dev/null
@@ -1,98 +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 PropTypes from 'prop-types'
-import {
- Card,
- CardActions,
- CardBody,
- CardHeader,
- CardTitle,
- DescriptionList,
- DescriptionListDescription,
- DescriptionListGroup,
- DescriptionListTerm,
- Grid,
- GridItem,
- Skeleton,
-} from '@patternfly/react-core'
-import NewTopology from './NewTopology'
-import TopologyTable from './TopologyTable'
-import NewPortfolio from './NewPortfolio'
-import PortfolioTable from './PortfolioTable'
-import { useProject } from '../../data/project'
-
-function ProjectOverview({ projectId }) {
- const { data: project } = useProject(projectId)
-
- return (
- <Grid hasGutter>
- <GridItem md={2}>
- <Card>
- <CardTitle>Details</CardTitle>
- <CardBody>
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Name</DescriptionListTerm>
- <DescriptionListDescription>
- {project?.name ?? <Skeleton screenreaderText="Loading project" />}
- </DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- </CardBody>
- </Card>
- </GridItem>
- <GridItem md={5}>
- <Card>
- <CardHeader>
- <CardActions>
- <NewTopology projectId={projectId} />
- </CardActions>
- <CardTitle>Topologies</CardTitle>
- </CardHeader>
- <CardBody>
- <TopologyTable projectId={projectId} />
- </CardBody>
- </Card>
- </GridItem>
- <GridItem md={5}>
- <Card>
- <CardHeader>
- <CardActions>
- <NewPortfolio projectId={projectId} />
- </CardActions>
- <CardTitle>Portfolios</CardTitle>
- </CardHeader>
- <CardBody>
- <PortfolioTable projectId={projectId} />
- </CardBody>
- </Card>
- </GridItem>
- </Grid>
- )
-}
-
-ProjectOverview.propTypes = {
- projectId: PropTypes.number,
-}
-
-export default ProjectOverview
diff --git a/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js b/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js
deleted file mode 100644
index 1c2c4f04..00000000
--- a/opendc-web/opendc-web-ui/src/components/projects/TopologyTable.js
+++ /dev/null
@@ -1,115 +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 { Bullseye, AlertGroup, Alert, AlertVariant, AlertActionCloseButton } from '@patternfly/react-core'
-import PropTypes from 'prop-types'
-import Link from 'next/link'
-import { Tr, Th, Thead, Td, ActionsColumn, Tbody, TableComposable } from '@patternfly/react-table'
-import React, { useState } from 'react'
-import TableEmptyState from '../util/TableEmptyState'
-import { parseAndFormatDateTime } from '../../util/date-time'
-import { useTopologies, useDeleteTopology } from '../../data/topology'
-
-function TopologyTable({ projectId }) {
- const [error, setError] = useState('')
-
- const { status, data: topologies = [] } = useTopologies(projectId)
- const { mutate: deleteTopology } = useDeleteTopology({
- onError: (error) => setError(error),
- })
-
- const actions = ({ number }) => [
- {
- title: 'Delete Topology',
- onClick: () => deleteTopology({ projectId, number }),
- isDisabled: number === 0,
- },
- ]
-
- return (
- <>
- <AlertGroup isToast>
- {error && (
- <Alert
- isLiveRegion
- variant={AlertVariant.danger}
- title={error}
- actionClose={
- <AlertActionCloseButton
- title={error}
- variantLabel="danger alert"
- onClose={() => setError(null)}
- />
- }
- />
- )}
- </AlertGroup>
- <TableComposable aria-label="Topology List" variant="compact">
- <Thead>
- <Tr>
- <Th>Name</Th>
- <Th>Rooms</Th>
- <Th>Last Edited</Th>
- </Tr>
- </Thead>
- <Tbody>
- {topologies.map((topology) => (
- <Tr key={topology.id}>
- <Td dataLabel="Name">
- <Link href={`/projects/${projectId}/topologies/${topology.number}`}>
- {topology.name}
- </Link>
- </Td>
- <Td dataLabel="Rooms">
- {topology.rooms.length === 1 ? '1 room' : `${topology.rooms.length} rooms`}
- </Td>
- <Td dataLabel="Last Edited">{parseAndFormatDateTime(topology.updatedAt)}</Td>
- <Td isActionCell>
- <ActionsColumn items={actions(topology)} />
- </Td>
- </Tr>
- ))}
- {topologies.length === 0 && (
- <Tr>
- <Td colSpan={3}>
- <Bullseye>
- <TableEmptyState
- status={status}
- loadingTitle="Loading topologies"
- emptyTitle="No topologies"
- emptyText="You have not created any topology for this project yet. Click the New Topology button to create one."
- />
- </Bullseye>
- </Td>
- </Tr>
- )}
- </Tbody>
- </TableComposable>
- </>
- )
-}
-
-TopologyTable.propTypes = {
- 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
deleted file mode 100644
index 7f7b4171..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/RoomTable.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import { Button, Bullseye } from '@patternfly/react-core'
-import PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch } from 'react-redux'
-import { useTopology } from '../../data/topology'
-import { Tr, Th, Thead, TableComposable, Td, ActionsColumn, Tbody } from '@patternfly/react-table'
-import { deleteRoom } from '../../redux/actions/topology/room'
-import TableEmptyState from '../util/TableEmptyState'
-
-function RoomTable({ projectId, topologyId, onSelect }) {
- const dispatch = useDispatch()
- const { status, data: topology } = useTopology(projectId, topologyId)
- const onDelete = (room) => dispatch(deleteRoom(room.id))
- const actions = (room) => [
- {
- title: 'Delete room',
- onClick: () => onDelete(room),
- },
- ]
-
- return (
- <TableComposable aria-label="Room list" variant="compact">
- <Thead>
- <Tr>
- <Th>Name</Th>
- <Th>Tiles</Th>
- <Th>Racks</Th>
- </Tr>
- </Thead>
- <Tbody>
- {topology?.rooms.map((room) => {
- const tileCount = room.tiles.length
- const rackCount = room.tiles.filter((tile) => tile.rack).length
- return (
- <Tr key={room.id}>
- <Td dataLabel="Name">
- <Button variant="link" isInline onClick={() => onSelect(room)}>
- {room.name}
- </Button>
- </Td>
- <Td dataLabel="Tiles">{tileCount === 1 ? '1 tile' : `${tileCount} tiles`}</Td>
- <Td dataLabel="Racks">{rackCount === 1 ? '1 rack' : `${rackCount} racks`}</Td>
- <Td isActionCell>
- <ActionsColumn items={actions(room)} />
- </Td>
- </Tr>
- )
- })}
- {topology?.rooms.length === 0 && (
- <Tr>
- <Td colSpan={4}>
- <Bullseye>
- <TableEmptyState
- status={status}
- loadingTitle="Loading Rooms"
- emptyTitle="No rooms"
- emptyText="There are currently no rooms in this topology. Open the Floor Plan to create a room"
- />
- </Bullseye>
- </Td>
- </Tr>
- )}
- </Tbody>
- </TableComposable>
- )
-}
-
-RoomTable.propTypes = {
- projectId: PropTypes.number,
- topologyId: PropTypes.number,
- onSelect: PropTypes.func,
-}
-
-export default RoomTable
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/TopologyMap.js b/opendc-web/opendc-web-ui/src/components/topologies/TopologyMap.js
deleted file mode 100644
index ff583750..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/TopologyMap.js
+++ /dev/null
@@ -1,69 +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 React, { useState, useRef } from 'react'
-import {
- Bullseye,
- Drawer,
- DrawerContent,
- DrawerContentBody,
- EmptyState,
- EmptyStateIcon,
- Spinner,
- Title,
-} from '@patternfly/react-core'
-import MapStage from './map/MapStage'
-import Collapse from './map/controls/Collapse'
-import { useSelector } from 'react-redux'
-import TopologySidebar from './sidebar/TopologySidebar'
-
-function TopologyMap() {
- const topologyIsLoading = useSelector((state) => !state.topology.root)
- const interactionLevel = useSelector((state) => state.interactionLevel)
-
- const [isExpanded, setExpanded] = useState(true)
- const panelContent = <TopologySidebar interactionLevel={interactionLevel} onClose={() => setExpanded(false)} />
-
- const hotkeysRef = useRef()
-
- return topologyIsLoading ? (
- <Bullseye>
- <EmptyState>
- <EmptyStateIcon variant="container" component={Spinner} />
- <Title size="lg" headingLevel="h4">
- Loading Topology
- </Title>
- </EmptyState>
- </Bullseye>
- ) : (
- <Drawer isExpanded={isExpanded}>
- <DrawerContent panelContent={panelContent}>
- <DrawerContentBody style={{ position: 'relative' }}>
- <MapStage hotkeysRef={hotkeysRef} />
- <Collapse onClick={() => setExpanded(true)} />
- </DrawerContentBody>
- </DrawerContent>
- </Drawer>
- )
-}
-
-export default TopologyMap
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js b/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js
deleted file mode 100644
index f8ee4990..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/TopologyOverview.js
+++ /dev/null
@@ -1,92 +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 PropTypes from 'prop-types'
-import {
- Card,
- CardBody,
- CardTitle,
- DescriptionList,
- DescriptionListDescription,
- DescriptionListGroup,
- DescriptionListTerm,
- Grid,
- GridItem,
- Skeleton,
-} from '@patternfly/react-core'
-import React from 'react'
-import { useTopology } from '../../data/topology'
-import { parseAndFormatDateTime } from '../../util/date-time'
-import RoomTable from './RoomTable'
-
-function TopologyOverview({ projectId, topologyNumber, onSelect }) {
- const { data: topology } = useTopology(projectId, topologyNumber)
- return (
- <Grid hasGutter>
- <GridItem md={2}>
- <Card>
- <CardTitle>Details</CardTitle>
- <CardBody>
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Name</DescriptionListTerm>
- <DescriptionListDescription>
- {topology?.name ?? <Skeleton screenreaderText="Loading topology" />}
- </DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Last edited</DescriptionListTerm>
- <DescriptionListDescription>
- {topology ? (
- parseAndFormatDateTime(topology.updatedAt)
- ) : (
- <Skeleton screenreaderText="Loading topology" />
- )}
- </DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- </CardBody>
- </Card>
- </GridItem>
- <GridItem md={5}>
- <Card>
- <CardTitle>Rooms</CardTitle>
- <CardBody>
- <RoomTable
- projectId={projectId}
- topologyId={topologyNumber}
- onSelect={(room) => onSelect('room', room)}
- />
- </CardBody>
- </Card>
- </GridItem>
- </Grid>
- )
-}
-
-TopologyOverview.propTypes = {
- projectId: PropTypes.number,
- topologyNumber: PropTypes.number,
- onSelect: PropTypes.func,
-}
-
-export default TopologyOverview
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/GrayContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/GrayContainer.js
deleted file mode 100644
index ccf637e5..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/GrayContainer.js
+++ /dev/null
@@ -1,34 +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 React from 'react'
-import { useDispatch } from 'react-redux'
-import { goDownOneInteractionLevel } from '../../../redux/actions/interaction-level'
-import GrayLayer from './elements/GrayLayer'
-
-function GrayContainer() {
- const dispatch = useDispatch()
- const onClick = () => dispatch(goDownOneInteractionLevel())
- return <GrayLayer onClick={onClick} />
-}
-
-export default GrayContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/MapConstants.js b/opendc-web/opendc-web-ui/src/components/topologies/map/MapConstants.js
deleted file mode 100644
index 4c3b2757..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/MapConstants.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export const MAP_SIZE = 50
-export const TILE_SIZE_IN_PIXELS = 100
-export const TILE_SIZE_IN_METERS = 0.5
-export const MAP_SIZE_IN_PIXELS = MAP_SIZE * TILE_SIZE_IN_PIXELS
-
-export const OBJECT_MARGIN_IN_PIXELS = TILE_SIZE_IN_PIXELS / 5
-export const TILE_PLUS_MARGIN_IN_PIXELS = TILE_SIZE_IN_PIXELS / 3
-export const OBJECT_SIZE_IN_PIXELS = TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2
-
-export const GRID_LINE_WIDTH_IN_PIXELS = 2
-export const WALL_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 16
-export const OBJECT_BORDER_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 16
-export const TILE_PLUS_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 10
-
-export const RACK_FILL_ICON_WIDTH = OBJECT_SIZE_IN_PIXELS / 3
-export const RACK_FILL_ICON_OPACITY = 0.8
-
-export const MAP_MOVE_PIXELS_PER_EVENT = 20
-export const MAP_SCALE_PER_EVENT = 1.1
-export const MAP_MIN_SCALE = 0.5
-export const MAP_MAX_SCALE = 1.5
-
-export const MAX_NUM_UNITS_PER_MACHINE = 6
-export const DEFAULT_RACK_SLOT_CAPACITY = 42
-export const DEFAULT_RACK_POWER_CAPACITY = 10000
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.js b/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.js
deleted file mode 100644
index e2b626ec..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, { useRef, useState } from 'react'
-import PropTypes from 'prop-types'
-import { useHotkeys } from 'react-hotkeys-hook'
-import { Stage } from 'react-konva'
-import { MAP_MAX_SCALE, MAP_MIN_SCALE, MAP_MOVE_PIXELS_PER_EVENT, MAP_SCALE_PER_EVENT } from './MapConstants'
-import useResizeObserver from 'use-resize-observer'
-import { mapContainer } from './MapStage.module.css'
-import MapLayer from './layers/MapLayer'
-import RoomHoverLayer from './layers/RoomHoverLayer'
-import ObjectHoverLayer from './layers/ObjectHoverLayer'
-import ScaleIndicator from './controls/ScaleIndicator'
-import Toolbar from './controls/Toolbar'
-
-function MapStage({ hotkeysRef }) {
- const stageRef = useRef(null)
- const { width = 500, height = 500 } = useResizeObserver({ ref: stageRef.current?.attrs?.container })
- const [[x, y], setPos] = useState([0, 0])
- const [scale, setScale] = useState(1)
-
- const clampScale = (target) => Math.min(Math.max(target, MAP_MIN_SCALE), MAP_MAX_SCALE)
- const moveWithDelta = (deltaX, deltaY) => setPos(([x, y]) => [x + deltaX, y + deltaY])
-
- const onZoom = (e) => {
- e.evt.preventDefault()
-
- const stage = stageRef.current.getStage()
- const oldScale = scale
-
- const pointer = stage.getPointerPosition()
- const mousePointTo = {
- x: (pointer.x - x) / oldScale,
- y: (pointer.y - y) / oldScale,
- }
-
- const newScale = clampScale(e.evt.deltaY > 0 ? oldScale * MAP_SCALE_PER_EVENT : oldScale / MAP_SCALE_PER_EVENT)
-
- setScale(newScale)
- setPos([pointer.x - mousePointTo.x * newScale, pointer.y - mousePointTo.y * newScale])
- }
- const onZoomButton = (zoomIn) =>
- setScale((scale) => clampScale(zoomIn ? scale * MAP_SCALE_PER_EVENT : scale / MAP_SCALE_PER_EVENT))
- const onDragEnd = (e) => setPos([e.target.x(), e.target.y()])
- const onExport = () => {
- const download = document.createElement('a')
- download.href = stageRef.current.getStage().toDataURL()
- download.download = 'opendc-canvas-export-' + Date.now() + '.png'
- download.click()
- }
-
- useHotkeys('left, a', () => moveWithDelta(MAP_MOVE_PIXELS_PER_EVENT, 0), { element: hotkeysRef.current })
- useHotkeys('right, d', () => moveWithDelta(-MAP_MOVE_PIXELS_PER_EVENT, 0), { element: hotkeysRef.current })
- useHotkeys('up, w', () => moveWithDelta(0, MAP_MOVE_PIXELS_PER_EVENT), { element: hotkeysRef.current })
- useHotkeys('down, s', () => moveWithDelta(0, -MAP_MOVE_PIXELS_PER_EVENT), { element: hotkeysRef.current })
-
- return (
- <>
- <Stage
- className={mapContainer}
- ref={stageRef}
- onWheel={onZoom}
- onDragEnd={onDragEnd}
- draggable
- width={width}
- height={height}
- scale={{ x: scale, y: scale }}
- x={x}
- y={y}
- >
- <MapLayer />
- <RoomHoverLayer />
- <ObjectHoverLayer />
- </Stage>
- <ScaleIndicator scale={scale} />
- <Toolbar onZoom={onZoomButton} onExport={onExport} />
- </>
- )
-}
-
-MapStage.propTypes = {
- hotkeysRef: PropTypes.object.isRequired,
-}
-
-export default MapStage
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.module.css b/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.module.css
deleted file mode 100644
index 47c3dde2..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/MapStage.module.css
+++ /dev/null
@@ -1,29 +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.
- */
-
-.mapContainer {
- background-color: var(--pf-global--Color--light-200);
- position: relative;
- display: flex;
- width: 100%;
- height: 100%;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RackContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RackContainer.js
deleted file mode 100644
index 14449a91..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RackContainer.js
+++ /dev/null
@@ -1,37 +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 React from 'react'
-import { useSelector } from 'react-redux'
-import { Tile } from '../../../shapes'
-import RackGroup from './groups/RackGroup'
-
-function RackContainer({ tile }) {
- const interactionLevel = useSelector((state) => state.interactionLevel)
- return <RackGroup interactionLevel={interactionLevel} tile={tile} />
-}
-
-RackContainer.propTypes = {
- tile: Tile,
-}
-
-export default RackContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js
deleted file mode 100644
index a1ca7426..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { useSelector } from 'react-redux'
-import RackFillBar from './elements/RackFillBar'
-
-function RackSpaceFillContainer({ rackId, ...props }) {
- const fillFraction = useSelector((state) => {
- const rack = state.topology.racks[rackId]
- if (!rack) {
- return 0
- }
-
- const { machines, cpus, gpus, memories, storages } = state.topology
- let energyConsumptionTotal = 0
-
- for (const machineId of rack.machines) {
- if (!machineId) {
- continue
- }
- const machine = machines[machineId]
- machine.cpus.forEach((id) => (energyConsumptionTotal += cpus[id].energyConsumptionW))
- machine.gpus.forEach((id) => (energyConsumptionTotal += gpus[id].energyConsumptionW))
- machine.memories.forEach((id) => (energyConsumptionTotal += memories[id].energyConsumptionW))
- machine.storages.forEach((id) => (energyConsumptionTotal += storages[id].energyConsumptionW))
- }
-
- return Math.min(1, energyConsumptionTotal / rack.powerCapacityW)
- })
- return <RackFillBar {...props} type="energy" fillFraction={fillFraction} />
-}
-
-RackSpaceFillContainer.propTypes = {
- rackId: PropTypes.string.isRequired,
-}
-
-export default RackSpaceFillContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js
deleted file mode 100644
index 2039a9d3..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js
+++ /dev/null
@@ -1,42 +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 React from 'react'
-import PropTypes from 'prop-types'
-import { useSelector } from 'react-redux'
-import RackFillBar from './elements/RackFillBar'
-
-function RackSpaceFillContainer({ rackId, ...props }) {
- const rack = useSelector((state) => state.topology.racks[rackId])
-
- if (!rack) {
- return null
- }
-
- return <RackFillBar {...props} type="space" fillFraction={rack.machines.length / rack.capacity} />
-}
-
-RackSpaceFillContainer.propTypes = {
- rackId: PropTypes.string.isRequired,
-}
-
-export default RackSpaceFillContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js
deleted file mode 100644
index 76785bea..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js
+++ /dev/null
@@ -1,54 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { goFromBuildingToRoom } from '../../../redux/actions/interaction-level'
-import RoomGroup from './groups/RoomGroup'
-
-function RoomContainer({ roomId, ...props }) {
- const interactionLevel = useSelector((state) => state.interactionLevel)
- const currentRoomInConstruction = useSelector((state) => state.construction.currentRoomInConstruction)
- const room = useSelector((state) => state.topology.rooms[roomId])
- const dispatch = useDispatch()
-
- if (!room) {
- return null
- }
-
- return (
- <RoomGroup
- {...props}
- interactionLevel={interactionLevel}
- currentRoomInConstruction={currentRoomInConstruction}
- room={room}
- onClick={() => dispatch(goFromBuildingToRoom(roomId))}
- />
- )
-}
-
-RoomContainer.propTypes = {
- roomId: PropTypes.string,
-}
-
-export default RoomContainer
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
deleted file mode 100644
index 0788b894..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js
+++ /dev/null
@@ -1,50 +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 React from 'react'
-import PropTypes from 'prop-types'
-import { useDispatch, useSelector } from 'react-redux'
-import { goFromRoomToRack } from '../../../redux/actions/interaction-level'
-import TileGroup from './groups/TileGroup'
-
-function TileContainer({ tileId, ...props }) {
- const interactionLevel = useSelector((state) => state.interactionLevel)
- const dispatch = useDispatch()
- const tile = useSelector((state) => state.topology.tiles[tileId])
-
- if (!tile) {
- return null
- }
-
- const onClick = (tile) => {
- if (tile.rack) {
- dispatch(goFromRoomToRack(tile.id))
- }
- }
- return <TileGroup {...props} onClick={onClick} tile={tile} interactionLevel={interactionLevel} />
-}
-
-TileContainer.propTypes = {
- tileId: PropTypes.string.isRequired,
-}
-
-export default TileContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/TopologyContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/TopologyContainer.js
deleted file mode 100644
index cc0d46b3..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/TopologyContainer.js
+++ /dev/null
@@ -1,34 +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 React from 'react'
-import { useSelector } from 'react-redux'
-import TopologyGroup from './groups/TopologyGroup'
-
-function TopologyContainer() {
- const topology = useSelector((state) => state.topology.root)
- const interactionLevel = useSelector((state) => state.interactionLevel)
-
- return <TopologyGroup topology={topology} interactionLevel={interactionLevel} />
-}
-
-export default TopologyContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js
deleted file mode 100644
index 106d8d3d..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.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 React from 'react'
-import PropTypes from 'prop-types'
-import { useSelector } from 'react-redux'
-import WallGroup from './groups/WallGroup'
-
-function WallContainer({ roomId, ...props }) {
- const tiles = useSelector((state) => {
- return state.topology.rooms[roomId]?.tiles.map((tileId) => state.topology.tiles[tileId]) ?? []
- })
- return <WallGroup {...props} tiles={tiles} />
-}
-
-WallContainer.propTypes = {
- roomId: PropTypes.string.isRequired,
-}
-
-export default WallContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.js b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.js
deleted file mode 100644
index 931ded94..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.js
+++ /dev/null
@@ -1,42 +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 PropTypes from 'prop-types'
-import { ChevronLeftIcon } from '@patternfly/react-icons'
-import { collapseContainer } from './Collapse.module.css'
-import { Button } from '@patternfly/react-core'
-
-function Collapse({ onClick }) {
- return (
- <div className={collapseContainer}>
- <Button variant="tertiary" onClick={onClick}>
- <ChevronLeftIcon />
- </Button>
- </div>
- )
-}
-
-Collapse.propTypes = {
- onClick: PropTypes.func,
-}
-
-export default Collapse
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.module.css b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.module.css
deleted file mode 100644
index 70fd465f..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Collapse.module.css
+++ /dev/null
@@ -1,55 +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.
- */
-
-.collapseContainer {
- position: absolute;
- right: var(--pf-global--spacer--xs);
- top: 0;
- bottom: 10%;
- margin: auto 0;
- height: 50px;
-}
-
-.collapseContainer > button:global(.pf-m-tertiary) {
- height: 100%;
- padding: 2px;
-
- margin-right: var(--pf-global--spacer--xs);
- margin-top: var(--pf-global--spacer--xs);
- background-color: var(--pf-global--BackgroundColor--100);
- border: none;
- border-radius: var(--pf-global--BorderRadius--sm);
- box-shadow: var(--pf-global--BoxShadow--sm);
-}
-
-.collapseContainer > button:global(.pf-m-tertiary):not(:global(.pf-m-disabled)) {
- background-color: var(--pf-global--BackgroundColor--100);
-}
-
-.collapseContainer > button:global(.pf-m-tertiary):after {
- display: none;
-}
-
-.collapseContainer > button:global(.pf-m-tertiary):hover {
- border: none;
- box-shadow: var(--pf-global--BoxShadow--md);
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.js b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.js
deleted file mode 100644
index 3ec893fb..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { TILE_SIZE_IN_METERS, TILE_SIZE_IN_PIXELS } from '../MapConstants'
-import { scaleIndicator } from './ScaleIndicator.module.css'
-
-function ScaleIndicator({ scale }) {
- return (
- <div className={scaleIndicator} style={{ width: TILE_SIZE_IN_PIXELS * scale }}>
- {TILE_SIZE_IN_METERS}m
- </div>
- )
-}
-
-ScaleIndicator.propTypes = {
- scale: PropTypes.number.isRequired,
-}
-
-export default ScaleIndicator
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.module.css b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.module.css
deleted file mode 100644
index f19e0ff2..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/ScaleIndicator.module.css
+++ /dev/null
@@ -1,10 +0,0 @@
-.scaleIndicator {
- position: absolute;
- right: 10px;
- bottom: 10px;
- z-index: 50;
-
- border: solid 2px #212529;
- border-top: none;
- border-left: none;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js
deleted file mode 100644
index 00aaf3e1..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { control, toolBar } from './Toolbar.module.css'
-import { Button } from '@patternfly/react-core'
-import { SearchPlusIcon, SearchMinusIcon, CameraIcon } from '@patternfly/react-icons'
-
-function Toolbar({ onZoom, onExport }) {
- return (
- <div className={toolBar}>
- <Button variant="tertiary" title="Zoom in" onClick={() => onZoom(true)} className={control}>
- <SearchPlusIcon />
- </Button>
- <Button variant="tertiary" title="Zoom out" onClick={() => onZoom(false)} className={control}>
- <SearchMinusIcon />
- </Button>
- <Button
- variant="tertiary"
- title="Export Canvas to PNG Image"
- onClick={() => onExport()}
- className={control}
- >
- <CameraIcon />
- </Button>
- </div>
- )
-}
-
-Toolbar.propTypes = {
- onZoom: PropTypes.func,
- onExport: PropTypes.func,
-}
-
-export default Toolbar
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.module.css b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.module.css
deleted file mode 100644
index 007389da..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.module.css
+++ /dev/null
@@ -1,27 +0,0 @@
-.toolBar {
- position: absolute;
- bottom: var(--pf-global--spacer--md);
- left: var(--pf-global--spacer--xl);
-}
-
-.control:global(.pf-m-tertiary) {
- margin-right: var(--pf-global--spacer--xs);
- margin-top: var(--pf-global--spacer--xs);
- background-color: var(--pf-global--BackgroundColor--100);
- border: none;
- border-radius: var(--pf-global--BorderRadius--sm);
- box-shadow: var(--pf-global--BoxShadow--sm);
-}
-
-.control:global(.pf-m-tertiary):not(:global(.pf-m-disabled)) {
- background-color: var(--pf-global--BackgroundColor--100);
-}
-
-.control:global(.pf-m-tertiary):after {
- display: none;
-}
-
-.control:global(.pf-m-tertiary):hover {
- border: none;
- box-shadow: var(--pf-global--BoxShadow--md);
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/Backdrop.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/Backdrop.js
deleted file mode 100644
index 93037b51..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/Backdrop.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from 'react'
-import { Rect } from 'react-konva'
-import { BACKDROP_COLOR } from '../../../../util/colors'
-import { MAP_SIZE_IN_PIXELS } from '../MapConstants'
-
-function Backdrop() {
- return <Rect x={0} y={0} width={MAP_SIZE_IN_PIXELS} height={MAP_SIZE_IN_PIXELS} fill={BACKDROP_COLOR} />
-}
-
-export default Backdrop
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/GrayLayer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/GrayLayer.js
deleted file mode 100644
index 08c687f6..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/GrayLayer.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Rect } from 'react-konva'
-import { GRAYED_OUT_AREA_COLOR } from '../../../../util/colors'
-import { MAP_SIZE_IN_PIXELS } from '../MapConstants'
-
-function GrayLayer({ onClick }) {
- return (
- <Rect
- x={0}
- y={0}
- width={MAP_SIZE_IN_PIXELS}
- height={MAP_SIZE_IN_PIXELS}
- fill={GRAYED_OUT_AREA_COLOR}
- onClick={onClick}
- />
- )
-}
-
-GrayLayer.propTypes = {
- onClick: PropTypes.func,
-}
-
-export default GrayLayer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/HoverTile.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/HoverTile.js
deleted file mode 100644
index 20c2c6d1..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/HoverTile.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Rect } from 'react-konva'
-import { ROOM_HOVER_INVALID_COLOR, ROOM_HOVER_VALID_COLOR } from '../../../../util/colors'
-import { TILE_SIZE_IN_PIXELS } from '../MapConstants'
-
-function HoverTile({ x, y, isValid, scale = 1, onClick }) {
- return (
- <Rect
- x={x}
- y={y}
- scaleX={scale}
- scaleY={scale}
- width={TILE_SIZE_IN_PIXELS}
- height={TILE_SIZE_IN_PIXELS}
- fill={isValid ? ROOM_HOVER_VALID_COLOR : ROOM_HOVER_INVALID_COLOR}
- onClick={onClick}
- />
- )
-}
-
-HoverTile.propTypes = {
- x: PropTypes.number.isRequired,
- y: PropTypes.number.isRequired,
- isValid: PropTypes.bool.isRequired,
- scale: PropTypes.number,
- onClick: PropTypes.func.isRequired,
-}
-
-export default HoverTile
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
deleted file mode 100644
index fdae53f2..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/ImageComponent.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useEffect, useState } from 'react'
-import { Image } from 'react-konva'
-
-const imageCaches = {}
-
-function ImageComponent({ src, x, y, width, height, opacity }) {
- const [image, setImage] = useState(null)
-
- useEffect(() => {
- if (imageCaches[src]) {
- setImage(imageCaches[src])
- return
- }
-
- const image = new window.Image()
- image.src = src
- image.onload = () => {
- setImage(image)
- imageCaches[src] = image
- }
- }, [src])
-
- // eslint-disable-next-line jsx-a11y/alt-text
- return <Image image={image} x={x} y={y} width={width} height={height} opacity={opacity} />
-}
-
-ImageComponent.propTypes = {
- src: PropTypes.string.isRequired,
- x: PropTypes.number.isRequired,
- y: PropTypes.number.isRequired,
- width: PropTypes.number.isRequired,
- height: PropTypes.number.isRequired,
- opacity: PropTypes.number.isRequired,
-}
-
-export default ImageComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RackFillBar.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RackFillBar.js
deleted file mode 100644
index aa284944..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RackFillBar.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Group, Rect } from 'react-konva'
-import {
- RACK_ENERGY_BAR_BACKGROUND_COLOR,
- RACK_ENERGY_BAR_FILL_COLOR,
- RACK_SPACE_BAR_BACKGROUND_COLOR,
- RACK_SPACE_BAR_FILL_COLOR,
-} from '../../../../util/colors'
-import {
- OBJECT_BORDER_WIDTH_IN_PIXELS,
- OBJECT_MARGIN_IN_PIXELS,
- RACK_FILL_ICON_OPACITY,
- RACK_FILL_ICON_WIDTH,
- TILE_SIZE_IN_PIXELS,
-} from '../MapConstants'
-import ImageComponent from './ImageComponent'
-
-function RackFillBar({ positionX, positionY, type, fillFraction }) {
- const halfOfObjectBorderWidth = OBJECT_BORDER_WIDTH_IN_PIXELS / 2
- const x =
- positionX * TILE_SIZE_IN_PIXELS +
- OBJECT_MARGIN_IN_PIXELS +
- (type === 'space' ? halfOfObjectBorderWidth : 0.5 * (TILE_SIZE_IN_PIXELS - 2 * OBJECT_MARGIN_IN_PIXELS))
- const startY = positionY * TILE_SIZE_IN_PIXELS + OBJECT_MARGIN_IN_PIXELS + halfOfObjectBorderWidth
- const width = 0.5 * (TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2) - halfOfObjectBorderWidth
- const fullHeight = TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2 - OBJECT_BORDER_WIDTH_IN_PIXELS
-
- const fractionHeight = fillFraction * fullHeight
- const fractionY =
- (positionY + 1) * TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS - halfOfObjectBorderWidth - fractionHeight
-
- return (
- <Group>
- <Rect
- x={x}
- y={startY}
- width={width}
- height={fullHeight}
- fill={type === 'space' ? RACK_SPACE_BAR_BACKGROUND_COLOR : RACK_ENERGY_BAR_BACKGROUND_COLOR}
- />
- <Rect
- x={x}
- y={fractionY}
- width={width}
- height={fractionHeight}
- fill={type === 'space' ? RACK_SPACE_BAR_FILL_COLOR : RACK_ENERGY_BAR_FILL_COLOR}
- />
- <ImageComponent
- src={'/img/topology/rack-' + type + '-icon.png'}
- x={x + width * 0.5 - RACK_FILL_ICON_WIDTH * 0.5}
- y={startY + fullHeight * 0.5 - RACK_FILL_ICON_WIDTH * 0.5}
- width={RACK_FILL_ICON_WIDTH}
- height={RACK_FILL_ICON_WIDTH}
- opacity={RACK_FILL_ICON_OPACITY}
- />
- </Group>
- )
-}
-
-RackFillBar.propTypes = {
- positionX: PropTypes.number.isRequired,
- positionY: PropTypes.number.isRequired,
- type: PropTypes.string.isRequired,
- fillFraction: PropTypes.number.isRequired,
-}
-
-export default RackFillBar
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RoomTile.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RoomTile.js
deleted file mode 100644
index e7329dc0..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/RoomTile.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Rect } from 'react-konva'
-import { Tile } from '../../../../shapes'
-import { TILE_SIZE_IN_PIXELS } from '../MapConstants'
-
-function RoomTile({ tile, color }) {
- return (
- <Rect
- x={tile.positionX * TILE_SIZE_IN_PIXELS}
- y={tile.positionY * TILE_SIZE_IN_PIXELS}
- width={TILE_SIZE_IN_PIXELS}
- height={TILE_SIZE_IN_PIXELS}
- fill={color}
- />
- )
-}
-
-RoomTile.propTypes = {
- tile: Tile,
- color: PropTypes.string,
-}
-
-export default RoomTile
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TileObject.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TileObject.js
deleted file mode 100644
index 3211f187..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TileObject.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Rect } from 'react-konva'
-import { OBJECT_BORDER_COLOR } from '../../../../util/colors'
-import { OBJECT_BORDER_WIDTH_IN_PIXELS, OBJECT_MARGIN_IN_PIXELS, TILE_SIZE_IN_PIXELS } from '../MapConstants'
-
-function TileObject({ positionX, positionY, color }) {
- return (
- <Rect
- x={positionX * TILE_SIZE_IN_PIXELS + OBJECT_MARGIN_IN_PIXELS}
- y={positionY * TILE_SIZE_IN_PIXELS + OBJECT_MARGIN_IN_PIXELS}
- width={TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2}
- height={TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2}
- fill={color}
- stroke={OBJECT_BORDER_COLOR}
- strokeWidth={OBJECT_BORDER_WIDTH_IN_PIXELS}
- />
- )
-}
-
-TileObject.propTypes = {
- positionX: PropTypes.number.isRequired,
- positionY: PropTypes.number.isRequired,
- color: PropTypes.string.isRequired,
-}
-
-export default TileObject
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TilePlusIcon.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TilePlusIcon.js
deleted file mode 100644
index 186c2b3a..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/TilePlusIcon.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Group, Line } from 'react-konva'
-import { TILE_PLUS_COLOR } from '../../../../util/colors'
-import { TILE_PLUS_MARGIN_IN_PIXELS, TILE_PLUS_WIDTH_IN_PIXELS, TILE_SIZE_IN_PIXELS } from '../MapConstants'
-
-function TilePlusIcon({ x, y, scale = 1 }) {
- const linePoints = [
- [
- x + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- y + TILE_PLUS_MARGIN_IN_PIXELS * scale,
- x + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- y + TILE_SIZE_IN_PIXELS * scale - TILE_PLUS_MARGIN_IN_PIXELS * scale,
- ],
- [
- x + TILE_PLUS_MARGIN_IN_PIXELS * scale,
- y + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- x + TILE_SIZE_IN_PIXELS * scale - TILE_PLUS_MARGIN_IN_PIXELS * scale,
- y + 0.5 * TILE_SIZE_IN_PIXELS * scale,
- ],
- ]
- return (
- <Group>
- {linePoints.map((points, index) => (
- <Line
- key={index}
- points={points}
- lineCap="round"
- stroke={TILE_PLUS_COLOR}
- strokeWidth={TILE_PLUS_WIDTH_IN_PIXELS * scale}
- listening={false}
- />
- ))}
- </Group>
- )
-}
-
-TilePlusIcon.propTypes = {
- x: PropTypes.number,
- y: PropTypes.number,
- scale: PropTypes.number,
-}
-
-export default TilePlusIcon
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/WallSegment.js b/opendc-web/opendc-web-ui/src/components/topologies/map/elements/WallSegment.js
deleted file mode 100644
index 4f18813e..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/elements/WallSegment.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react'
-import { Line } from 'react-konva'
-import { WallSegment as WallSegmentShape } from '../../../../shapes'
-import { WALL_COLOR } from '../../../../util/colors'
-import { TILE_SIZE_IN_PIXELS, WALL_WIDTH_IN_PIXELS } from '../MapConstants'
-
-function WallSegment({ wallSegment }) {
- let points
- if (wallSegment.isHorizontal) {
- points = [
- wallSegment.startPosX * TILE_SIZE_IN_PIXELS,
- wallSegment.startPosY * TILE_SIZE_IN_PIXELS,
- (wallSegment.startPosX + wallSegment.length) * TILE_SIZE_IN_PIXELS,
- wallSegment.startPosY * TILE_SIZE_IN_PIXELS,
- ]
- } else {
- points = [
- wallSegment.startPosX * TILE_SIZE_IN_PIXELS,
- wallSegment.startPosY * TILE_SIZE_IN_PIXELS,
- wallSegment.startPosX * TILE_SIZE_IN_PIXELS,
- (wallSegment.startPosY + wallSegment.length) * TILE_SIZE_IN_PIXELS,
- ]
- }
-
- return <Line points={points} lineCap="round" stroke={WALL_COLOR} strokeWidth={WALL_WIDTH_IN_PIXELS} />
-}
-
-WallSegment.propTypes = {
- wallSegment: WallSegmentShape,
-}
-
-export default WallSegment
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/GridGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/GridGroup.js
deleted file mode 100644
index d66a18de..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/GridGroup.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-import { Group, Line } from 'react-konva'
-import { GRID_COLOR } from '../../../../util/colors'
-import { GRID_LINE_WIDTH_IN_PIXELS, MAP_SIZE, MAP_SIZE_IN_PIXELS, TILE_SIZE_IN_PIXELS } from '../MapConstants'
-
-const MAP_COORDINATE_ENTRIES = Array.from(new Array(MAP_SIZE), (x, i) => i)
-const HORIZONTAL_POINT_PAIRS = MAP_COORDINATE_ENTRIES.map((index) => [
- 0,
- index * TILE_SIZE_IN_PIXELS,
- MAP_SIZE_IN_PIXELS,
- index * TILE_SIZE_IN_PIXELS,
-])
-const VERTICAL_POINT_PAIRS = MAP_COORDINATE_ENTRIES.map((index) => [
- index * TILE_SIZE_IN_PIXELS,
- 0,
- index * TILE_SIZE_IN_PIXELS,
- MAP_SIZE_IN_PIXELS,
-])
-
-function GridGroup() {
- return (
- <Group>
- {HORIZONTAL_POINT_PAIRS.concat(VERTICAL_POINT_PAIRS).map((points, index) => (
- <Line
- key={index}
- points={points}
- stroke={GRID_COLOR}
- strokeWidth={GRID_LINE_WIDTH_IN_PIXELS}
- listening={false}
- />
- ))}
- </Group>
- )
-}
-
-export default GridGroup
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
deleted file mode 100644
index ed942661..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react'
-import { Group } from 'react-konva'
-import { Tile } from '../../../../shapes'
-import { RACK_BACKGROUND_COLOR } from '../../../../util/colors'
-import TileObject from '../elements/TileObject'
-import RackSpaceFillContainer from '../RackSpaceFillContainer'
-import RackEnergyFillContainer from '../RackEnergyFillContainer'
-
-function RackGroup({ tile }) {
- return (
- <Group>
- <TileObject positionX={tile.positionX} positionY={tile.positionY} color={RACK_BACKGROUND_COLOR} />
- <Group>
- <RackSpaceFillContainer rackId={tile.rack} positionX={tile.positionX} positionY={tile.positionY} />
- <RackEnergyFillContainer rackId={tile.rack} positionX={tile.positionX} positionY={tile.positionY} />
- </Group>
- </Group>
- )
-}
-
-RackGroup.propTypes = {
- tile: Tile,
-}
-
-export default RackGroup
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
deleted file mode 100644
index 3f8b3089..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RoomGroup.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Group } from 'react-konva'
-import { InteractionLevel, Room } from '../../../../shapes'
-import GrayContainer from '../GrayContainer'
-import TileContainer from '../TileContainer'
-import WallContainer from '../WallContainer'
-
-function RoomGroup({ room, interactionLevel, currentRoomInConstruction, onClick }) {
- if (currentRoomInConstruction === room.id) {
- return (
- <Group onClick={onClick}>
- {room.tiles.map((tileId) => (
- <TileContainer key={tileId} tileId={tileId} newTile={true} />
- ))}
- </Group>
- )
- }
-
- return (
- <Group onClick={onClick}>
- {(() => {
- if (
- (interactionLevel.mode === 'RACK' || interactionLevel.mode === 'MACHINE') &&
- interactionLevel.roomId === room.id
- ) {
- return [
- room.tiles
- .filter((tileId) => tileId !== interactionLevel.tileId)
- .map((tileId) => <TileContainer key={tileId} tileId={tileId} />),
- <GrayContainer key={-1} />,
- room.tiles
- .filter((tileId) => tileId === interactionLevel.tileId)
- .map((tileId) => <TileContainer key={tileId} tileId={tileId} />),
- ]
- } else {
- return room.tiles.map((tileId) => <TileContainer key={tileId} tileId={tileId} />)
- }
- })()}
- <WallContainer roomId={room.id} />
- </Group>
- )
-}
-
-RoomGroup.propTypes = {
- room: Room,
- interactionLevel: InteractionLevel,
- currentRoomInConstruction: PropTypes.string,
- onClick: PropTypes.func,
-}
-
-export default RoomGroup
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TileGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TileGroup.js
deleted file mode 100644
index f2084017..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TileGroup.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Group } from 'react-konva'
-import { Tile } from '../../../../shapes'
-import { ROOM_DEFAULT_COLOR, ROOM_IN_CONSTRUCTION_COLOR } from '../../../../util/colors'
-import RoomTile from '../elements/RoomTile'
-import RackContainer from '../RackContainer'
-
-function TileGroup({ tile, newTile, onClick }) {
- let tileObject
- if (tile.rack) {
- tileObject = <RackContainer tile={tile} />
- } else {
- tileObject = null
- }
-
- let color = ROOM_DEFAULT_COLOR
- if (newTile) {
- color = ROOM_IN_CONSTRUCTION_COLOR
- }
-
- return (
- <Group onClick={() => onClick(tile)}>
- <RoomTile tile={tile} color={color} />
- {tileObject}
- </Group>
- )
-}
-
-TileGroup.propTypes = {
- tile: Tile,
- newTile: PropTypes.bool,
- onClick: PropTypes.func,
-}
-
-export default TileGroup
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TopologyGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TopologyGroup.js
deleted file mode 100644
index 011dcf34..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/TopologyGroup.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react'
-import { Group } from 'react-konva'
-import { InteractionLevel, Topology } from '../../../../shapes'
-import RoomContainer from '../RoomContainer'
-import GrayContainer from '../GrayContainer'
-
-function TopologyGroup({ topology, interactionLevel }) {
- if (!topology) {
- return <Group />
- }
-
- if (interactionLevel.mode === 'BUILDING') {
- return (
- <Group>
- {topology.rooms.map((roomId) => (
- <RoomContainer key={roomId} roomId={roomId} />
- ))}
- </Group>
- )
- }
-
- return (
- <Group>
- {topology.rooms
- .filter((roomId) => roomId !== interactionLevel.roomId)
- .map((roomId) => (
- <RoomContainer key={roomId} roomId={roomId} />
- ))}
- {interactionLevel.mode === 'ROOM' ? <GrayContainer /> : null}
- {topology.rooms
- .filter((roomId) => roomId === interactionLevel.roomId)
- .map((roomId) => (
- <RoomContainer key={roomId} roomId={roomId} />
- ))}
- </Group>
- )
-}
-
-TopologyGroup.propTypes = {
- topology: Topology,
- interactionLevel: InteractionLevel,
-}
-
-export default TopologyGroup
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/WallGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/WallGroup.js
deleted file mode 100644
index 6cbd1cd0..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/WallGroup.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Group } from 'react-konva'
-import { Tile } from '../../../../shapes'
-import { deriveWallLocations } from '../../../../util/tile-calculations'
-import WallSegment from '../elements/WallSegment'
-
-function WallGroup({ tiles }) {
- return (
- <Group>
- {deriveWallLocations(tiles).map((wallSegment, index) => (
- <WallSegment key={index} wallSegment={wallSegment} />
- ))}
- </Group>
- )
-}
-
-WallGroup.propTypes = {
- tiles: PropTypes.arrayOf(Tile).isRequired,
-}
-
-export default WallGroup
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/HoverLayerComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/map/layers/HoverLayerComponent.js
deleted file mode 100644
index d7e0c56a..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/HoverLayerComponent.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useMemo, useState } from 'react'
-import { Layer } from 'react-konva/lib/ReactKonva'
-import HoverTile from '../elements/HoverTile'
-import { TILE_SIZE_IN_PIXELS } from '../MapConstants'
-import { useEffectRef } from '../../../../util/effect-ref'
-
-function HoverLayerComponent({ isEnabled, isValid, onClick, children }) {
- const [[mouseWorldX, mouseWorldY], setPos] = useState([0, 0])
-
- const layerRef = useEffectRef((layer) => {
- if (!layer) {
- return
- }
-
- const stage = layer.getStage()
-
- stage.on('mousemove.hover', () => {
- // Transform used to convert mouse coordinates to world coordinates
- const transform = stage.getAbsoluteTransform().copy()
- transform.invert()
-
- const { x, y } = transform.point(stage.getPointerPosition())
- setPos([x, y])
- })
- return () => stage.off('mousemove.hover')
- })
-
- const gridX = Math.floor(mouseWorldX / TILE_SIZE_IN_PIXELS)
- const gridY = Math.floor(mouseWorldY / TILE_SIZE_IN_PIXELS)
- const valid = useMemo(() => isEnabled && isValid(gridX, gridY), [isEnabled, isValid, gridX, gridY])
-
- if (!isEnabled) {
- return <Layer />
- }
-
- const x = gridX * TILE_SIZE_IN_PIXELS
- const y = gridY * TILE_SIZE_IN_PIXELS
-
- return (
- <Layer opacity={0.2} ref={layerRef}>
- <HoverTile x={x} y={y} isValid={valid} onClick={() => (valid ? onClick(gridX, gridY) : undefined)} />
- {children ? React.cloneElement(children, { x, y, scale: 1 }) : undefined}
- </Layer>
- )
-}
-
-HoverLayerComponent.propTypes = {
- isEnabled: PropTypes.bool.isRequired,
- isValid: PropTypes.func.isRequired,
- onClick: PropTypes.func.isRequired,
- children: PropTypes.node,
-}
-
-export default HoverLayerComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/MapLayer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/layers/MapLayer.js
deleted file mode 100644
index c902532b..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/MapLayer.js
+++ /dev/null
@@ -1,41 +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 React from 'react'
-import { Group, Layer } from 'react-konva'
-import Backdrop from '../elements/Backdrop'
-import TopologyContainer from '../TopologyContainer'
-import GridGroup from '../groups/GridGroup'
-
-function MapLayer() {
- return (
- <Layer>
- <Group>
- <Backdrop />
- <TopologyContainer />
- <GridGroup />
- </Group>
- </Layer>
- )
-}
-
-export default MapLayer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/ObjectHoverLayer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/layers/ObjectHoverLayer.js
deleted file mode 100644
index 5e741a3b..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/ObjectHoverLayer.js
+++ /dev/null
@@ -1,51 +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 React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { addRackToTile } from '../../../../redux/actions/topology/room'
-import { findTileWithPosition } from '../../../../util/tile-calculations'
-import HoverLayerComponent from './HoverLayerComponent'
-import TilePlusIcon from '../elements/TilePlusIcon'
-
-export default function ObjectHoverLayer() {
- const isEnabled = useSelector((state) => state.construction.inRackConstructionMode)
- const isValid = useSelector((state) => (x, y) => {
- if (state.interactionLevel.mode !== 'ROOM') {
- return false
- }
-
- const currentRoom = state.topology.rooms[state.interactionLevel.roomId]
- const tiles = currentRoom.tiles.map((tileId) => state.topology.tiles[tileId])
- const tile = findTileWithPosition(tiles, x, y)
-
- return !(tile === null || tile.rack)
- })
-
- const dispatch = useDispatch()
- const onClick = (x, y) => dispatch(addRackToTile(x, y))
- return (
- <HoverLayerComponent onClick={onClick} isEnabled={isEnabled} isValid={isValid}>
- <TilePlusIcon />
- </HoverLayerComponent>
- )
-}
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
deleted file mode 100644
index b9cfcaf4..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/layers/RoomHoverLayer.js
+++ /dev/null
@@ -1,59 +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 React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { toggleTileAtLocation } from '../../../../redux/actions/topology/building'
-import {
- deriveValidNextTilePositions,
- findPositionInPositions,
- findPositionInRooms,
-} from '../../../../util/tile-calculations'
-import HoverLayerComponent from './HoverLayerComponent'
-
-export default function RoomHoverLayer() {
- const dispatch = useDispatch()
- const onClick = (x, y) => dispatch(toggleTileAtLocation(x, y))
- const isEnabled = useSelector((state) => state.construction.currentRoomInConstruction !== '-1')
- const isValid = useSelector((state) => (x, y) => {
- const newRoom = { ...state.topology.rooms[state.construction.currentRoomInConstruction] }
- const oldRooms = Object.keys(state.topology.rooms)
- .map((id) => ({ ...state.topology.rooms[id] }))
- .filter(
- (room) =>
- state.topology.root.rooms.indexOf(room.id) !== -1 &&
- room.id !== state.construction.currentRoomInConstruction
- )
-
- ;[...oldRooms, newRoom].forEach((room) => {
- room.tiles = room.tiles.map((tileId) => state.topology.tiles[tileId])
- })
- if (newRoom.tiles.length === 0) {
- return findPositionInRooms(oldRooms, x, y) === -1
- }
-
- const validNextPositions = deriveValidNextTilePositions(oldRooms, newRoom.tiles)
- return findPositionInPositions(validNextPositions, x, y) !== -1
- })
-
- return <HoverLayerComponent onClick={onClick} isEnabled={isEnabled} isValid={isValid} />
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/NameComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/NameComponent.js
deleted file mode 100644
index ececd07b..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/NameComponent.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useRef, useState } from 'react'
-import { Button, TextInput } from '@patternfly/react-core'
-import { PencilAltIcon, CheckIcon, TimesIcon } from '@patternfly/react-icons'
-
-function NameComponent({ name, onEdit }) {
- const [isEditing, setEditing] = useState(false)
- const nameInput = useRef(null)
-
- const onCancel = () => {
- nameInput.current.value = name
- setEditing(false)
- }
-
- const onSubmit = (event) => {
- if (event) {
- event.preventDefault()
- }
-
- const name = nameInput.current.value
- if (name) {
- onEdit(name)
- }
-
- setEditing(false)
- }
-
- return (
- <form
- className={`pf-c-inline-edit ${isEditing ? 'pf-m-inline-editable' : ''} pf-u-display-inline-block`}
- onSubmit={onSubmit}
- >
- <div className="pf-c-inline-edit__group">
- <div className="pf-c-inline-edit__value" id="single-inline-edit-example-label">
- {name}
- </div>
- <div className="pf-c-inline-edit__action pf-m-enable-editable">
- <Button className="pf-u-py-0" variant="plain" aria-label="Edit" onClick={() => setEditing(true)}>
- <PencilAltIcon />
- </Button>
- </div>
- </div>
- <div className="pf-c-inline-edit__group">
- <div className="pf-c-inline-edit__input">
- <TextInput type="text" defaultValue={name} ref={nameInput} aria-label="Editable text input" />
- </div>
- <div className="pf-c-inline-edit__group pf-m-action-group pf-m-icon-group">
- <div className="pf-c-inline-edit__action pf-m-valid">
- <Button className="pf-u-py-0" variant="plain" aria-label="Save edits" onClick={onSubmit}>
- <CheckIcon />
- </Button>
- </div>
- <div className="pf-c-inline-edit__action">
- <Button className="pf-u-py-0" variant="plain" aria-label="Cancel edits" onClick={onCancel}>
- <TimesIcon />
- </Button>
- </div>
- </div>
- </div>
- </form>
- )
-}
-
-NameComponent.propTypes = {
- name: PropTypes.string,
- onEdit: PropTypes.func,
-}
-
-export default NameComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.js
deleted file mode 100644
index 5aaa7834..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { InteractionLevel } from '../../../shapes'
-import BuildingSidebar from './building/BuildingSidebar'
-import {
- Button,
- DrawerActions,
- DrawerCloseButton,
- DrawerHead,
- DrawerPanelBody,
- DrawerPanelContent,
- Flex,
- Title,
-} from '@patternfly/react-core'
-import { AngleLeftIcon } from '@patternfly/react-icons'
-import { useDispatch } from 'react-redux'
-import { backButton } from './TopologySidebar.module.css'
-import RoomSidebar from './room/RoomSidebar'
-import RackSidebar from './rack/RackSidebar'
-import MachineSidebar from './machine/MachineSidebar'
-import { goDownOneInteractionLevel } from '../../../redux/actions/interaction-level'
-
-const name = {
- BUILDING: 'Building',
- ROOM: 'Room',
- RACK: 'Rack',
- MACHINE: 'Machine',
-}
-
-function TopologySidebar({ interactionLevel, onClose }) {
- let sidebarContent
-
- switch (interactionLevel.mode) {
- case 'BUILDING':
- sidebarContent = <BuildingSidebar />
- break
- case 'ROOM':
- sidebarContent = <RoomSidebar roomId={interactionLevel.roomId} />
- break
- case 'RACK':
- sidebarContent = <RackSidebar tileId={interactionLevel.tileId} />
- break
- case 'MACHINE':
- sidebarContent = <MachineSidebar tileId={interactionLevel.tileId} position={interactionLevel.position} />
- break
- default:
- sidebarContent = 'Missing Content'
- }
-
- const dispatch = useDispatch()
- const onClick = () => dispatch(goDownOneInteractionLevel())
-
- return (
- <DrawerPanelContent isResizable defaultSize="450px" minSize="400px">
- <DrawerHead>
- <Flex>
- <Button
- variant="tertiary"
- isSmall
- className={backButton}
- onClick={interactionLevel.mode === 'BUILDING' ? onClose : onClick}
- >
- <AngleLeftIcon />
- </Button>
- <Title className="pf-u-align-self-center" headingLevel="h1">
- {name[interactionLevel.mode]}
- </Title>
- </Flex>
- <DrawerActions>
- <DrawerCloseButton onClose={onClose} />
- </DrawerActions>
- </DrawerHead>
- <DrawerPanelBody>{sidebarContent}</DrawerPanelBody>
- </DrawerPanelContent>
- )
-}
-
-TopologySidebar.propTypes = {
- interactionLevel: InteractionLevel,
- onClose: PropTypes.func,
-}
-
-export default TopologySidebar
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.module.css b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.module.css
deleted file mode 100644
index 3853c625..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/TopologySidebar.module.css
+++ /dev/null
@@ -1,35 +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.
- */
-
-.backButton:global(.pf-c-button) {
- align-self: center;
- --pf-c-button--after--BorderColor: var(--pf-global--BorderColor--light-100);
- color: var(--pf-global--Color--400);
-
- --pf-c-button--PaddingRight: var(--pf-global--spacer--sm);
- --pf-c-button--PaddingLeft: var(--pf-global--spacer--sm);
-}
-
-.backButton:hover,
-.backButton:global(.pf-c-button):focus {
- --pf-c-button--after--BorderColor: var(--pf-global--BorderColor--100);
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/BuildingSidebar.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/BuildingSidebar.js
deleted file mode 100644
index 5fcd46be..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/BuildingSidebar.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react'
-import NewRoomConstructionContainer from './NewRoomConstructionContainer'
-
-function BuildingSidebar() {
- return <NewRoomConstructionContainer />
-}
-
-export default BuildingSidebar
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionComponent.js
deleted file mode 100644
index 9fc85d0c..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionComponent.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Button, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from '@patternfly/react-core'
-import PlusIcon from '@patternfly/react-icons/dist/js/icons/plus-icon'
-import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon'
-
-function NewRoomConstructionComponent({ onStart, onFinish, onCancel, currentRoomInConstruction }) {
- if (currentRoomInConstruction === '-1') {
- return (
- <Button isBlock icon={<PlusIcon />} onClick={onStart}>
- Construct a new room
- </Button>
- )
- }
- return (
- <Toolbar
- inset={{
- default: 'insetNone',
- }}
- >
- <ToolbarContent>
- <ToolbarGroup>
- <ToolbarItem>
- <Button icon={<CheckIcon />} onClick={onFinish}>
- Finalize new room
- </Button>
- </ToolbarItem>
- <ToolbarItem widths={{ default: '100%' }}>
- <Button isBlock variant="secondary" onClick={onCancel}>
- Cancel
- </Button>
- </ToolbarItem>
- </ToolbarGroup>
- </ToolbarContent>
- </Toolbar>
- )
-}
-
-NewRoomConstructionComponent.propTypes = {
- onStart: PropTypes.func,
- onFinish: PropTypes.func,
- onCancel: PropTypes.func,
- currentRoomInConstruction: PropTypes.string,
-}
-
-export default NewRoomConstructionComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionContainer.js
deleted file mode 100644
index c149b224..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/building/NewRoomConstructionContainer.js
+++ /dev/null
@@ -1,46 +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 React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import {
- cancelNewRoomConstruction,
- finishNewRoomConstruction,
- startNewRoomConstruction,
-} from '../../../../redux/actions/topology/building'
-import NewRoomConstructionComponent from './NewRoomConstructionComponent'
-
-function NewRoomConstructionButton() {
- const currentRoomInConstruction = useSelector((state) => state.construction.currentRoomInConstruction)
- const dispatch = useDispatch()
-
- return (
- <NewRoomConstructionComponent
- onStart={() => dispatch(startNewRoomConstruction())}
- onFinish={() => dispatch(finishNewRoomConstruction())}
- onCancel={() => dispatch(cancelNewRoomConstruction())}
- currentRoomInConstruction={currentRoomInConstruction}
- />
- )
-}
-
-export default NewRoomConstructionButton
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/DeleteMachine.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/DeleteMachine.js
deleted file mode 100644
index a4b9457b..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/DeleteMachine.js
+++ /dev/null
@@ -1,59 +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 PropTypes from 'prop-types'
-import React, { useState } from 'react'
-import { useDispatch } from 'react-redux'
-import { Button } from '@patternfly/react-core'
-import { TrashIcon } from '@patternfly/react-icons'
-import ConfirmationModal from '../../../util/modals/ConfirmationModal'
-import { deleteMachine } from '../../../../redux/actions/topology/machine'
-
-function DeleteMachine({ machineId }) {
- const dispatch = useDispatch()
- const [isVisible, setVisible] = useState(false)
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteMachine(machineId))
- }
- setVisible(false)
- }
- return (
- <>
- <Button variant="danger" icon={<TrashIcon />} isBlock onClick={() => setVisible(true)}>
- Delete this machine
- </Button>
- <ConfirmationModal
- title="Delete this machine"
- message="Are you sure you want to delete this machine?"
- isOpen={isVisible}
- callback={callback}
- />
- </>
- )
-}
-
-DeleteMachine.propTypes = {
- machineId: PropTypes.string.isRequired,
-}
-
-export default DeleteMachine
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
deleted file mode 100644
index 8a4c33dc..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/MachineSidebar.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import UnitTabsComponent from './UnitTabsComponent'
-import DeleteMachine from './DeleteMachine'
-import {
- TextContent,
- TextList,
- TextListItem,
- TextListItemVariants,
- TextListVariants,
- Title,
-} from '@patternfly/react-core'
-import { useSelector } from 'react-redux'
-
-function MachineSidebar({ tileId, position }) {
- const machine = useSelector(({ topology }) => {
- const rack = topology.racks[topology.tiles[tileId].rack]
-
- for (const machineId of rack.machines) {
- const machine = topology.machines[machineId]
- if (machine.position === position) {
- return machine
- }
- }
- })
- const machineId = machine.id
- return (
- <div>
- <TextContent>
- <Title headingLevel="h2">Details</Title>
- <TextList component={TextListVariants.dl}>
- <TextListItem component={TextListItemVariants.dt}>Name</TextListItem>
- <TextListItem component={TextListItemVariants.dd}>
- Machine at position {machine.position}
- </TextListItem>
- </TextList>
-
- <Title headingLevel="h2">Actions</Title>
- <DeleteMachine machineId={machineId} />
-
- <Title headingLevel="h2">Units</Title>
- </TextContent>
- <div className="pf-u-h-100">
- <UnitTabsComponent machineId={machineId} />
- </div>
- </div>
- )
-}
-
-MachineSidebar.propTypes = {
- tileId: PropTypes.string.isRequired,
- position: PropTypes.number.isRequired,
-}
-
-export default MachineSidebar
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
deleted file mode 100644
index 18cba23a..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddComponent.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useState } from 'react'
-import { Button, InputGroup, Select, SelectOption, SelectVariant } from '@patternfly/react-core'
-import PlusIcon from '@patternfly/react-icons/dist/js/icons/plus-icon'
-
-function UnitAddComponent({ units, onAdd }) {
- const [isOpen, setOpen] = useState(false)
- const [selected, setSelected] = useState(null)
-
- return (
- <InputGroup>
- <Select
- variant={SelectVariant.single}
- placeholderText="Select a unit"
- aria-label="Select Unit"
- onToggle={() => setOpen(!isOpen)}
- isOpen={isOpen}
- onSelect={(_, selection) => {
- setSelected(selection)
- setOpen(false)
- }}
- selections={selected}
- >
- {units.map((unit) => (
- <SelectOption value={unit.id} key={unit.id}>
- {unit.name}
- </SelectOption>
- ))}
- </Select>
- <Button icon={<PlusIcon />} variant="control" onClick={() => onAdd(selected)} isDisabled={!selected}>
- Add
- </Button>
- </InputGroup>
- )
-}
-
-UnitAddComponent.propTypes = {
- units: PropTypes.array.isRequired,
- onAdd: PropTypes.func.isRequired,
-}
-
-export default UnitAddComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddContainer.js
deleted file mode 100644
index a0054ef6..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitAddContainer.js
+++ /dev/null
@@ -1,44 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import UnitAddComponent from './UnitAddComponent'
-import { addUnit } from '../../../../redux/actions/topology/machine'
-import UnitType from './UnitType'
-
-function UnitAddContainer({ machineId, unitType }) {
- const units = useSelector((state) => Object.values(state.topology[unitType]))
- const dispatch = useDispatch()
-
- const onAdd = (id) => dispatch(addUnit(machineId, unitType, id))
-
- return <UnitAddComponent onAdd={onAdd} units={units} />
-}
-
-UnitAddContainer.propTypes = {
- machineId: PropTypes.string.isRequired,
- unitType: UnitType.isRequired,
-}
-
-export default UnitAddContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListComponent.js
deleted file mode 100644
index 75ab0ad7..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListComponent.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import {
- Button,
- DataList,
- DataListAction,
- DataListCell,
- DataListItem,
- DataListItemCells,
- DataListItemRow,
- DescriptionList,
- DescriptionListDescription,
- DescriptionListGroup,
- DescriptionListTerm,
- EmptyState,
- EmptyStateBody,
- EmptyStateIcon,
- Popover,
- Title,
-} from '@patternfly/react-core'
-import { CubesIcon, InfoIcon, TrashIcon } from '@patternfly/react-icons'
-import { ProcessingUnit, StorageUnit } from '../../../../shapes'
-import UnitType from './UnitType'
-
-function UnitInfo({ unit, unitType }) {
- if (unitType === 'cpus' || unitType === 'gpus') {
- return (
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Clock Frequency</DescriptionListTerm>
- <DescriptionListDescription>{unit.clockRateMhz} MHz</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Number of Cores</DescriptionListTerm>
- <DescriptionListDescription>{unit.numberOfCores}</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Energy Consumption</DescriptionListTerm>
- <DescriptionListDescription>{unit.energyConsumptionW} W</DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- )
- }
-
- return (
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Speed</DescriptionListTerm>
- <DescriptionListDescription>{unit.speedMbPerS} Mb/s</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Capacity</DescriptionListTerm>
- <DescriptionListDescription>{unit.sizeMb} MB</DescriptionListDescription>
- </DescriptionListGroup>
- <DescriptionListGroup>
- <DescriptionListTerm>Energy Consumption</DescriptionListTerm>
- <DescriptionListDescription>{unit.energyConsumptionW} W</DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- )
-}
-
-UnitInfo.propTypes = {
- unitType: UnitType.isRequired,
- unit: PropTypes.oneOfType([ProcessingUnit, StorageUnit]).isRequired,
-}
-
-function UnitListComponent({ unitType, units, onDelete }) {
- if (units.length === 0) {
- return (
- <EmptyState>
- <EmptyStateIcon icon={CubesIcon} />
- <Title headingLevel="h5" size="lg">
- No units found
- </Title>
- <EmptyStateBody>You have not configured any units yet. Add some with the menu above!</EmptyStateBody>
- </EmptyState>
- )
- }
-
- return (
- <DataList aria-label="Machine Units" isCompact>
- {units.map((unit, index) => (
- <DataListItem key={index}>
- <DataListItemRow>
- <DataListItemCells dataListCells={[<DataListCell key="unit">{unit.name}</DataListCell>]} />
- <DataListAction id="goto" aria-label="Goto Machine" aria-labelledby="goto">
- <Popover
- headerContent="Unit Information"
- bodyContent={<UnitInfo unitType={unitType} unit={unit} />}
- >
- <Button isSmall variant="plain" className="pf-u-p-0">
- <InfoIcon />
- </Button>
- </Popover>
- <Button isSmall variant="plain" className="pf-u-p-0" onClick={() => onDelete(units[index])}>
- <TrashIcon />
- </Button>
- </DataListAction>
- </DataListItemRow>
- </DataListItem>
- ))}
- </DataList>
- )
-}
-
-UnitListComponent.propTypes = {
- unitType: UnitType.isRequired,
- units: PropTypes.arrayOf(PropTypes.oneOfType([ProcessingUnit, StorageUnit])).isRequired,
- onDelete: PropTypes.func,
-}
-
-export default UnitListComponent
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
deleted file mode 100644
index bcd4bdcc..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitListContainer.js
+++ /dev/null
@@ -1,47 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import UnitListComponent from './UnitListComponent'
-import { deleteUnit } from '../../../../redux/actions/topology/machine'
-import UnitType from './UnitType'
-
-function UnitListContainer({ machineId, unitType }) {
- const dispatch = useDispatch()
- const units = useSelector((state) => {
- const machine = state.topology.machines[machineId]
- return machine[unitType].map((id) => state.topology[unitType][id])
- })
-
- const onDelete = (unit) => dispatch(deleteUnit(machineId, unitType, unit.id))
-
- return <UnitListComponent units={units} unitType={unitType} onDelete={onDelete} />
-}
-
-UnitListContainer.propTypes = {
- machineId: PropTypes.string.isRequired,
- unitType: UnitType.isRequired,
-}
-
-export default UnitListContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitTabsComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitTabsComponent.js
deleted file mode 100644
index 4032d607..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitTabsComponent.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useState } from 'react'
-import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'
-import UnitAddContainer from './UnitAddContainer'
-import UnitListContainer from './UnitListContainer'
-
-function UnitTabsComponent({ machineId }) {
- const [activeTab, setActiveTab] = useState('cpuModel-units')
-
- return (
- <Tabs activeKey={activeTab} onSelect={(_, tab) => setActiveTab(tab)}>
- <Tab eventKey="cpuModel-units" title={<TabTitleText>CPU</TabTitleText>}>
- <UnitAddContainer machineId={machineId} unitType="cpus" />
- <UnitListContainer machineId={machineId} unitType="cpus" />
- </Tab>
- <Tab eventKey="gpu-units" title={<TabTitleText>GPU</TabTitleText>}>
- <UnitAddContainer machineId={machineId} unitType="gpus" />
- <UnitListContainer machineId={machineId} unitType="gpus" />
- </Tab>
- <Tab eventKey="memory-units" title={<TabTitleText>Memory</TabTitleText>}>
- <UnitAddContainer machineId={machineId} unitType="memories" />
- <UnitListContainer machineId={machineId} unitType="memories" />
- </Tab>
- <Tab eventKey="storage-units" title={<TabTitleText>Storage</TabTitleText>}>
- <UnitAddContainer machineId={machineId} unitType="storages" />
- <UnitListContainer machineId={machineId} unitType="storages" />
- </Tab>
- </Tabs>
- )
-}
-
-UnitTabsComponent.propTypes = {
- machineId: PropTypes.string.isRequired,
-}
-
-export default UnitTabsComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitType.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitType.js
deleted file mode 100644
index b6d7bf8b..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/machine/UnitType.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2022 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'
-
-export default PropTypes.oneOf(['cpus', 'gpus', 'memories', 'storages'])
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
deleted file mode 100644
index 6a0c3ff3..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/AddPrefab.js
+++ /dev/null
@@ -1,41 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { Button } from '@patternfly/react-core'
-import { SaveIcon } from '@patternfly/react-icons'
-
-function AddPrefab() {
- const onClick = () => {} // TODO
- return (
- <Button variant="primary" icon={<SaveIcon />} isBlock onClick={onClick} className="pf-u-mb-sm">
- Save this rack to a prefab
- </Button>
- )
-}
-
-AddPrefab.propTypes = {
- tileId: PropTypes.string.isRequired,
-}
-
-export default AddPrefab
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/DeleteRackContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/DeleteRackContainer.js
deleted file mode 100644
index 0583a7a4..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/DeleteRackContainer.js
+++ /dev/null
@@ -1,60 +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 PropTypes from 'prop-types'
-import React, { useState } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon'
-import { Button } from '@patternfly/react-core'
-import ConfirmationModal from '../../../util/modals/ConfirmationModal'
-import { deleteRack } from '../../../../redux/actions/topology/rack'
-
-function DeleteRackContainer({ tileId }) {
- const dispatch = useDispatch()
- const [isVisible, setVisible] = useState(false)
- const rackId = useSelector((state) => state.topology.tiles[tileId].rack)
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteRack(tileId, rackId))
- }
- 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}
- />
- </>
- )
-}
-
-DeleteRackContainer.propTypes = {
- tileId: PropTypes.string.isRequired,
-}
-
-export default DeleteRackContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineComponent.js
deleted file mode 100644
index b0a96a9f..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineComponent.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Flex, Label } from '@patternfly/react-core'
-import { Machine } from '../../../../shapes'
-
-const UnitIcon = ({ id, type }) => (
- // eslint-disable-next-line @next/next/no-img-element
- <img src={'/img/topology/' + id + '-icon.png'} alt={'Machine contains ' + type + ' units'} height={24} width={24} />
-)
-
-UnitIcon.propTypes = {
- id: PropTypes.string,
- type: PropTypes.string,
-}
-
-function MachineComponent({ machine, onClick }) {
- const hasNoUnits =
- machine.cpus.length + machine.gpus.length + machine.memories.length + machine.storages.length === 0
-
- return (
- <Flex onClick={() => onClick()}>
- {machine.cpus.length > 0 ? <UnitIcon id="cpuModel" 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.isRequired,
- onClick: PropTypes.func,
-}
-
-export default MachineComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListComponent.js
deleted file mode 100644
index 02c97730..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListComponent.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import MachineComponent from './MachineComponent'
-import {
- Badge,
- Button,
- DataList,
- DataListAction,
- DataListCell,
- DataListItem,
- DataListItemCells,
- DataListItemRow,
-} from '@patternfly/react-core'
-import { AngleRightIcon, PlusIcon } from '@patternfly/react-icons'
-import { Machine } from '../../../../shapes'
-
-function MachineListComponent({ machines = [], onSelect, onAdd }) {
- return (
- <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>{index + 1}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>{index + 1}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>
- )
- )
- .reverse()}
- </DataList>
- )
-}
-
-MachineListComponent.propTypes = {
- machines: PropTypes.arrayOf(Machine),
- onSelect: PropTypes.func.isRequired,
- onAdd: PropTypes.func.isRequired,
-}
-
-export default MachineListComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListContainer.js
deleted file mode 100644
index e1914730..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/MachineListContainer.js
+++ /dev/null
@@ -1,56 +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 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.topology.racks[state.topology.tiles[tileId].rack])
- const machines = useSelector((state) => rack.machines.map((id) => state.topology.machines[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(rack.id, 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/topologies/sidebar/rack/RackNameContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackNameContainer.js
deleted file mode 100644
index c3422318..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackNameContainer.js
+++ /dev/null
@@ -1,22 +0,0 @@
-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 { name: rackName, id } = useSelector((state) => state.topology.racks[state.topology.tiles[tileId].rack])
- const dispatch = useDispatch()
- const callback = (name) => {
- if (name) {
- dispatch(editRackName(id, 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/topologies/sidebar/rack/RackSidebar.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.js
deleted file mode 100644
index cb7d3b68..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { machineListContainer, sidebarContainer } from './RackSidebar.module.css'
-import RackNameContainer from './RackNameContainer'
-import AddPrefab from './AddPrefab'
-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 RackSidebar({ tileId }) {
- const rack = useSelector((state) => state.topology.racks[state.topology.tiles[tileId].rack])
-
- return (
- <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>
- <AddPrefab tileId={tileId} />
- <DeleteRackContainer tileId={tileId} />
-
- <Title headingLevel="h2">Slots</Title>
- </TextContent>
- <div className={machineListContainer}>
- <MachineListContainer tileId={tileId} />
- </div>
- </div>
- )
-}
-
-RackSidebar.propTypes = {
- tileId: PropTypes.string.isRequired,
-}
-
-export default RackSidebar
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.module.css b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.module.css
deleted file mode 100644
index f4c8829f..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/rack/RackSidebar.module.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.sidebarContainer {
- display: flex;
- flex-direction: column;
-
- height: 100%;
-}
-
-.machineListContainer {
- overflow-y: auto;
-
- flex: 1 0 300px;
-
- margin-top: 10px;
-}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/DeleteRoomContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/DeleteRoomContainer.js
deleted file mode 100644
index 29b8f78a..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/DeleteRoomContainer.js
+++ /dev/null
@@ -1,59 +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 PropTypes from 'prop-types'
-import React, { useState } from 'react'
-import { useDispatch } from 'react-redux'
-import ConfirmationModal from '../../../util/modals/ConfirmationModal'
-import { deleteRoom } from '../../../../redux/actions/topology/room'
-import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon'
-import { Button } from '@patternfly/react-core'
-
-function DeleteRoomContainer({ roomId }) {
- const dispatch = useDispatch()
- const [isVisible, setVisible] = useState(false)
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteRoom(roomId))
- }
- setVisible(false)
- }
- return (
- <>
- <Button variant="danger" icon={<TrashIcon />} isBlock onClick={() => setVisible(true)}>
- Delete this room
- </Button>
- <ConfirmationModal
- title="Delete this room"
- message="Are you sure you want to delete this room?"
- isOpen={isVisible}
- callback={callback}
- />
- </>
- )
-}
-
-DeleteRoomContainer.propTypes = {
- roomId: PropTypes.string.isRequired,
-}
-
-export default DeleteRoomContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/EditRoomContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/EditRoomContainer.js
deleted file mode 100644
index 7a278cd6..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/EditRoomContainer.js
+++ /dev/null
@@ -1,61 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { finishRoomEdit, startRoomEdit } from '../../../../redux/actions/topology/building'
-import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon'
-import PencilAltIcon from '@patternfly/react-icons/dist/js/icons/pencil-alt-icon'
-import { Button } from '@patternfly/react-core'
-
-function EditRoomContainer({ roomId }) {
- const isEditing = useSelector((state) => state.construction.currentRoomInConstruction !== '-1')
- const isInRackConstructionMode = useSelector((state) => state.construction.inRackConstructionMode)
-
- const dispatch = useDispatch()
- const onEdit = () => dispatch(startRoomEdit(roomId))
- const onFinish = () => dispatch(finishRoomEdit())
-
- return isEditing ? (
- <Button variant="tertiary" icon={<CheckIcon />} isBlock onClick={onFinish} className="pf-u-mb-sm">
- Finish editing room
- </Button>
- ) : (
- <Button
- variant="tertiary"
- icon={<PencilAltIcon />}
- isBlock
- disabled={isInRackConstructionMode}
- onClick={() => (isInRackConstructionMode ? undefined : onEdit())}
- className="pf-u-mb-sm"
- >
- Edit the tiles of this room
- </Button>
- )
-}
-
-EditRoomContainer.propTypes = {
- roomId: PropTypes.string.isRequired,
-}
-
-export default EditRoomContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionComponent.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionComponent.js
deleted file mode 100644
index a384d5d5..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionComponent.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import { Button } from '@patternfly/react-core'
-import { PlusIcon, TimesIcon } from '@patternfly/react-icons'
-
-const RackConstructionComponent = ({ onStart, onStop, inRackConstructionMode, isEditingRoom }) => {
- if (inRackConstructionMode) {
- return (
- <Button isBlock={true} icon={<TimesIcon />} onClick={onStop} className="pf-u-mb-sm">
- Stop rack construction
- </Button>
- )
- }
-
- return (
- <Button
- icon={<PlusIcon />}
- isBlock
- isDisabled={isEditingRoom}
- onClick={() => (isEditingRoom ? undefined : onStart())}
- className="pf-u-mb-sm"
- >
- Start rack construction
- </Button>
- )
-}
-
-RackConstructionComponent.propTypes = {
- onStart: PropTypes.func,
- onStop: PropTypes.func,
- inRackConstructionMode: PropTypes.bool,
- isEditingRoom: PropTypes.bool,
-}
-
-export default RackConstructionComponent
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionContainer.js
deleted file mode 100644
index e04287a5..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RackConstructionContainer.js
+++ /dev/null
@@ -1,46 +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 React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { startRackConstruction, stopRackConstruction } from '../../../../redux/actions/topology/room'
-import RackConstructionComponent from './RackConstructionComponent'
-
-function RackConstructionContainer(props) {
- const isRackConstructionMode = useSelector((state) => state.construction.inRackConstructionMode)
- const isEditingRoom = useSelector((state) => state.construction.currentRoomInConstruction !== '-1')
-
- const dispatch = useDispatch()
- const onStart = () => dispatch(startRackConstruction())
- const onStop = () => dispatch(stopRackConstruction())
- return (
- <RackConstructionComponent
- {...props}
- inRackConstructionMode={isRackConstructionMode}
- isEditingRoom={isEditingRoom}
- onStart={onStart}
- onStop={onStop}
- />
- )
-}
-
-export default RackConstructionContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomName.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomName.js
deleted file mode 100644
index 72d45bea..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomName.js
+++ /dev/null
@@ -1,44 +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 PropTypes from 'prop-types'
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import NameComponent from '../NameComponent'
-import { editRoomName } from '../../../../redux/actions/topology/room'
-
-function RoomName({ roomId }) {
- const { name: roomName, id } = useSelector((state) => state.topology.rooms[roomId])
- const dispatch = useDispatch()
- const callback = (name) => {
- if (name) {
- dispatch(editRoomName(id, name))
- }
- }
- return <NameComponent name={roomName} onEdit={callback} />
-}
-
-RoomName.propTypes = {
- roomId: PropTypes.string.isRequired,
-}
-
-export default RoomName
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomSidebar.js b/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomSidebar.js
deleted file mode 100644
index 6ad489e0..00000000
--- a/opendc-web/opendc-web-ui/src/components/topologies/sidebar/room/RoomSidebar.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import RoomName from './RoomName'
-import RackConstructionContainer from './RackConstructionContainer'
-import EditRoomContainer from './EditRoomContainer'
-import DeleteRoomContainer from './DeleteRoomContainer'
-import {
- TextContent,
- TextList,
- TextListItem,
- TextListItemVariants,
- TextListVariants,
- Title,
-} from '@patternfly/react-core'
-
-const RoomSidebar = ({ roomId }) => {
- return (
- <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}>
- <RoomName roomId={roomId} />
- </TextListItem>
- </TextList>
- <Title headingLevel="h2">Construction</Title>
- <RackConstructionContainer />
- <EditRoomContainer roomId={roomId} />
- <DeleteRoomContainer roomId={roomId} />
- </TextContent>
- )
-}
-
-RoomSidebar.propTypes = {
- roomId: PropTypes.string.isRequired,
-}
-
-export default RoomSidebar
diff --git a/opendc-web/opendc-web-ui/src/components/util/TableEmptyState.js b/opendc-web/opendc-web-ui/src/components/util/TableEmptyState.js
deleted file mode 100644
index 9d16ffbb..00000000
--- a/opendc-web/opendc-web-ui/src/components/util/TableEmptyState.js
+++ /dev/null
@@ -1,103 +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 PropTypes from 'prop-types'
-import { Bullseye, EmptyState, EmptyStateBody, EmptyStateIcon, Spinner, Title } from '@patternfly/react-core'
-import { SearchIcon, CubesIcon } from '@patternfly/react-icons'
-import { Status } from '../../shapes'
-
-function TableEmptyState({
- status,
- isFiltering,
- loadingTitle = 'Loading',
- emptyTitle = 'No results found',
- emptyText = 'No results found of this type.',
- emptyAction = '',
-}) {
- if (status === 'loading') {
- return (
- <Bullseye>
- <EmptyState variant="xs">
- <EmptyStateIcon variant="container" component={Spinner} />
- <Title headingLevel="h4" size="md">
- {loadingTitle}
- </Title>
- </EmptyState>
- </Bullseye>
- )
- } else if (status === 'error') {
- return (
- <EmptyState variant="xs">
- <Title headingLevel="h4" size="md">
- Unable to connect
- </Title>
- <EmptyStateBody>
- There was an error retrieving data. Check your connection and try again.
- </EmptyStateBody>
- </EmptyState>
- )
- } else if (status === 'idle') {
- return (
- <EmptyState variant="xs">
- <EmptyStateIcon icon={CubesIcon} />
- <Title headingLevel="h4" size="md">
- {emptyTitle}
- </Title>
- <EmptyStateBody>No results available at this moment.</EmptyStateBody>
- </EmptyState>
- )
- } else if (isFiltering) {
- return (
- <EmptyState variant="xs">
- <EmptyStateIcon icon={SearchIcon} />
- <Title headingLevel="h4" size="md">
- No results found
- </Title>
- <EmptyStateBody>
- No results match this filter criteria. Remove all filters or clear all filters to show results.
- </EmptyStateBody>
- </EmptyState>
- )
- }
-
- return (
- <EmptyState variant="xs">
- <EmptyStateIcon icon={CubesIcon} />
- <Title headingLevel="h4" size="md">
- {emptyTitle}
- </Title>
- <EmptyStateBody>{emptyText}</EmptyStateBody>
- {emptyAction}
- </EmptyState>
- )
-}
-
-TableEmptyState.propTypes = {
- status: Status.isRequired,
- isFiltering: PropTypes.bool,
- loadingTitle: PropTypes.string,
- emptyTitle: PropTypes.string,
- emptyText: PropTypes.string,
- emptyAction: PropTypes.node,
-}
-
-export default TableEmptyState
diff --git a/opendc-web/opendc-web-ui/src/components/util/modals/ConfirmationModal.js b/opendc-web/opendc-web-ui/src/components/util/modals/ConfirmationModal.js
deleted file mode 100644
index f6e1c98b..00000000
--- a/opendc-web/opendc-web-ui/src/components/util/modals/ConfirmationModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import Modal from './Modal'
-
-function ConfirmationModal({ title, message, isOpen, callback }) {
- return (
- <Modal
- title={title}
- isOpen={isOpen}
- onSubmit={() => callback(true)}
- onCancel={() => callback(false)}
- submitButtonType="danger"
- submitButtonText="Confirm"
- >
- {message}
- </Modal>
- )
-}
-
-ConfirmationModal.propTypes = {
- title: PropTypes.string.isRequired,
- message: PropTypes.string.isRequired,
- isOpen: PropTypes.bool.isRequired,
- callback: PropTypes.func.isRequired,
-}
-
-export default ConfirmationModal
diff --git a/opendc-web/opendc-web-ui/src/components/util/modals/Modal.js b/opendc-web/opendc-web-ui/src/components/util/modals/Modal.js
deleted file mode 100644
index d4577062..00000000
--- a/opendc-web/opendc-web-ui/src/components/util/modals/Modal.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { Button, Modal as PModal, ModalVariant } from '@patternfly/react-core'
-
-function Modal({ children, title, isOpen, onSubmit, onCancel, submitButtonType, submitButtonText }) {
- const actions = [
- <Button variant={submitButtonType} onClick={onSubmit} key="confirm">
- {submitButtonText}
- </Button>,
- <Button variant="link" onClick={onCancel} key="cancel">
- Cancel
- </Button>,
- ]
-
- return (
- <PModal variant={ModalVariant.small} isOpen={isOpen} onClose={onCancel} title={title} actions={actions}>
- {children}
- </PModal>
- )
-}
-
-Modal.propTypes = {
- title: PropTypes.string.isRequired,
- isOpen: PropTypes.bool,
- onSubmit: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired,
- submitButtonType: PropTypes.string,
- submitButtonText: PropTypes.string,
- children: PropTypes.node,
-}
-
-Modal.defaultProps = {
- submitButtonType: 'primary',
- submitButtonText: 'Save',
- isOpen: false,
-}
-
-export default Modal
diff --git a/opendc-web/opendc-web-ui/src/components/util/modals/TextInputModal.js b/opendc-web/opendc-web-ui/src/components/util/modals/TextInputModal.js
deleted file mode 100644
index 392a729e..00000000
--- a/opendc-web/opendc-web-ui/src/components/util/modals/TextInputModal.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import PropTypes from 'prop-types'
-import React, { useRef, useState } from 'react'
-import Modal from './Modal'
-import { Form, FormGroup, TextInput } from '@patternfly/react-core'
-
-function TextInputModal({ title, label, isOpen, callback, initialValue }) {
- const textInput = useRef(null)
- const [isSubmitted, setSubmitted] = useState(false)
- const [isValid, setValid] = useState(true)
-
- const resetState = () => {
- textInput.current.value = ''
- setSubmitted(false)
- setValid(false)
- }
- const onSubmit = (event) => {
- const value = textInput.current.value
- setSubmitted(true)
-
- if (event) {
- event.preventDefault()
- }
-
- if (!value) {
- setValid(false)
- return false
- }
-
- callback(value)
- resetState()
- return true
- }
- const onCancel = () => {
- callback(undefined)
- resetState()
- }
-
- return (
- <Modal title={title} isOpen={isOpen} onSubmit={onSubmit} onCancel={onCancel}>
- <Form onSubmit={onSubmit}>
- <FormGroup
- label={label}
- fieldId="text-input"
- isRequired
- validated={isSubmitted && !isValid ? 'error' : 'default'}
- helperTextInvalid="This field cannot be empty"
- >
- <TextInput
- id="text-input"
- name="text-input"
- isRequired
- type="text"
- ref={textInput}
- defaultValue={initialValue}
- />
- </FormGroup>
- </Form>
- </Modal>
- )
-}
-
-TextInputModal.propTypes = {
- title: PropTypes.string.isRequired,
- label: PropTypes.string.isRequired,
- isOpen: PropTypes.bool.isRequired,
- callback: PropTypes.func.isRequired,
- initialValue: PropTypes.string,
-}
-
-export default TextInputModal
diff --git a/opendc-web/opendc-web-ui/src/config.js b/opendc-web/opendc-web-ui/src/config.js
deleted file mode 100644
index 52952d69..00000000
--- a/opendc-web/opendc-web-ui/src/config.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- */
-
-/**
- * URL to OpenDC API.
- */
-export const apiUrl = process.env.NEXT_PUBLIC_API_BASE_URL
-
-/**
- * Authentication configuration.
- */
-export const auth = {
- domain: process.env.NEXT_PUBLIC_AUTH0_DOMAIN,
- clientId: process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID,
- audience: process.env.NEXT_PUBLIC_AUTH0_AUDIENCE,
- redirectUri: global.window && global.window.location.origin,
-}
-
-/**
- * Sentry DSN for web frontend.
- */
-export const sentryDsn = process.env.NEXT_PUBLIC_SENTRY_DSN
diff --git a/opendc-web/opendc-web-ui/src/data/experiments.js b/opendc-web/opendc-web-ui/src/data/experiments.js
deleted file mode 100644
index ca8912a2..00000000
--- a/opendc-web/opendc-web-ui/src/data/experiments.js
+++ /dev/null
@@ -1,47 +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 { useQuery } from 'react-query'
-import { fetchTraces } from '../api/traces'
-import { fetchSchedulers } from '../api/schedulers'
-
-/**
- * Configure the query defaults for the experiment endpoints.
- */
-export function configureExperimentClient(queryClient, auth) {
- queryClient.setQueryDefaults('traces', { queryFn: () => fetchTraces(auth) })
- queryClient.setQueryDefaults('schedulers', { queryFn: () => fetchSchedulers(auth) })
-}
-
-/**
- * Return the available traces to experiment with.
- */
-export function useTraces(options) {
- return useQuery('traces', options)
-}
-
-/**
- * Return the available schedulers to experiment with.
- */
-export function useSchedulers(options) {
- return useQuery('schedulers', options)
-}
diff --git a/opendc-web/opendc-web-ui/src/data/project.js b/opendc-web/opendc-web-ui/src/data/project.js
deleted file mode 100644
index 60a8fab6..00000000
--- a/opendc-web/opendc-web-ui/src/data/project.js
+++ /dev/null
@@ -1,166 +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 { useQuery, useMutation } from 'react-query'
-import { addProject, deleteProject, fetchProject, fetchProjects } from '../api/projects'
-import { addPortfolio, deletePortfolio, fetchPortfolio, fetchPortfolios } from '../api/portfolios'
-import { addScenario, deleteScenario, fetchScenario } from '../api/scenarios'
-
-/**
- * Configure the query defaults for the project endpoints.
- */
-export function configureProjectClient(queryClient, auth) {
- queryClient.setQueryDefaults('projects', {
- queryFn: ({ queryKey }) => (queryKey.length === 1 ? fetchProjects(auth) : fetchProject(auth, queryKey[1])),
- })
-
- queryClient.setMutationDefaults('addProject', {
- mutationFn: (data) => addProject(auth, data),
- onSuccess: async (result) => {
- queryClient.setQueryData('projects', (old = []) => [...old, result])
- queryClient.setQueryData(['projects', result.id], result)
- },
- })
- queryClient.setMutationDefaults('deleteProject', {
- mutationFn: (id) => deleteProject(auth, id),
- onSuccess: async (result) => {
- queryClient.setQueryData('projects', (old = []) => old.filter((project) => project.id !== result.id))
- queryClient.removeQueries(['projects', result.id])
- },
- })
-
- queryClient.setQueryDefaults('portfolios', {
- queryFn: ({ queryKey }) =>
- queryKey.length === 2 ? fetchPortfolios(auth, queryKey[1]) : fetchPortfolio(auth, queryKey[1], queryKey[2]),
- })
- queryClient.setMutationDefaults('addPortfolio', {
- mutationFn: ({ projectId, ...data }) => addPortfolio(auth, projectId, data),
- onSuccess: async (result) => {
- queryClient.setQueryData(['portfolios', result.project.id], (old = []) => [...old, result])
- queryClient.setQueryData(['portfolios', result.project.id, result.number], result)
- },
- })
- queryClient.setMutationDefaults('deletePortfolio', {
- mutationFn: ({ projectId, number }) => deletePortfolio(auth, projectId, number),
- onSuccess: async (result) => {
- queryClient.setQueryData(['portfolios', result.project.id], (old = []) =>
- old.filter((portfolio) => portfolio.id !== result.id)
- )
- queryClient.removeQueries(['portfolios', result.project.id, result.number])
- },
- })
-
- queryClient.setQueryDefaults('scenarios', {
- queryFn: ({ queryKey }) => fetchScenario(auth, queryKey[1], queryKey[2]),
- })
- queryClient.setMutationDefaults('addScenario', {
- mutationFn: ({ projectId, portfolioNumber, data }) => addScenario(auth, projectId, portfolioNumber, data),
- onSuccess: async (result) => {
- // Register updated scenario in cache
- queryClient.setQueryData(['scenarios', result.project.id, result.id], result)
- queryClient.setQueryData(['portfolios', result.project.id, result.portfolio.number], (old) => ({
- ...old,
- scenarios: [...old.scenarios, result],
- }))
- },
- })
- queryClient.setMutationDefaults('deleteScenario', {
- mutationFn: ({ projectId, number }) => deleteScenario(auth, projectId, number),
- onSuccess: async (result) => {
- queryClient.removeQueries(['scenarios', result.project.id, result.id])
- queryClient.setQueryData(['portfolios', result.project.id, result.portfolio.number], (old) => ({
- ...old,
- scenarios: old?.scenarios?.filter((scenario) => scenario.id !== result.id),
- }))
- },
- })
-}
-
-/**
- * Return the available projects.
- */
-export function useProjects(options = {}) {
- return useQuery('projects', options)
-}
-
-/**
- * Return the project with the specified identifier.
- */
-export function useProject(projectId, options = {}) {
- return useQuery(['projects', projectId], { enabled: !!projectId, ...options })
-}
-
-/**
- * Create a mutation for a new project.
- */
-export function useNewProject() {
- return useMutation('addProject')
-}
-
-/**
- * Create a mutation for deleting a project.
- */
-export function useDeleteProject() {
- return useMutation('deleteProject')
-}
-
-/**
- * Return the portfolio with the specified identifier.
- */
-export function usePortfolio(projectId, portfolioId, options = {}) {
- return useQuery(['portfolios', projectId, portfolioId], { enabled: !!(projectId && portfolioId), ...options })
-}
-
-/**
- * Return the portfolios of the specified project.
- */
-export function usePortfolios(projectId, options = {}) {
- return useQuery(['portfolios', projectId], { enabled: !!projectId, ...options })
-}
-
-/**
- * Create a mutation for a new portfolio.
- */
-export function useNewPortfolio() {
- return useMutation('addPortfolio')
-}
-
-/**
- * Create a mutation for deleting a portfolio.
- */
-export function useDeletePortfolio() {
- return useMutation('deletePortfolio')
-}
-
-/**
- * Create a mutation for a new scenario.
- */
-export function useNewScenario() {
- return useMutation('addScenario')
-}
-
-/**
- * Create a mutation for deleting a scenario.
- */
-export function useDeleteScenario() {
- return useMutation('deleteScenario')
-}
diff --git a/opendc-web/opendc-web-ui/src/data/query.js b/opendc-web/opendc-web-ui/src/data/query.js
deleted file mode 100644
index 3e5423b9..00000000
--- a/opendc-web/opendc-web-ui/src/data/query.js
+++ /dev/null
@@ -1,59 +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 { useMemo } from 'react'
-import { QueryClient } from 'react-query'
-import { useAuth } from '../auth'
-import { configureExperimentClient } from './experiments'
-import { configureProjectClient } from './project'
-import { configureTopologyClient } from './topology'
-import { configureUserClient } from './user'
-
-let queryClient
-
-function createQueryClient(auth) {
- const client = new QueryClient()
- configureProjectClient(client, auth)
- configureExperimentClient(client, auth)
- configureTopologyClient(client, auth)
- configureUserClient(client, auth)
- return client
-}
-
-function initializeQueryClient(auth) {
- const _queryClient = queryClient ?? createQueryClient(auth)
-
- // For SSG and SSR always create a new query client
- if (typeof window === 'undefined') return _queryClient
- // Create the query client once in the client
- if (!queryClient) queryClient = _queryClient
-
- return _queryClient
-}
-
-/**
- * Obtain a cached query client.
- */
-export function useNewQueryClient() {
- const auth = useAuth()
- return useMemo(() => initializeQueryClient(auth), []) // eslint-disable-line react-hooks/exhaustive-deps
-}
diff --git a/opendc-web/opendc-web-ui/src/data/topology.js b/opendc-web/opendc-web-ui/src/data/topology.js
deleted file mode 100644
index d5e624d5..00000000
--- a/opendc-web/opendc-web-ui/src/data/topology.js
+++ /dev/null
@@ -1,88 +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 { useQuery, useMutation } from 'react-query'
-import { addTopology, deleteTopology, fetchTopologies, fetchTopology, updateTopology } from '../api/topologies'
-
-/**
- * Configure the query defaults for the topology endpoints.
- */
-export function configureTopologyClient(queryClient, auth) {
- queryClient.setQueryDefaults('topologies', {
- queryFn: ({ queryKey }) =>
- queryKey.length === 2 ? fetchTopologies(auth, queryKey[1]) : fetchTopology(auth, queryKey[1], queryKey[2]),
- })
-
- queryClient.setMutationDefaults('addTopology', {
- mutationFn: ({ projectId, ...data }) => addTopology(auth, projectId, data),
- onSuccess: (result) => {
- queryClient.setQueryData(['topologies', result.project.id], (old = []) => [...old, result])
- queryClient.setQueryData(['topologies', result.project.id, result.number], result)
- },
- })
- queryClient.setMutationDefaults('updateTopology', {
- mutationFn: (data) => updateTopology(auth, data),
- onSuccess: (result) => {
- queryClient.setQueryData(['topologies', result.project.id], (old = []) =>
- old.map((topology) => (topology.id === result.id ? result : topology))
- )
- queryClient.setQueryData(['topologies', result.project.id, result.number], result)
- },
- })
- queryClient.setMutationDefaults('deleteTopology', {
- mutationFn: ({ projectId, number }) => deleteTopology(auth, projectId, number),
- onSuccess: (result) => {
- queryClient.setQueryData(['topologies', result.project.id], (old = []) =>
- old.filter((topology) => topology.id !== result.id)
- )
- queryClient.removeQueries(['topologies', result.project.id, result.number])
- },
- })
-}
-
-/**
- * Fetch the topology with the specified identifier for the specified project.
- */
-export function useTopology(projectId, topologyId, options = {}) {
- return useQuery(['topologies', projectId, topologyId], { enabled: !!(projectId && topologyId), ...options })
-}
-
-/**
- * Fetch all topologies of the specified project.
- */
-export function useTopologies(projectId, options = {}) {
- return useQuery(['topologies', projectId], { enabled: !!projectId, ...options })
-}
-
-/**
- * Create a mutation for a new topology.
- */
-export function useNewTopology() {
- return useMutation('addTopology')
-}
-
-/**
- * Create a mutation for deleting a topology.
- */
-export function useDeleteTopology(options = {}) {
- return useMutation('deleteTopology', options)
-}
diff --git a/opendc-web/opendc-web-ui/src/data/user.js b/opendc-web/opendc-web-ui/src/data/user.js
deleted file mode 100644
index 97c0e1e2..00000000
--- a/opendc-web/opendc-web-ui/src/data/user.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2022 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 { useQuery } from 'react-query'
-import { fetchUser } from '../api/users'
-
-/**
- * Configure the query defaults for the user client.
- */
-export function configureUserClient(queryClient, auth) {
- queryClient.setQueryDefaults('user', {
- queryFn: () => fetchUser(auth),
- })
-}
-
-/**
- * Fetch the user data on the server.
- */
-export default function useUser(options = {}) {
- return useQuery('user', options)
-}
diff --git a/opendc-web/opendc-web-ui/src/pages/404.js b/opendc-web/opendc-web-ui/src/pages/404.js
deleted file mode 100644
index 0939bc56..00000000
--- a/opendc-web/opendc-web-ui/src/pages/404.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react'
-import Head from 'next/head'
-import { AppPage } from '../components/AppPage'
-import {
- Bullseye,
- EmptyState,
- EmptyStateBody,
- EmptyStateIcon,
- PageSection,
- PageSectionVariants,
- Title,
-} from '@patternfly/react-core'
-import { UnknownIcon } from '@patternfly/react-icons'
-
-const NotFound = () => {
- return (
- <AppPage>
- <Head>
- <title>Page Not Found - OpenDC</title>
- </Head>
- <PageSection variant={PageSectionVariants.light}>
- <Bullseye>
- <EmptyState>
- <EmptyStateIcon variant="container" component={UnknownIcon} />
- <Title size="lg" headingLevel="h4">
- 404: That page does not exist
- </Title>
- <EmptyStateBody>
- The requested page is not found. Try refreshing the page if it was recently added.
- </EmptyStateBody>
- </EmptyState>
- </Bullseye>
- </PageSection>
- </AppPage>
- )
-}
-
-export default NotFound
diff --git a/opendc-web/opendc-web-ui/src/pages/_app.js b/opendc-web/opendc-web-ui/src/pages/_app.js
deleted file mode 100644
index 62ce0539..00000000
--- a/opendc-web/opendc-web-ui/src/pages/_app.js
+++ /dev/null
@@ -1,108 +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 PropTypes from 'prop-types'
-import Head from 'next/head'
-import Script from 'next/script'
-import { Provider } from 'react-redux'
-import { useNewQueryClient } from '../data/query'
-import { useStore } from '../redux'
-import { AuthProvider, useRequireAuth } from '../auth'
-import * as Sentry from '@sentry/react'
-import { Integrations } from '@sentry/tracing'
-import { QueryClientProvider } from 'react-query'
-import { sentryDsn } from '../config'
-
-import '@patternfly/react-core/dist/styles/base.css'
-import '@patternfly/react-styles/css/utilities/Alignment/alignment.css'
-import '@patternfly/react-styles/css/utilities/BackgroundColor/BackgroundColor.css'
-import '@patternfly/react-styles/css/utilities/BoxShadow/box-shadow.css'
-import '@patternfly/react-styles/css/utilities/Display/display.css'
-import '@patternfly/react-styles/css/utilities/Flex/flex.css'
-import '@patternfly/react-styles/css/utilities/Float/float.css'
-import '@patternfly/react-styles/css/utilities/Sizing/sizing.css'
-import '@patternfly/react-styles/css/utilities/Spacing/spacing.css'
-import '@patternfly/react-styles/css/utilities/Text/text.css'
-import '@patternfly/react-styles/css/components/InlineEdit/inline-edit.css'
-import '../style/index.css'
-
-// This setup is necessary to forward the Auth0 context to the Redux context
-function Inner({ Component, pageProps }) {
- // Force user to be authorized
- useRequireAuth()
-
- const queryClient = useNewQueryClient()
- const store = useStore(pageProps.initialReduxState, { queryClient })
- return (
- <QueryClientProvider client={queryClient}>
- <Provider store={store}>
- <Component {...pageProps} />
- </Provider>
- </QueryClientProvider>
- )
-}
-
-Inner.propTypes = {
- Component: PropTypes.func,
- pageProps: PropTypes.shape({
- initialReduxState: PropTypes.object,
- }).isRequired,
-}
-
-// Initialize Sentry if the user has configured a DSN
-if (process.browser && sentryDsn) {
- Sentry.init({
- environment: process.env.NODE_ENV,
- dsn: sentryDsn,
- integrations: [new Integrations.BrowserTracing()],
- tracesSampleRate: 0.1,
- })
-}
-
-export default function App(props) {
- return (
- <>
- <Head>
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
- <meta name="theme-color" content="#00A6D6" />
- </Head>
- <Sentry.ErrorBoundary fallback={'An error has occurred'}>
- <AuthProvider>
- <Inner {...props} />
- </AuthProvider>
- </Sentry.ErrorBoundary>
- {/* Google Analytics */}
- <Script async src="https://www.googletagmanager.com/gtag/js?id=UA-84285092-3" />
- <Script
- id="gtag"
- dangerouslySetInnerHTML={{
- __html: `
- window.dataLayer = window.dataLayer || [];
- function gtag(){dataLayer.push(arguments);}
- gtag('js', new Date());
- gtag('config', 'UA-84285092-3');
- `,
- }}
- />
- </>
- )
-}
diff --git a/opendc-web/opendc-web-ui/src/pages/_document.js b/opendc-web/opendc-web-ui/src/pages/_document.js
deleted file mode 100644
index 9f84b2ab..00000000
--- a/opendc-web/opendc-web-ui/src/pages/_document.js
+++ /dev/null
@@ -1,76 +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 Document, { Html, Head, Main, NextScript } from 'next/document'
-
-class OpenDCDocument extends Document {
- render() {
- return (
- <Html lang="en">
- <Head>
- <meta charSet="utf-8" />
- <meta name="theme-color" content="#00A6D6" />
- <meta
- name="description"
- content="Collaborative Datacenter Simulation and Exploration for Everybody"
- />
- <meta name="author" content="@Large Research" />
- <meta
- name="keywords"
- content="OpenDC, Datacenter, Simulation, Simulator, Collaborative, Distributed, Cluster"
- />
- <link rel="manifest" href="/manifest.json" />
- <link rel="shortcut icon" href="/favicon.ico" />
-
- {/* Twitter Card data */}
- <meta name="twitter:card" content="summary" />
- <meta name="twitter:site" content="@LargeResearch" />
- <meta name="twitter:title" content="OpenDC" />
- <meta
- name="twitter:description"
- content="Collaborative Datacenter Simulation and Exploration for Everybody"
- />
- <meta name="twitter:creator" content="@LargeResearch" />
- <meta name="twitter:image" content="http://opendc.org/img/logo.png" />
-
- {/* OpenGraph meta tags */}
- <meta property="og:title" content="OpenDC" />
- <meta property="og:site_name" content="OpenDC" />
- <meta property="og:type" content="website" />
- <meta property="og:image" content="http://opendc.org/img/logo.png" />
- <meta property="og:url" content="http://opendc.org/" />
- <meta
- property="og:description"
- content="OpenDC provides collaborative online datacenter modeling, diverse and effective datacenter simulation, and exploratory datacenter performance feedback."
- />
- <meta property="og:locale" content="en_US" />
- </Head>
- <body>
- <Main />
- <NextScript />
- </body>
- </Html>
- )
- }
-}
-
-export default OpenDCDocument
diff --git a/opendc-web/opendc-web-ui/src/pages/logout.js b/opendc-web/opendc-web-ui/src/pages/logout.js
deleted file mode 100644
index 38d5968e..00000000
--- a/opendc-web/opendc-web-ui/src/pages/logout.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 React from 'react'
-import Head from 'next/head'
-import { AppPage } from '../components/AppPage'
-import { PageSection, PageSectionVariants } from '@patternfly/react-core'
-
-function Logout() {
- return (
- <AppPage>
- <Head>
- <title>Logged Out - OpenDC</title>
- </Head>
- <PageSection variant={PageSectionVariants.light}>Logged out successfully</PageSection>
- </AppPage>
- )
-}
-
-export default Logout
diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js
deleted file mode 100644
index 52938bcd..00000000
--- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js
+++ /dev/null
@@ -1,75 +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 { useRouter } from 'next/router'
-import ProjectOverview from '../../../components/projects/ProjectOverview'
-import { useProject } from '../../../data/project'
-import { AppPage } from '../../../components/AppPage'
-import Head from 'next/head'
-import Link from 'next/link'
-import {
- Breadcrumb,
- BreadcrumbItem,
- PageSection,
- PageSectionVariants,
- Skeleton,
- Text,
- TextContent,
-} from '@patternfly/react-core'
-
-function Project() {
- const router = useRouter()
- const projectId = +router.query['project']
-
- const { data: project } = useProject(+projectId)
-
- const breadcrumb = (
- <Breadcrumb>
- <BreadcrumbItem to="/projects" component={Link}>
- Projects
- </BreadcrumbItem>
- <BreadcrumbItem to={`/projects/${projectId}`} component={Link} isActive>
- Project details
- </BreadcrumbItem>
- </Breadcrumb>
- )
-
- return (
- <AppPage breadcrumb={breadcrumb}>
- <Head>
- <title>{`${project?.name ?? 'Project'} - OpenDC`}</title>
- </Head>
- <PageSection variant={PageSectionVariants.light}>
- <TextContent>
- <Text component="h1">
- {project?.name ?? <Skeleton width="15%" screenreaderText="Loading project" />}
- </Text>
- </TextContent>
- </PageSection>
- <PageSection isFilled>
- <ProjectOverview projectId={projectId} />
- </PageSection>
- </AppPage>
- )
-}
-
-export default Project
diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js
deleted file mode 100644
index 5d1e041b..00000000
--- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js
+++ /dev/null
@@ -1,121 +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 dynamic from 'next/dynamic'
-import { useRouter } from 'next/router'
-import Head from 'next/head'
-import Link from 'next/link'
-import React, { useRef } from 'react'
-import {
- Breadcrumb,
- BreadcrumbItem,
- Divider,
- PageSection,
- PageSectionVariants,
- Tab,
- TabContent,
- Tabs,
- TabTitleText,
- Text,
- TextContent,
-} from '@patternfly/react-core'
-import { AppPage } from '../../../../components/AppPage'
-import ContextSelectionSection from '../../../../components/context/ContextSelectionSection'
-import PortfolioSelector from '../../../../components/context/PortfolioSelector'
-import PortfolioOverview from '../../../../components/portfolios/PortfolioOverview'
-import { usePortfolio } from '../../../../data/project'
-
-const PortfolioResults = dynamic(() => import('../../../../components/portfolios/PortfolioResults'), { ssr: false })
-
-/**
- * Page that displays the results in a portfolio.
- */
-function Portfolio() {
- const router = useRouter()
- const projectId = +router.query['project']
- const portfolioNumber = +router.query['portfolio']
-
- const overviewRef = useRef(null)
- const resultsRef = useRef(null)
-
- const { data: portfolio } = usePortfolio(projectId, portfolioNumber)
-
- const breadcrumb = (
- <Breadcrumb>
- <BreadcrumbItem to="/projects" component={Link}>
- Projects
- </BreadcrumbItem>
- <BreadcrumbItem to={`/projects/${projectId}`} component={Link}>
- Project details
- </BreadcrumbItem>
- <BreadcrumbItem to={`/projects/${projectId}/portfolios/${portfolioNumber}`} component={Link} isActive>
- Portfolio
- </BreadcrumbItem>
- </Breadcrumb>
- )
-
- const contextSelectors = (
- <ContextSelectionSection>
- <PortfolioSelector activePortfolio={portfolio} />
- </ContextSelectionSection>
- )
-
- return (
- <AppPage breadcrumb={breadcrumb} contextSelectors={contextSelectors}>
- <Head>
- <title>Portfolio - OpenDC</title>
- </Head>
- <PageSection variant={PageSectionVariants.light}>
- <TextContent>
- <Text component="h1">Portfolio</Text>
- </TextContent>
- </PageSection>
- <PageSection type="tabs" variant={PageSectionVariants.light} stickyOnBreakpoint={{ default: 'top' }}>
- <Divider component="div" />
- <Tabs defaultActiveKey={0} className="pf-m-page-insets">
- <Tab
- eventKey={0}
- title={<TabTitleText>Overview</TabTitleText>}
- tabContentId="overview"
- tabContentRef={overviewRef}
- />
- <Tab
- eventKey={1}
- title={<TabTitleText>Results</TabTitleText>}
- tabContentId="results"
- tabContentRef={resultsRef}
- />
- </Tabs>
- </PageSection>
- <PageSection isFilled>
- <TabContent eventKey={0} id="overview" ref={overviewRef} aria-label="Overview tab">
- <PortfolioOverview projectId={projectId} portfolioId={portfolioNumber} />
- </TabContent>
- <TabContent eventKey={1} id="results" ref={resultsRef} aria-label="Results tab" hidden>
- <PortfolioResults projectId={projectId} portfolioId={portfolioNumber} />
- </TabContent>
- </PageSection>
- </AppPage>
- )
-}
-
-export default Portfolio
diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js
deleted file mode 100644
index 48359365..00000000
--- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js
+++ /dev/null
@@ -1,142 +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 dynamic from 'next/dynamic'
-import { useRouter } from 'next/router'
-import Head from 'next/head'
-import Link from 'next/link'
-import ContextSelectionSection from '../../../../components/context/ContextSelectionSection'
-import TopologySelector from '../../../../components/context/TopologySelector'
-import TopologyOverview from '../../../../components/topologies/TopologyOverview'
-import { useDispatch } from 'react-redux'
-import React, { useEffect, useState } from 'react'
-import { AppPage } from '../../../../components/AppPage'
-import {
- Breadcrumb,
- BreadcrumbItem,
- Divider,
- PageSection,
- PageSectionVariants,
- Tab,
- TabContent,
- Tabs,
- TabTitleText,
- Text,
- TextContent,
-} from '@patternfly/react-core'
-import { useTopology } from '../../../../data/topology'
-import { goToRoom } from '../../../../redux/actions/interaction-level'
-import { openTopology } from '../../../../redux/actions/topology'
-
-const TopologyMap = dynamic(() => import('../../../../components/topologies/TopologyMap'), { ssr: false })
-
-/**
- * Page that displays a datacenter topology.
- */
-function Topology() {
- const router = useRouter()
- const projectId = +router.query['project']
- const topologyNumber = +router.query['topology']
-
- const { data: topology } = useTopology(projectId, topologyNumber)
-
- const dispatch = useDispatch()
- useEffect(() => {
- if (topologyNumber) {
- dispatch(openTopology(projectId, topologyNumber))
- }
- }, [projectId, topologyNumber, dispatch])
-
- const [activeTab, setActiveTab] = useState('overview')
-
- const breadcrumb = (
- <Breadcrumb>
- <BreadcrumbItem to="/projects" component={Link}>
- Projects
- </BreadcrumbItem>
- <BreadcrumbItem to={`/projects/${projectId}`} component={Link}>
- Project details
- </BreadcrumbItem>
- <BreadcrumbItem to={`/projects/${projectId}/topologies/${topologyNumber}`} component={Link} isActive>
- Topology
- </BreadcrumbItem>
- </Breadcrumb>
- )
-
- const contextSelectors = (
- <ContextSelectionSection>
- <TopologySelector activeTopology={topology} />
- </ContextSelectionSection>
- )
-
- return (
- <AppPage breadcrumb={breadcrumb} contextSelectors={contextSelectors}>
- <Head>
- <title>{`${topology?.name ?? 'Topologies'} - OpenDC`}</title>
- </Head>
- <PageSection variant={PageSectionVariants.light}>
- <TextContent>
- <Text component="h1">Topology</Text>
- </TextContent>
- </PageSection>
- <PageSection type="none" variant={PageSectionVariants.light} className="pf-c-page__main-tabs" sticky="top">
- <Divider component="div" />
- <Tabs
- activeKey={activeTab}
- onSelect={(_, tabIndex) => setActiveTab(tabIndex)}
- className="pf-m-page-insets"
- >
- <Tab eventKey="overview" title={<TabTitleText>Overview</TabTitleText>} tabContentId="overview" />
- <Tab
- eventKey="floor-plan"
- title={<TabTitleText>Floor Plan</TabTitleText>}
- tabContentId="floor-plan"
- />
- </Tabs>
- </PageSection>
- <PageSection padding={activeTab === 'floor-plan' && { default: 'noPadding' }} isFilled>
- <TabContent id="overview" aria-label="Overview tab" hidden={activeTab !== 'overview'}>
- <TopologyOverview
- projectId={projectId}
- topologyNumber={topologyNumber}
- onSelect={(type, obj) => {
- if (type === 'room') {
- dispatch(goToRoom(obj.id))
- setActiveTab('floor-plan')
- }
- }}
- />
- </TabContent>
- <TabContent
- id="floor-plan"
- aria-label="Floor Plan tab"
- className="pf-u-h-100"
- hidden={activeTab !== 'floor-plan'}
- >
- <TopologyMap />
- </TabContent>
- </PageSection>
- </AppPage>
- )
-}
-
-export default Topology
diff --git a/opendc-web/opendc-web-ui/src/pages/projects/index.js b/opendc-web/opendc-web-ui/src/pages/projects/index.js
deleted file mode 100644
index 97ff105c..00000000
--- a/opendc-web/opendc-web-ui/src/pages/projects/index.js
+++ /dev/null
@@ -1,116 +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 { PlusIcon } from '@patternfly/react-icons'
-import React, { useMemo, useState } from 'react'
-import Head from 'next/head'
-import ProjectFilterPanel from '../../components/projects/FilterPanel'
-import { AppPage } from '../../components/AppPage'
-import {
- PageSection,
- PageSectionVariants,
- Title,
- Toolbar,
- ToolbarItem,
- ToolbarContent,
- Button,
- TextContent,
- Text,
-} from '@patternfly/react-core'
-import ProjectCollection from '../../components/projects/ProjectCollection'
-import TextInputModal from '../../components/util/modals/TextInputModal'
-import { useProjects, useDeleteProject, useNewProject } from '../../data/project'
-
-const getVisibleProjects = (projects, filter) => {
- switch (filter) {
- case 'SHOW_ALL':
- return projects
- case 'SHOW_OWN':
- return projects.filter((project) => project.role === 'OWNER')
- case 'SHOW_SHARED':
- return projects.filter((project) => project.role !== 'OWNER')
- default:
- return projects
- }
-}
-
-function Projects() {
- const { status, data: projects } = useProjects()
- const [filter, setFilter] = useState('SHOW_ALL')
- const visibleProjects = useMemo(() => getVisibleProjects(projects ?? [], filter), [projects, filter])
-
- const { mutate: deleteProject } = useDeleteProject()
- const { mutate: addProject } = useNewProject()
-
- const [isProjectCreationModalVisible, setProjectCreationModalVisible] = useState(false)
- const onProjectCreation = (name) => {
- if (name) {
- addProject({ name })
- }
- setProjectCreationModalVisible(false)
- }
-
- return (
- <AppPage>
- <Head>
- <title>My Projects - OpenDC</title>
- </Head>
- <PageSection variant={PageSectionVariants.light} isFilled>
- <div className="pf-u-mx-auto pf-u-max-width" style={{ '--pf-u-max-width--MaxWidth': '100ch' }}>
- <Title className="pf-u-mt-xl-on-md" headingLevel="h1" size="4xl">
- Welcome
- </Title>
- <TextContent>
- <Text component="p">Find all your personal and shared projects</Text>
- </TextContent>
- <Toolbar inset={{ default: 'insetNone' }}>
- <ToolbarContent>
- <ToolbarItem>
- <ProjectFilterPanel onSelect={setFilter} activeFilter={filter} />
- </ToolbarItem>
- <ToolbarItem alignment={{ default: 'alignRight' }}>
- <Button icon={<PlusIcon />} onClick={() => setProjectCreationModalVisible(true)}>
- Create Project
- </Button>
- </ToolbarItem>
- </ToolbarContent>
- </Toolbar>
- <ProjectCollection
- status={status}
- isFiltering={filter !== 'SHOW_ALL'}
- projects={visibleProjects}
- onDelete={(project) => deleteProject(project.id)}
- onCreate={() => setProjectCreationModalVisible(true)}
- />
- <TextInputModal
- title="New Project"
- label="Project name"
- isOpen={isProjectCreationModalVisible}
- callback={onProjectCreation}
- />
- </div>
- </PageSection>
- </AppPage>
- )
-}
-
-export default Projects
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/interaction-level.js b/opendc-web/opendc-web-ui/src/redux/actions/interaction-level.js
deleted file mode 100644
index 8381eeef..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/interaction-level.js
+++ /dev/null
@@ -1,57 +0,0 @@
-export const GO_FROM_BUILDING_TO_ROOM = 'GO_FROM_BUILDING_TO_ROOM'
-export const GO_FROM_ROOM_TO_RACK = 'GO_FROM_ROOM_TO_RACK'
-export const GO_FROM_RACK_TO_MACHINE = 'GO_FROM_RACK_TO_MACHINE'
-export const GO_DOWN_ONE_INTERACTION_LEVEL = 'GO_DOWN_ONE_INTERACTION_LEVEL'
-
-export function goToRoom(roomId) {
- return {
- type: GO_FROM_BUILDING_TO_ROOM,
- roomId,
- }
-}
-
-export function goFromBuildingToRoom(roomId) {
- return (dispatch, getState) => {
- const { interactionLevel } = getState()
- if (interactionLevel.mode !== 'BUILDING') {
- return
- }
-
- dispatch({
- type: GO_FROM_BUILDING_TO_ROOM,
- roomId,
- })
- }
-}
-
-export function goFromRoomToRack(tileId) {
- return (dispatch, getState) => {
- const { interactionLevel } = getState()
- if (interactionLevel.mode !== 'ROOM') {
- return
- }
- dispatch({
- type: GO_FROM_ROOM_TO_RACK,
- tileId,
- })
- }
-}
-
-export function goFromRackToMachine(position) {
- return (dispatch, getState) => {
- const { interactionLevel } = getState()
- if (interactionLevel.mode !== 'RACK') {
- return
- }
- dispatch({
- type: GO_FROM_RACK_TO_MACHINE,
- position,
- })
- }
-}
-
-export function goDownOneInteractionLevel() {
- return {
- type: GO_DOWN_ONE_INTERACTION_LEVEL,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/topology/building.js b/opendc-web/opendc-web-ui/src/redux/actions/topology/building.js
deleted file mode 100644
index c12417b9..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/topology/building.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import { v4 as uuid } from 'uuid'
-import { addRoom, deleteRoom } from './room'
-
-export const START_NEW_ROOM_CONSTRUCTION = 'START_NEW_ROOM_CONSTRUCTION'
-export const START_NEW_ROOM_CONSTRUCTION_SUCCEEDED = 'START_NEW_ROOM_CONSTRUCTION_SUCCEEDED'
-export const FINISH_NEW_ROOM_CONSTRUCTION = 'FINISH_NEW_ROOM_CONSTRUCTION'
-export const CANCEL_NEW_ROOM_CONSTRUCTION = 'CANCEL_NEW_ROOM_CONSTRUCTION'
-export const CANCEL_NEW_ROOM_CONSTRUCTION_SUCCEEDED = 'CANCEL_NEW_ROOM_CONSTRUCTION_SUCCEEDED'
-export const START_ROOM_EDIT = 'START_ROOM_EDIT'
-export const FINISH_ROOM_EDIT = 'FINISH_ROOM_EDIT'
-export const ADD_TILE = 'ADD_TILE'
-export const DELETE_TILE = 'DELETE_TILE'
-
-export function startNewRoomConstruction() {
- return (dispatch, getState) => {
- const { topology } = getState()
- const topologyId = topology.root.id
- const room = {
- id: uuid(),
- name: 'Room',
- topologyId,
- tiles: [],
- }
-
- dispatch(addRoom(topologyId, room))
- dispatch(startNewRoomConstructionSucceeded(room.id))
- }
-}
-
-export function startNewRoomConstructionSucceeded(roomId) {
- return {
- type: START_NEW_ROOM_CONSTRUCTION_SUCCEEDED,
- roomId,
- }
-}
-
-export function finishNewRoomConstruction() {
- return (dispatch, getState) => {
- const { topology, construction } = getState()
- if (topology.rooms[construction.currentRoomInConstruction].tiles.length === 0) {
- dispatch(cancelNewRoomConstruction())
- return
- }
-
- dispatch({
- type: FINISH_NEW_ROOM_CONSTRUCTION,
- })
- }
-}
-
-export function cancelNewRoomConstruction() {
- return (dispatch, getState) => {
- const { construction } = getState()
- const roomId = construction.currentRoomInConstruction
- dispatch(deleteRoom(roomId))
- dispatch(cancelNewRoomConstructionSucceeded())
- }
-}
-
-export function cancelNewRoomConstructionSucceeded() {
- return {
- type: CANCEL_NEW_ROOM_CONSTRUCTION_SUCCEEDED,
- }
-}
-
-export function startRoomEdit(roomId) {
- return {
- type: START_ROOM_EDIT,
- roomId: roomId,
- }
-}
-
-export function finishRoomEdit() {
- return {
- type: FINISH_ROOM_EDIT,
- }
-}
-
-export function toggleTileAtLocation(positionX, positionY) {
- return (dispatch, getState) => {
- const { topology, construction } = getState()
-
- const roomId = construction.currentRoomInConstruction
- const tileIds = topology.rooms[roomId].tiles
- for (const tileId of tileIds) {
- if (topology.tiles[tileId].positionX === positionX && topology.tiles[tileId].positionY === positionY) {
- dispatch(deleteTile(tileId))
- return
- }
- }
-
- dispatch(addTile(roomId, positionX, positionY))
- }
-}
-
-export function addTile(roomId, positionX, positionY) {
- return {
- type: ADD_TILE,
- tile: {
- id: uuid(),
- roomId,
- positionX,
- positionY,
- },
- }
-}
-
-export function deleteTile(tileId) {
- return {
- type: DELETE_TILE,
- tileId,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/topology/index.js b/opendc-web/opendc-web-ui/src/redux/actions/topology/index.js
deleted file mode 100644
index d48af37a..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/topology/index.js
+++ /dev/null
@@ -1,40 +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.
- */
-
-export const OPEN_TOPOLOGY = 'OPEN_TOPOLOGY'
-export const STORE_TOPOLOGY = 'STORE_TOPOLOGY'
-
-export function openTopology(projectId, id) {
- return {
- type: OPEN_TOPOLOGY,
- projectId,
- id,
- }
-}
-
-export function storeTopology(topology, entities) {
- return {
- type: STORE_TOPOLOGY,
- topology,
- entities,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/topology/machine.js b/opendc-web/opendc-web-ui/src/redux/actions/topology/machine.js
deleted file mode 100644
index 93320884..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/topology/machine.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export const DELETE_MACHINE = 'DELETE_MACHINE'
-export const ADD_UNIT = 'ADD_UNIT'
-export const DELETE_UNIT = 'DELETE_UNIT'
-
-export function deleteMachine(machineId) {
- return {
- type: DELETE_MACHINE,
- machineId,
- }
-}
-
-export function addUnit(machineId, unitType, unitId) {
- return {
- type: ADD_UNIT,
- machineId,
- unitType,
- unitId,
- }
-}
-
-export function deleteUnit(machineId, unitType, unitId) {
- return {
- type: DELETE_UNIT,
- machineId,
- unitType,
- unitId,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/topology/rack.js b/opendc-web/opendc-web-ui/src/redux/actions/topology/rack.js
deleted file mode 100644
index 1f65952a..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/topology/rack.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { v4 as uuid } from 'uuid'
-
-export const EDIT_RACK_NAME = 'EDIT_RACK_NAME'
-export const DELETE_RACK = 'DELETE_RACK'
-export const ADD_MACHINE = 'ADD_MACHINE'
-
-export function editRackName(rackId, name) {
- return {
- type: EDIT_RACK_NAME,
- name,
- rackId,
- }
-}
-
-export function deleteRack(tileId, rackId) {
- return {
- type: DELETE_RACK,
- rackId,
- tileId,
- }
-}
-
-export function addMachine(rackId, position) {
- return {
- type: ADD_MACHINE,
- machine: {
- id: uuid(),
- rackId,
- position,
- cpus: [],
- gpus: [],
- memories: [],
- storages: [],
- },
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/actions/topology/room.js b/opendc-web/opendc-web-ui/src/redux/actions/topology/room.js
deleted file mode 100644
index 14cc126c..00000000
--- a/opendc-web/opendc-web-ui/src/redux/actions/topology/room.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import { v4 as uuid } from 'uuid'
-import {
- DEFAULT_RACK_SLOT_CAPACITY,
- DEFAULT_RACK_POWER_CAPACITY,
-} from '../../../components/topologies/map/MapConstants'
-import { findTileWithPosition } from '../../../util/tile-calculations'
-
-export const ADD_ROOM = 'ADD_ROOM'
-export const EDIT_ROOM_NAME = 'EDIT_ROOM_NAME'
-export const DELETE_ROOM = 'DELETE_ROOM'
-export const START_RACK_CONSTRUCTION = 'START_RACK_CONSTRUCTION'
-export const STOP_RACK_CONSTRUCTION = 'STOP_RACK_CONSTRUCTION'
-export const ADD_RACK_TO_TILE = 'ADD_RACK_TO_TILE'
-
-export function addRoom(topologyId, room) {
- return {
- type: ADD_ROOM,
- room: {
- id: uuid(),
- topologyId,
- ...room,
- },
- }
-}
-
-export function editRoomName(roomId, name) {
- return {
- type: EDIT_ROOM_NAME,
- name,
- roomId,
- }
-}
-
-export function startRackConstruction() {
- return {
- type: START_RACK_CONSTRUCTION,
- }
-}
-
-export function stopRackConstruction() {
- return {
- type: STOP_RACK_CONSTRUCTION,
- }
-}
-
-export function addRackToTile(positionX, positionY) {
- return (dispatch, getState) => {
- const { topology, interactionLevel } = getState()
- const currentRoom = topology.rooms[interactionLevel.roomId]
- const tiles = currentRoom.tiles.map((tileId) => topology.tiles[tileId])
- const tile = findTileWithPosition(tiles, positionX, positionY)
-
- if (tile !== null) {
- dispatch({
- type: ADD_RACK_TO_TILE,
- tileId: tile.id,
- rack: {
- id: uuid(),
- name: 'Rack',
- capacity: DEFAULT_RACK_SLOT_CAPACITY,
- powerCapacityW: DEFAULT_RACK_POWER_CAPACITY,
- machines: [],
- },
- })
- }
- }
-}
-
-export function deleteRoom(roomId) {
- return {
- type: DELETE_ROOM,
- roomId,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/index.js b/opendc-web/opendc-web-ui/src/redux/index.js
deleted file mode 100644
index 53cd9144..00000000
--- a/opendc-web/opendc-web-ui/src/redux/index.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { useMemo } from 'react'
-import { applyMiddleware, compose, createStore } from 'redux'
-import { createLogger } from 'redux-logger'
-import createSagaMiddleware from 'redux-saga'
-import thunk from 'redux-thunk'
-import rootReducer from './reducers'
-import rootSaga from './sagas'
-import { createReduxEnhancer } from '@sentry/react'
-import { sentryDsn } from '../config'
-
-let store
-
-function initStore(initialState, ctx) {
- const sagaMiddleware = createSagaMiddleware({ context: ctx })
-
- const middlewares = [thunk, sagaMiddleware]
-
- if (process.env.NODE_ENV !== 'production') {
- middlewares.push(createLogger())
- }
-
- let middleware = applyMiddleware(...middlewares)
-
- if (sentryDsn) {
- middleware = compose(middleware, createReduxEnhancer())
- }
-
- const configuredStore = createStore(rootReducer, initialState, middleware)
- sagaMiddleware.run(rootSaga)
- store = configuredStore
-
- return configuredStore
-}
-
-export const initializeStore = (preloadedState, ctx) => {
- let _store = store ?? initStore(preloadedState, ctx)
-
- // After navigating to a page with an initial Redux state, merge that state
- // with the current state in the store, and create a new store
- if (preloadedState && store) {
- _store = initStore({
- ...store.getState(),
- ...preloadedState,
- })
- // Reset the current store
- store = undefined
- }
-
- // For SSG and SSR always create a new store
- if (typeof window === 'undefined') return _store
- // Create the store once in the client
- if (!store) store = _store
-
- return _store
-}
-
-export function useStore(initialState, ctx) {
- return useMemo(() => initializeStore(initialState, ctx), [initialState, ctx])
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/construction-mode.js b/opendc-web/opendc-web-ui/src/redux/reducers/construction-mode.js
deleted file mode 100644
index d0aac5ae..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/construction-mode.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { combineReducers } from 'redux'
-import { GO_DOWN_ONE_INTERACTION_LEVEL } from '../actions/interaction-level'
-import {
- CANCEL_NEW_ROOM_CONSTRUCTION_SUCCEEDED,
- FINISH_NEW_ROOM_CONSTRUCTION,
- FINISH_ROOM_EDIT,
- START_NEW_ROOM_CONSTRUCTION_SUCCEEDED,
- START_ROOM_EDIT,
-} from '../actions/topology/building'
-import { DELETE_ROOM, START_RACK_CONSTRUCTION, STOP_RACK_CONSTRUCTION } from '../actions/topology/room'
-
-export function currentRoomInConstruction(state = '-1', action) {
- switch (action.type) {
- case START_NEW_ROOM_CONSTRUCTION_SUCCEEDED:
- return action.roomId
- case START_ROOM_EDIT:
- return action.roomId
- case CANCEL_NEW_ROOM_CONSTRUCTION_SUCCEEDED:
- case FINISH_NEW_ROOM_CONSTRUCTION:
- case FINISH_ROOM_EDIT:
- case DELETE_ROOM:
- return '-1'
- default:
- return state
- }
-}
-
-export function inRackConstructionMode(state = false, action) {
- switch (action.type) {
- case START_RACK_CONSTRUCTION:
- return true
- case STOP_RACK_CONSTRUCTION:
- case GO_DOWN_ONE_INTERACTION_LEVEL:
- return false
- default:
- return state
- }
-}
-
-export const construction = combineReducers({
- currentRoomInConstruction,
- inRackConstructionMode,
-})
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/index.js b/opendc-web/opendc-web-ui/src/redux/reducers/index.js
deleted file mode 100644
index 7ffb1211..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { combineReducers } from 'redux'
-import { construction } from './construction-mode'
-import { interactionLevel } from './interaction-level'
-import topology from './topology'
-
-const rootReducer = combineReducers({
- topology,
- construction,
- interactionLevel,
-})
-
-export default rootReducer
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/interaction-level.js b/opendc-web/opendc-web-ui/src/redux/reducers/interaction-level.js
deleted file mode 100644
index b30c68b9..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/interaction-level.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import {
- GO_DOWN_ONE_INTERACTION_LEVEL,
- GO_FROM_BUILDING_TO_ROOM,
- GO_FROM_RACK_TO_MACHINE,
- GO_FROM_ROOM_TO_RACK,
-} from '../actions/interaction-level'
-import { DELETE_MACHINE } from '../actions/topology/machine'
-import { DELETE_RACK } from '../actions/topology/rack'
-import { DELETE_ROOM } from '../actions/topology/room'
-
-export function interactionLevel(state = { mode: 'BUILDING' }, action) {
- switch (action.type) {
- case GO_FROM_BUILDING_TO_ROOM:
- return {
- mode: 'ROOM',
- roomId: action.roomId,
- }
- case GO_FROM_ROOM_TO_RACK:
- return {
- mode: 'RACK',
- roomId: state.roomId,
- tileId: action.tileId,
- }
- case GO_FROM_RACK_TO_MACHINE:
- return {
- mode: 'MACHINE',
- roomId: state.roomId,
- tileId: state.tileId,
- position: action.position,
- }
- case GO_DOWN_ONE_INTERACTION_LEVEL:
- if (state.mode === 'ROOM') {
- return {
- mode: 'BUILDING',
- }
- } else if (state.mode === 'RACK') {
- return {
- mode: 'ROOM',
- roomId: state.roomId,
- }
- } else if (state.mode === 'MACHINE') {
- return {
- mode: 'RACK',
- roomId: state.roomId,
- tileId: state.tileId,
- }
- } else {
- return state
- }
- case DELETE_MACHINE:
- return {
- mode: 'RACK',
- roomId: state.roomId,
- tileId: state.tileId,
- }
- case DELETE_RACK:
- return {
- mode: 'ROOM',
- roomId: state.roomId,
- }
- case DELETE_ROOM:
- return {
- mode: 'BUILDING',
- }
- default:
- return state
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/index.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/index.js
deleted file mode 100644
index 2c849387..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/index.js
+++ /dev/null
@@ -1,44 +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 { CPU_UNITS, GPU_UNITS, MEMORY_UNITS, STORAGE_UNITS } from '../../../util/unit-specifications'
-import machine from './machine'
-import rack from './rack'
-import room from './room'
-import tile from './tile'
-import topology from './topology'
-
-function objects(state = {}, action) {
- return {
- cpus: CPU_UNITS,
- gpus: GPU_UNITS,
- memories: MEMORY_UNITS,
- storages: STORAGE_UNITS,
- machines: machine(state.machines, action, state),
- racks: rack(state.racks, action, state),
- tiles: tile(state.tiles, action),
- rooms: room(state.rooms, action, state),
- root: topology(state.root, action, state),
- }
-}
-
-export default objects
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/machine.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/machine.js
deleted file mode 100644
index 1789257b..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/machine.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import produce from 'immer'
-import { STORE_TOPOLOGY } from '../../actions/topology'
-import { DELETE_MACHINE, ADD_UNIT, DELETE_UNIT } from '../../actions/topology/machine'
-import { ADD_MACHINE, DELETE_RACK } from '../../actions/topology/rack'
-
-function machine(state = {}, action, { racks }) {
- switch (action.type) {
- case STORE_TOPOLOGY:
- return action.entities.machines || {}
- case ADD_MACHINE:
- return produce(state, (draft) => {
- const { machine } = action
- draft[machine.id] = machine
- })
- case DELETE_MACHINE:
- return produce(state, (draft) => {
- const { machineId } = action
- delete draft[machineId]
- })
- case ADD_UNIT:
- return produce(state, (draft) => {
- const { machineId, unitType, unitId } = action
- draft[machineId][unitType].push(unitId)
- })
- case DELETE_UNIT:
- return produce(state, (draft) => {
- const { machineId, unitType, unitId } = action
- const units = draft[machineId][unitType]
- const index = units.indexOf(unitId)
- units.splice(index, 1)
- })
- case DELETE_RACK:
- return produce(state, (draft) => {
- const { rackId } = action
- const rack = racks[rackId]
-
- for (const id of rack.machines) {
- const machine = draft[id]
- machine.rackId = undefined
- }
- })
- default:
- return state
- }
-}
-
-export default machine
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/rack.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/rack.js
deleted file mode 100644
index ca79348a..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/rack.js
+++ /dev/null
@@ -1,66 +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 produce from 'immer'
-import { STORE_TOPOLOGY } from '../../actions/topology'
-import { DELETE_MACHINE } from '../../actions/topology/machine'
-import { DELETE_RACK, EDIT_RACK_NAME, ADD_MACHINE } from '../../actions/topology/rack'
-import { ADD_RACK_TO_TILE } from '../../actions/topology/room'
-
-function rack(state = {}, action, { machines }) {
- switch (action.type) {
- case STORE_TOPOLOGY:
- return action.entities.racks || {}
- case ADD_RACK_TO_TILE:
- return produce(state, (draft) => {
- const { rack } = action
- draft[rack.id] = rack
- })
- case EDIT_RACK_NAME:
- return produce(state, (draft) => {
- const { rackId, name } = action
- draft[rackId].name = name
- })
- case DELETE_RACK:
- return produce(state, (draft) => {
- const { rackId } = action
- delete draft[rackId]
- })
- case ADD_MACHINE:
- return produce(state, (draft) => {
- const { machine } = action
- draft[machine.rackId].machines.push(machine.id)
- })
- case DELETE_MACHINE:
- return produce(state, (draft) => {
- const { machineId } = action
- const machine = machines[machineId]
- const rack = draft[machine.rackId]
- const index = rack.machines.indexOf(machineId)
- rack.machines.splice(index, 1)
- })
- default:
- return state
- }
-}
-
-export default rack
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/room.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/room.js
deleted file mode 100644
index c05c8bfa..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/room.js
+++ /dev/null
@@ -1,65 +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 produce from 'immer'
-import { STORE_TOPOLOGY } from '../../actions/topology'
-import { ADD_TILE, DELETE_TILE } from '../../actions/topology/building'
-import { DELETE_ROOM, EDIT_ROOM_NAME, ADD_ROOM } from '../../actions/topology/room'
-
-function room(state = {}, action, { tiles }) {
- switch (action.type) {
- case STORE_TOPOLOGY:
- return action.entities.rooms || {}
- case ADD_ROOM:
- return produce(state, (draft) => {
- const { room } = action
- draft[room.id] = room
- })
- case DELETE_ROOM:
- return produce(state, (draft) => {
- const { roomId } = action
- delete draft[roomId]
- })
- case EDIT_ROOM_NAME:
- return produce(state, (draft) => {
- const { roomId, name } = action
- draft[roomId].name = name
- })
- case ADD_TILE:
- return produce(state, (draft) => {
- const { tile } = action
- draft[tile.roomId].tiles.push(tile.id)
- })
- case DELETE_TILE:
- return produce(state, (draft) => {
- const { tileId } = action
- const tile = tiles[tileId]
- const room = draft[tile.roomId]
- const index = room.tiles.indexOf(tileId)
- room.tiles.splice(index, 1)
- })
- default:
- return state
- }
-}
-
-export default room
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/tile.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/tile.js
deleted file mode 100644
index 24c0e20c..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/tile.js
+++ /dev/null
@@ -1,58 +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 produce from 'immer'
-import { STORE_TOPOLOGY } from '../../actions/topology'
-import { ADD_TILE, DELETE_TILE } from '../../actions/topology/building'
-import { DELETE_RACK } from '../../actions/topology/rack'
-import { ADD_RACK_TO_TILE } from '../../actions/topology/room'
-
-function tile(state = {}, action) {
- switch (action.type) {
- case STORE_TOPOLOGY:
- return action.entities.tiles || {}
- case ADD_TILE:
- return produce(state, (draft) => {
- const { tile } = action
- draft[tile.id] = tile
- })
- case DELETE_TILE:
- return produce(state, (draft) => {
- const { tileId } = action
- delete draft[tileId]
- })
- case ADD_RACK_TO_TILE:
- return produce(state, (draft) => {
- const { rack, tileId } = action
- draft[tileId].rack = rack.id
- })
- case DELETE_RACK:
- return produce(state, (draft) => {
- const { tileId } = action
- draft[tileId].rack = undefined
- })
- default:
- return state
- }
-}
-
-export default tile
diff --git a/opendc-web/opendc-web-ui/src/redux/reducers/topology/topology.js b/opendc-web/opendc-web-ui/src/redux/reducers/topology/topology.js
deleted file mode 100644
index dff0a69e..00000000
--- a/opendc-web/opendc-web-ui/src/redux/reducers/topology/topology.js
+++ /dev/null
@@ -1,47 +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 produce from 'immer'
-import { STORE_TOPOLOGY } from '../../actions/topology'
-import { ADD_ROOM, DELETE_ROOM } from '../../actions/topology/room'
-
-function topology(state = undefined, action) {
- switch (action.type) {
- case STORE_TOPOLOGY:
- return action.topology
- case ADD_ROOM:
- return produce(state, (draft) => {
- const { room } = action
- draft.rooms.push(room.id)
- })
- case DELETE_ROOM:
- return produce(state, (draft) => {
- const { roomId } = action
- const index = draft.rooms.indexOf(roomId)
- draft.rooms.splice(index, 1)
- })
- default:
- return state
- }
-}
-
-export default topology
diff --git a/opendc-web/opendc-web-ui/src/redux/sagas/index.js b/opendc-web/opendc-web-ui/src/redux/sagas/index.js
deleted file mode 100644
index 0fabdb6d..00000000
--- a/opendc-web/opendc-web-ui/src/redux/sagas/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { fork } from 'redux-saga/effects'
-import { watchServer, updateServer } from './topology'
-
-export default function* rootSaga() {
- yield fork(watchServer)
- yield fork(updateServer)
-}
diff --git a/opendc-web/opendc-web-ui/src/redux/sagas/topology.js b/opendc-web/opendc-web-ui/src/redux/sagas/topology.js
deleted file mode 100644
index 15147bcf..00000000
--- a/opendc-web/opendc-web-ui/src/redux/sagas/topology.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { QueryObserver, MutationObserver } from 'react-query'
-import { normalize, denormalize } from 'normalizr'
-import { select, put, take, race, getContext, call } from 'redux-saga/effects'
-import { eventChannel } from 'redux-saga'
-import { Topology } from '../../util/topology-schema'
-import { storeTopology, OPEN_TOPOLOGY } from '../actions/topology'
-
-/**
- * Update the topology on the server.
- */
-export function* updateServer() {
- const queryClient = yield getContext('queryClient')
- const mutationObserver = new MutationObserver(queryClient, { mutationKey: 'updateTopology' })
-
- while (true) {
- yield take(
- (action) =>
- action.type.startsWith('EDIT') || action.type.startsWith('ADD') || action.type.startsWith('DELETE')
- )
- const topology = yield select((state) => state.topology)
-
- if (!topology.root) {
- continue
- }
-
- const denormalizedTopology = denormalize(topology.root, Topology, topology)
- yield call([mutationObserver, mutationObserver.mutate], denormalizedTopology)
- }
-}
-
-/**
- * Watch the topology on the server for changes.
- */
-export function* watchServer() {
- let { projectId, id } = yield take(OPEN_TOPOLOGY)
- while (true) {
- const channel = yield queryObserver(projectId, id)
-
- while (true) {
- const [action, response] = yield race([take(OPEN_TOPOLOGY), take(channel)])
-
- if (action) {
- projectId = action.projectId
- id = action.id
- break
- }
-
- const { isFetched, data } = response
- // Only update the topology on the client-side when a new topology was fetched
- if (isFetched) {
- const { result: topologyId, entities } = normalize(data, Topology)
- yield put(storeTopology(entities.topologies[topologyId], entities))
- }
- }
- }
-}
-
-/**
- * Observe changes for the topology with the specified identifier.
- */
-function* queryObserver(projectId, id) {
- const queryClient = yield getContext('queryClient')
- const observer = new QueryObserver(queryClient, { queryKey: ['topologies', projectId, id] })
-
- return eventChannel((emitter) => {
- const unsubscribe = observer.subscribe((result) => {
- emitter(result)
- })
-
- // Update result to make sure we did not miss any query updates
- // between creating the observer and subscribing to it.
- observer.updateResult()
-
- return unsubscribe
- })
-}
diff --git a/opendc-web/opendc-web-ui/src/shapes.js b/opendc-web/opendc-web-ui/src/shapes.js
deleted file mode 100644
index 50b82361..00000000
--- a/opendc-web/opendc-web-ui/src/shapes.js
+++ /dev/null
@@ -1,187 +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 PropTypes from 'prop-types'
-
-export const ProjectRole = PropTypes.oneOf(['VIEWER', 'EDITOR', 'OWNER'])
-
-export const Project = PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- createdAt: PropTypes.string.isRequired,
- updatedAt: PropTypes.string.isRequired,
- role: ProjectRole,
-})
-
-export const ProcessingUnit = PropTypes.shape({
- id: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- clockRateMhz: PropTypes.number.isRequired,
- numberOfCores: PropTypes.number.isRequired,
- energyConsumptionW: PropTypes.number.isRequired,
-})
-
-export const StorageUnit = PropTypes.shape({
- id: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- speedMbPerS: PropTypes.number.isRequired,
- sizeMb: PropTypes.number.isRequired,
- energyConsumptionW: PropTypes.number.isRequired,
-})
-
-export const Machine = PropTypes.shape({
- id: PropTypes.string.isRequired,
- position: PropTypes.number.isRequired,
- cpus: PropTypes.arrayOf(PropTypes.oneOfType([ProcessingUnit, PropTypes.string])),
- gpus: PropTypes.arrayOf(PropTypes.oneOfType([ProcessingUnit, PropTypes.string])),
- memories: PropTypes.arrayOf(PropTypes.oneOfType([StorageUnit, PropTypes.string])),
- storages: PropTypes.arrayOf(PropTypes.oneOfType([StorageUnit, PropTypes.string])),
-})
-
-export const Rack = PropTypes.shape({
- id: PropTypes.string.isRequired,
- capacity: PropTypes.number.isRequired,
- powerCapacityW: PropTypes.number.isRequired,
- machines: PropTypes.arrayOf(PropTypes.oneOfType([Machine, PropTypes.string])),
-})
-
-export const Tile = PropTypes.shape({
- id: PropTypes.string.isRequired,
- positionX: PropTypes.number.isRequired,
- positionY: PropTypes.number.isRequired,
- rack: PropTypes.oneOfType([Rack, PropTypes.string]),
-})
-
-export const Room = PropTypes.shape({
- id: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- tiles: PropTypes.arrayOf(PropTypes.oneOfType([Tile, PropTypes.string])),
-})
-
-export const Topology = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- project: Project.isRequired,
- name: PropTypes.string.isRequired,
- rooms: PropTypes.arrayOf(PropTypes.oneOfType([Room, PropTypes.string])),
-})
-
-export const Phenomena = PropTypes.shape({
- failures: PropTypes.bool.isRequired,
- interference: PropTypes.bool.isRequired,
-})
-
-export const Scheduler = PropTypes.shape({
- name: PropTypes.string.isRequired,
-})
-
-export const Trace = PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- type: PropTypes.string.isRequired,
-})
-
-export const Workload = PropTypes.shape({
- trace: Trace.isRequired,
- samplingFraction: PropTypes.number.isRequired,
-})
-
-export const Targets = PropTypes.shape({
- repeats: PropTypes.number.isRequired,
- metrics: PropTypes.arrayOf(PropTypes.string).isRequired,
-})
-
-export const TopologySummary = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- project: Project.isRequired,
- name: PropTypes.string.isRequired,
-})
-
-export const PortfolioSummary = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- project: Project.isRequired,
- name: PropTypes.string.isRequired,
- targets: PropTypes.shape({
- repeats: PropTypes.number.isRequired,
- metrics: PropTypes.arrayOf(PropTypes.string).isRequired,
- }).isRequired,
-})
-
-export const ScenarioSummary = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- workload: Workload.isRequired,
- topology: TopologySummary.isRequired,
- phenomena: Phenomena.isRequired,
- schedulerName: PropTypes.string.isRequired,
- results: PropTypes.object,
-})
-
-export const JobState = PropTypes.oneOf(['PENDING', 'CLAIMED', 'RUNNING', 'FAILED', 'FINISHED'])
-
-export const Job = PropTypes.shape({
- id: PropTypes.number.isRequired,
- state: JobState.isRequired,
- createdAt: PropTypes.string.isRequired,
- updatedAt: PropTypes.string.isRequired,
- results: PropTypes.object,
-})
-
-export const Scenario = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- project: Project.isRequired,
- portfolio: PortfolioSummary.isRequired,
- name: PropTypes.string.isRequired,
- workload: Workload.isRequired,
- topology: TopologySummary.isRequired,
- phenomena: Phenomena.isRequired,
- schedulerName: PropTypes.string.isRequired,
- jobs: PropTypes.arrayOf(Job).isRequired,
-})
-
-export const Portfolio = PropTypes.shape({
- id: PropTypes.number.isRequired,
- number: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- project: Project.isRequired,
- targets: Targets.isRequired,
- scenarios: PropTypes.arrayOf(ScenarioSummary).isRequired,
-})
-
-export const WallSegment = PropTypes.shape({
- startPosX: PropTypes.number.isRequired,
- startPosY: PropTypes.number.isRequired,
- isHorizontal: PropTypes.bool.isRequired,
- length: PropTypes.number.isRequired,
-})
-
-export const InteractionLevel = PropTypes.shape({
- mode: PropTypes.string.isRequired,
- roomId: PropTypes.string,
- rackId: PropTypes.string,
-})
-
-export const Status = PropTypes.oneOf(['idle', 'loading', 'error', 'success'])
diff --git a/opendc-web/opendc-web-ui/src/style/index.css b/opendc-web/opendc-web-ui/src/style/index.css
deleted file mode 100644
index 7b7103a4..00000000
--- a/opendc-web/opendc-web-ui/src/style/index.css
+++ /dev/null
@@ -1,28 +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.
- */
-
-body,
-#__next {
- height: 100%;
-
- background: #eee;
-}
diff --git a/opendc-web/opendc-web-ui/src/util/authorizations.js b/opendc-web/opendc-web-ui/src/util/authorizations.js
deleted file mode 100644
index 6cb08ba8..00000000
--- a/opendc-web/opendc-web-ui/src/util/authorizations.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import HomeIcon from '@patternfly/react-icons/dist/js/icons/home-icon'
-import EditIcon from '@patternfly/react-icons/dist/js/icons/edit-icon'
-import EyeIcon from '@patternfly/react-icons/dist/js/icons/eye-icon'
-
-export const AUTH_ICON_MAP = {
- OWNER: HomeIcon,
- EDITOR: EditIcon,
- VIEWER: EyeIcon,
-}
-
-export const AUTH_NAME_MAP = {
- OWNER: 'Owner',
- EDITOR: 'Editor',
- VIEWER: 'Viewer',
-}
-
-export const AUTH_DESCRIPTION_MAP = {
- OWNER: 'You own this project',
- EDITOR: 'You can edit this project',
- VIEWER: 'You can view this project',
-}
diff --git a/opendc-web/opendc-web-ui/src/util/available-metrics.js b/opendc-web/opendc-web-ui/src/util/available-metrics.js
deleted file mode 100644
index fda6cd4d..00000000
--- a/opendc-web/opendc-web-ui/src/util/available-metrics.js
+++ /dev/null
@@ -1,101 +0,0 @@
-export const METRIC_GROUPS = {
- 'Host Metrics': [
- 'total_overcommitted_burst',
- 'total_power_draw',
- 'total_failure_vm_slices',
- 'total_granted_burst',
- 'total_interfered_burst',
- 'total_requested_burst',
- 'mean_cpu_usage',
- 'mean_cpu_demand',
- 'mean_num_deployed_images',
- 'max_num_deployed_images',
- ],
- 'Compute Service Metrics': ['total_vms_submitted', 'total_vms_queued', 'total_vms_finished', 'total_vms_failed'],
-}
-
-export const AVAILABLE_METRICS = [
- 'mean_cpu_usage',
- 'mean_cpu_demand',
- 'total_requested_burst',
- 'total_granted_burst',
- 'total_overcommitted_burst',
- 'total_interfered_burst',
- 'total_power_draw',
- 'total_failure_vm_slices',
- 'mean_num_deployed_images',
- 'max_num_deployed_images',
- 'total_vms_submitted',
- 'total_vms_queued',
- 'total_vms_finished',
- 'total_vms_failed',
-]
-
-export const METRIC_NAMES_SHORT = {
- total_overcommitted_burst: 'Overcomm. CPU Cycles',
- total_granted_burst: 'Granted CPU Cycles',
- total_requested_burst: 'Requested CPU Cycles',
- total_interfered_burst: 'Interfered CPU Cycles',
- total_power_draw: 'Total Power Consumption',
- mean_cpu_usage: 'Mean Host CPU Usage',
- mean_cpu_demand: 'Mean Host CPU Demand',
- mean_num_deployed_images: 'Mean Num. Deployed Images Per Host',
- max_num_deployed_images: 'Max. Num. Deployed Images Per Host',
- total_failure_vm_slices: 'Total Num. Failed VM Slices',
- total_vms_submitted: 'VMs Submitted',
- total_vms_queued: 'VMs Queued',
- total_vms_finished: 'VMs Finished',
- total_vms_failed: 'VMs Failed',
-}
-
-export const METRIC_NAMES = {
- total_overcommitted_burst: 'Overcommitted CPU Cycles',
- total_granted_burst: 'Granted CPU Cycles',
- total_requested_burst: 'Requested CPU Cycles',
- total_interfered_burst: 'Interfered CPU Cycles',
- total_power_draw: 'Total Power Consumption',
- mean_cpu_usage: 'Mean Host CPU Usage',
- mean_cpu_demand: 'Mean Host CPU Demand',
- mean_num_deployed_images: 'Mean Number of Deployed Images Per Host',
- max_num_deployed_images: 'Maximum Number Deployed Images Per Host',
- total_failure_vm_slices: 'Failed VM Slices',
- total_vms_submitted: 'VMs Submitted',
- total_vms_queued: 'VMs Queued',
- total_vms_finished: 'VMs Finished',
- total_vms_failed: 'VMs Failed',
-}
-
-export const METRIC_UNITS = {
- total_overcommitted_burst: 'MFLOP',
- total_granted_burst: 'MFLOP',
- total_requested_burst: 'MFLOP',
- total_interfered_burst: 'MFLOP',
- total_power_draw: 'Wh',
- mean_cpu_usage: 'MHz',
- mean_cpu_demand: 'MHz',
- mean_num_deployed_images: 'VMs',
- max_num_deployed_images: 'VMs',
- total_failure_vm_slices: 'VM Slices',
- total_vms_submitted: 'VMs',
- total_vms_queued: 'VMs',
- total_vms_finished: 'VMs',
- total_vms_failed: 'VMs',
-}
-
-export const METRIC_DESCRIPTIONS = {
- total_overcommitted_burst:
- 'The total CPU clock cycles lost due to overcommitting of resources. This metric is an indicator for resource overload.',
- total_requested_burst: 'The total CPU clock cycles that were requested by all virtual machines.',
- total_granted_burst: 'The total CPU clock cycles executed by the hosts.',
- total_interfered_burst: 'The total CPU clock cycles lost due to resource interference between virtual machines.',
- total_power_draw: 'The average power usage in watts.',
- mean_cpu_usage: 'The average amount of CPU clock cycles consumed by all virtual machines on a host.',
- mean_cpu_demand: 'The average amount of CPU clock cycles requested by all powered on virtual machines on a host.',
- mean_num_deployed_images: 'The average number of virtual machines deployed on a host.',
- max_num_deployed_images: 'The maximum number of virtual machines deployed at any time.',
- total_failure_vm_slices: 'The total amount of CPU clock cycles lost due to failure.',
- total_vms_submitted: 'The number of virtual machines scheduled by the compute service.',
- total_vms_queued: 'The number of virtual machines still waiting to be scheduled by the compute service.',
- total_vms_finished: 'The number of virtual machines that completed.',
- total_vms_failed: 'The number of virtual machines that could not be scheduled.',
-}
diff --git a/opendc-web/opendc-web-ui/src/util/colors.js b/opendc-web/opendc-web-ui/src/util/colors.js
deleted file mode 100644
index 34468503..00000000
--- a/opendc-web/opendc-web-ui/src/util/colors.js
+++ /dev/null
@@ -1,29 +0,0 @@
-export const GRID_COLOR = 'rgba(0, 0, 0, 0.5)'
-export const BACKDROP_COLOR = 'rgba(255, 255, 255, 1)'
-export const WALL_COLOR = 'rgba(0, 0, 0, 1)'
-
-export const ROOM_DEFAULT_COLOR = 'rgba(150, 150, 150, 1)'
-export const ROOM_IN_CONSTRUCTION_COLOR = 'rgba(51, 153, 255, 1)'
-export const ROOM_HOVER_VALID_COLOR = 'rgba(51, 153, 255, 1)'
-export const ROOM_HOVER_INVALID_COLOR = 'rgba(255, 102, 0, 1)'
-export const ROOM_NAME_COLOR = 'rgba(245, 245, 245, 1)'
-export const ROOM_TYPE_COLOR = 'rgba(245, 245, 245, 1)'
-
-export const TILE_PLUS_COLOR = 'rgba(0, 0, 0, 1)'
-
-export const OBJECT_BORDER_COLOR = 'rgba(0, 0, 0, 1)'
-
-export const RACK_BACKGROUND_COLOR = 'rgba(170, 170, 170, 1)'
-export const RACK_SPACE_BAR_BACKGROUND_COLOR = 'rgba(222, 235, 247, 0.6)'
-export const RACK_SPACE_BAR_FILL_COLOR = 'rgba(91, 155, 213, 0.7)'
-export const RACK_ENERGY_BAR_BACKGROUND_COLOR = 'rgba(255, 242, 204, 0.6)'
-export const RACK_ENERGY_BAR_FILL_COLOR = 'rgba(244, 215, 0, 0.7)'
-export const COOLING_ITEM_BACKGROUND_COLOR = 'rgba(40, 50, 230, 1)'
-export const PSU_BACKGROUND_COLOR = 'rgba(230, 50, 60, 1)'
-
-export const GRAYED_OUT_AREA_COLOR = 'rgba(0, 0, 0, 0.6)'
-
-export const SIM_LOW_COLOR = 'rgba(197, 224, 180, 1)'
-export const SIM_MID_LOW_COLOR = 'rgba(255, 230, 153, 1)'
-export const SIM_MID_HIGH_COLOR = 'rgba(248, 203, 173, 1)'
-export const SIM_HIGH_COLOR = 'rgba(249, 165, 165, 1)'
diff --git a/opendc-web/opendc-web-ui/src/util/date-time.js b/opendc-web/opendc-web-ui/src/util/date-time.js
deleted file mode 100644
index 7e2f6623..00000000
--- a/opendc-web/opendc-web-ui/src/util/date-time.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Parses and formats the given date-time string representation.
- *
- * The format assumed is "YYYY-MM-DDTHH:MM:SS".
- *
- * @param dateTimeString A string expressing a date and a time, in the above mentioned format.
- * @returns {string} A human-friendly string version of that date and time.
- */
-export function parseAndFormatDateTime(dateTimeString) {
- return formatDateTime(new Date(dateTimeString))
-}
-
-/**
- * Serializes the given date and time value to a human-friendly string.
- *
- * @param dateTime An object representation of a date and time.
- * @returns {string} A human-friendly string version of that date and time.
- */
-export function formatDateTime(dateTime) {
- let date
- const currentDate = new Date()
-
- date =
- addPaddingToTwo(dateTime.getDay()) +
- '/' +
- addPaddingToTwo(dateTime.getMonth()) +
- '/' +
- addPaddingToTwo(dateTime.getFullYear())
-
- if (dateTime.getFullYear() === currentDate.getFullYear() && dateTime.getMonth() === currentDate.getMonth()) {
- if (dateTime.getDate() === currentDate.getDate()) {
- date = 'Today'
- } else if (dateTime.getDate() === currentDate.getDate() - 1) {
- date = 'Yesterday'
- }
- }
-
- return date + ', ' + addPaddingToTwo(dateTime.getHours()) + ':' + addPaddingToTwo(dateTime.getMinutes())
-}
-
-/**
- * Formats the given number of seconds/ticks to a formatted time representation.
- *
- * @param seconds The number of seconds.
- * @returns {string} A string representation of that amount of second, in the from of HH:MM:SS.
- */
-export function convertSecondsToFormattedTime(seconds) {
- if (seconds <= 0) {
- return '0s'
- }
-
- let hour = Math.floor(seconds / 3600)
- let minute = Math.floor(seconds / 60) % 60
- let second = seconds % 60
-
- hour = isNaN(hour) ? 0 : hour
- minute = isNaN(minute) ? 0 : minute
- second = isNaN(second) ? 0 : second
-
- if (hour === 0 && minute === 0) {
- return second + 's'
- } else if (hour === 0) {
- return minute + 'm' + addPaddingToTwo(second) + 's'
- } else {
- return hour + 'h' + addPaddingToTwo(minute) + 'm' + addPaddingToTwo(second) + 's'
- }
-}
-
-/**
- * Pads the given integer to have at least two digits.
- *
- * @param integer An integer to be padded.
- * @returns {string} A string containing the padded integer.
- */
-function addPaddingToTwo(integer) {
- if (integer < 10) {
- return '0' + integer.toString()
- } else {
- return integer.toString()
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/util/date-time.test.js b/opendc-web/opendc-web-ui/src/util/date-time.test.js
deleted file mode 100644
index 431e39f7..00000000
--- a/opendc-web/opendc-web-ui/src/util/date-time.test.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { convertSecondsToFormattedTime } from './date-time'
-
-describe('tick formatting', () => {
- it("returns '0s' for numbers <= 0", () => {
- expect(convertSecondsToFormattedTime(-1)).toEqual('0s')
- expect(convertSecondsToFormattedTime(0)).toEqual('0s')
- })
- it('returns only seconds for values under a minute', () => {
- expect(convertSecondsToFormattedTime(1)).toEqual('1s')
- expect(convertSecondsToFormattedTime(59)).toEqual('59s')
- })
- it('returns seconds and minutes for values under an hour', () => {
- expect(convertSecondsToFormattedTime(60)).toEqual('1m00s')
- expect(convertSecondsToFormattedTime(61)).toEqual('1m01s')
- expect(convertSecondsToFormattedTime(3599)).toEqual('59m59s')
- })
- it('returns full time for values over an hour', () => {
- expect(convertSecondsToFormattedTime(3600)).toEqual('1h00m00s')
- expect(convertSecondsToFormattedTime(3601)).toEqual('1h00m01s')
- })
-})
diff --git a/opendc-web/opendc-web-ui/src/util/effect-ref.js b/opendc-web/opendc-web-ui/src/util/effect-ref.js
deleted file mode 100644
index 78528585..00000000
--- a/opendc-web/opendc-web-ui/src/util/effect-ref.js
+++ /dev/null
@@ -1,41 +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 { useCallback, useRef } from 'react'
-
-const noop = () => {}
-
-/**
- * A hook that will invoke the specified callback when the reference returned by this function is initialized.
- * The callback can return an optional clean-up function.
- */
-export function useEffectRef(callback, deps = []) {
- const disposeRef = useRef(noop)
- return useCallback((element) => {
- disposeRef.current()
- disposeRef.current = noop
-
- if (element) {
- disposeRef.current = callback(element) || noop
- }
- }, deps) // eslint-disable-line react-hooks/exhaustive-deps
-}
diff --git a/opendc-web/opendc-web-ui/src/util/tile-calculations.js b/opendc-web/opendc-web-ui/src/util/tile-calculations.js
deleted file mode 100644
index 374ca48c..00000000
--- a/opendc-web/opendc-web-ui/src/util/tile-calculations.js
+++ /dev/null
@@ -1,255 +0,0 @@
-export function deriveWallLocations(tiles) {
- const { verticalWalls, horizontalWalls } = getWallSegments(tiles)
- return mergeWallSegments(verticalWalls, horizontalWalls)
-}
-
-function getWallSegments(tiles) {
- const verticalWalls = {}
- const horizontalWalls = {}
-
- tiles.forEach((tile) => {
- const x = tile.positionX,
- y = tile.positionY
-
- for (let dX = -1; dX <= 1; dX++) {
- for (let dY = -1; dY <= 1; dY++) {
- if (Math.abs(dX) === Math.abs(dY)) {
- continue
- }
-
- let doInsert = true
- for (const tile of tiles) {
- if (tile.positionX === x + dX && tile.positionY === y + dY) {
- doInsert = false
- break
- }
- }
- if (!doInsert) {
- continue
- }
-
- if (dX === -1) {
- if (verticalWalls[x] === undefined) {
- verticalWalls[x] = []
- }
- if (verticalWalls[x].indexOf(y) === -1) {
- verticalWalls[x].push(y)
- }
- } else if (dX === 1) {
- if (verticalWalls[x + 1] === undefined) {
- verticalWalls[x + 1] = []
- }
- if (verticalWalls[x + 1].indexOf(y) === -1) {
- verticalWalls[x + 1].push(y)
- }
- } else if (dY === -1) {
- if (horizontalWalls[y] === undefined) {
- horizontalWalls[y] = []
- }
- if (horizontalWalls[y].indexOf(x) === -1) {
- horizontalWalls[y].push(x)
- }
- } else if (dY === 1) {
- if (horizontalWalls[y + 1] === undefined) {
- horizontalWalls[y + 1] = []
- }
- if (horizontalWalls[y + 1].indexOf(x) === -1) {
- horizontalWalls[y + 1].push(x)
- }
- }
- }
- }
- })
-
- return { verticalWalls, horizontalWalls }
-}
-
-function mergeWallSegments(vertical, horizontal) {
- const result = []
- const walls = [vertical, horizontal]
-
- for (let i = 0; i < 2; i++) {
- const wallList = walls[i]
- for (let a in wallList) {
- a = parseInt(a, 10)
-
- wallList[a].sort((a, b) => {
- return a - b
- })
-
- let startPos = wallList[a][0]
- const isHorizontal = i === 1
-
- if (wallList[a].length === 1) {
- const startPosX = isHorizontal ? startPos : a
- const startPosY = isHorizontal ? a : startPos
- result.push({
- startPosX,
- startPosY,
- isHorizontal,
- length: 1,
- })
- } else {
- let consecutiveCount = 1
- for (let b = 0; b < wallList[a].length - 1; b++) {
- if (b + 1 === wallList[a].length - 1) {
- if (wallList[a][b + 1] - wallList[a][b] > 1) {
- const startPosX = isHorizontal ? startPos : a
- const startPosY = isHorizontal ? a : startPos
- result.push({
- startPosX,
- startPosY,
- isHorizontal,
- length: consecutiveCount,
- })
- consecutiveCount = 0
- startPos = wallList[a][b + 1]
- }
- const startPosX = isHorizontal ? startPos : a
- const startPosY = isHorizontal ? a : startPos
- result.push({
- startPosX,
- startPosY,
- isHorizontal,
- length: consecutiveCount + 1,
- })
- break
- } else if (wallList[a][b + 1] - wallList[a][b] > 1) {
- const startPosX = isHorizontal ? startPos : a
- const startPosY = isHorizontal ? a : startPos
- result.push({
- startPosX,
- startPosY,
- isHorizontal,
- length: consecutiveCount,
- })
- startPos = wallList[a][b + 1]
- consecutiveCount = 0
- }
- consecutiveCount++
- }
- }
- }
- }
-
- return result
-}
-
-export function deriveValidNextTilePositions(rooms, selectedTiles) {
- const result = [],
- newPosition = { x: 0, y: 0 }
- let isSurroundingTile
-
- selectedTiles.forEach((tile) => {
- const x = tile.positionX
- const y = tile.positionY
- result.push({ x, y })
-
- for (let dX = -1; dX <= 1; dX++) {
- for (let dY = -1; dY <= 1; dY++) {
- if (Math.abs(dX) === Math.abs(dY)) {
- continue
- }
-
- newPosition.x = x + dX
- newPosition.y = y + dY
-
- isSurroundingTile = true
- for (let index in selectedTiles) {
- if (
- selectedTiles[index].positionX === newPosition.x &&
- selectedTiles[index].positionY === newPosition.y
- ) {
- isSurroundingTile = false
- break
- }
- }
-
- if (isSurroundingTile && findPositionInRooms(rooms, newPosition.x, newPosition.y) === -1) {
- result.push({ x: newPosition.x, y: newPosition.y })
- }
- }
- }
- })
-
- return result
-}
-
-export function findPositionInPositions(positions, positionX, positionY) {
- for (let i = 0; i < positions.length; i++) {
- const position = positions[i]
- if (positionX === position.x && positionY === position.y) {
- return i
- }
- }
-
- return -1
-}
-
-export function findPositionInRooms(rooms, positionX, positionY) {
- for (let i = 0; i < rooms.length; i++) {
- const room = rooms[i]
- if (findPositionInTiles(room.tiles, positionX, positionY) !== -1) {
- return i
- }
- }
-
- return -1
-}
-
-function findPositionInTiles(tiles, positionX, positionY) {
- let index = -1
-
- for (let i = 0; i < tiles.length; i++) {
- const tile = tiles[i]
- if (positionX === tile.positionX && positionY === tile.positionY) {
- index = i
- break
- }
- }
-
- return index
-}
-
-export function findTileWithPosition(tiles, positionX, positionY) {
- for (let i = 0; i < tiles.length; i++) {
- if (tiles[i].positionX === positionX && tiles[i].positionY === positionY) {
- return tiles[i]
- }
- }
-
- return null
-}
-
-export function calculateRoomListBounds(rooms) {
- const min = { x: Number.MAX_VALUE, y: Number.MAX_VALUE }
- const max = { x: -1, y: -1 }
-
- rooms.forEach((room) => {
- room.tiles.forEach((tile) => {
- if (tile.positionX < min.x) {
- min.x = tile.positionX
- }
- if (tile.positionY < min.y) {
- min.y = tile.positionY
- }
-
- if (tile.positionX > max.x) {
- max.x = tile.positionX
- }
- if (tile.positionY > max.y) {
- max.y = tile.positionY
- }
- })
- })
-
- max.x++
- max.y++
-
- const center = {
- x: min.x + (max.x - min.x) / 2.0,
- y: min.y + (max.y - min.y) / 2.0,
- }
-
- return { min, center, max }
-}
diff --git a/opendc-web/opendc-web-ui/src/util/topology-schema.js b/opendc-web/opendc-web-ui/src/util/topology-schema.js
deleted file mode 100644
index ff672dd6..00000000
--- a/opendc-web/opendc-web-ui/src/util/topology-schema.js
+++ /dev/null
@@ -1,47 +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 { schema } from 'normalizr'
-
-const Cpu = new schema.Entity('cpus', {}, { idAttribute: 'id' })
-const Gpu = new schema.Entity('gpus', {}, { idAttribute: 'id' })
-const Memory = new schema.Entity('memories', {}, { idAttribute: 'id' })
-const Storage = new schema.Entity('storages', {}, { idAttribute: 'id' })
-
-export const Machine = new schema.Entity(
- 'machines',
- {
- cpus: [Cpu],
- gpus: [Gpu],
- memories: [Memory],
- storages: [Storage],
- },
- { idAttribute: 'id' }
-)
-
-export const Rack = new schema.Entity('racks', { machines: [Machine] }, { idAttribute: 'id' })
-
-export const Tile = new schema.Entity('tiles', { rack: Rack }, { idAttribute: 'id' })
-
-export const Room = new schema.Entity('rooms', { tiles: [Tile] }, { idAttribute: 'id' })
-
-export const Topology = new schema.Entity('topologies', { rooms: [Room] }, { idAttribute: 'id' })
diff --git a/opendc-web/opendc-web-ui/src/util/unit-specifications.js b/opendc-web/opendc-web-ui/src/util/unit-specifications.js
deleted file mode 100644
index 3e3671cd..00000000
--- a/opendc-web/opendc-web-ui/src/util/unit-specifications.js
+++ /dev/null
@@ -1,102 +0,0 @@
-export const CPU_UNITS = {
- 'cpu-1': {
- id: 'cpu-1',
- name: 'Intel i7 v6 6700k',
- clockRateMhz: 4100,
- numberOfCores: 4,
- energyConsumptionW: 70,
- },
- 'cpu-2': {
- id: 'cpu-2',
- name: 'Intel i5 v6 6700k',
- clockRateMhz: 3500,
- numberOfCores: 2,
- energyConsumptionW: 50,
- },
- 'cpu-3': {
- id: 'cpu-3',
- name: 'Intel® Xeon® E-2224G',
- clockRateMhz: 3500,
- numberOfCores: 4,
- energyConsumptionW: 71,
- },
- 'cpu-4': {
- id: 'cpu-4',
- name: 'Intel® Xeon® E-2244G',
- clockRateMhz: 3800,
- numberOfCores: 8,
- energyConsumptionW: 71,
- },
- 'cpu-5': {
- id: 'cpu-5',
- name: 'Intel® Xeon® E-2246G',
- clockRateMhz: 3600,
- numberOfCores: 12,
- energyConsumptionW: 80,
- },
-}
-
-export const GPU_UNITS = {
- 'gpu-1': {
- id: 'gpu-1',
- name: 'NVIDIA GTX 4 1080',
- clockRateMhz: 1200,
- numberOfCores: 200,
- energyConsumptionW: 250,
- },
- 'gpu-2': {
- id: 'gpu-2',
- name: 'NVIDIA Tesla V100',
- clockRateMhz: 1200,
- numberOfCores: 5120,
- energyConsumptionW: 250,
- },
-}
-
-export const MEMORY_UNITS = {
- 'memory-1': {
- id: 'memory-1',
- name: 'Samsung PC DRAM K4A4G045WD',
- speedMbPerS: 16000,
- sizeMb: 4000,
- energyConsumptionW: 10,
- },
- 'memory-2': {
- id: 'memory-2',
- name: 'Samsung PC DRAM M393A2K43BB1-CRC',
- speedMbPerS: 2400,
- sizeMb: 16000,
- energyConsumptionW: 10,
- },
- 'memory-3': {
- id: 'memory-3',
- name: 'Crucial MTA18ASF4G72PDZ-3G2E1',
- speedMbPerS: 3200,
- sizeMb: 32000,
- energyConsumptionW: 10,
- },
- 'memory-4': {
- id: 'memory-4',
- name: 'Crucial MTA9ASF2G72PZ-3G2E1',
- speedMbPerS: 3200,
- sizeMb: 16000,
- energyConsumptionW: 10,
- },
-}
-
-export const STORAGE_UNITS = {
- 'storage-1': {
- id: 'storage-1',
- name: 'Samsung EVO 2016 SATA III',
- speedMbPerS: 6000,
- sizeMb: 250000,
- energyConsumptionW: 10,
- },
- 'storage-2': {
- id: 'storage-2',
- name: 'Western Digital MTA9ASF2G72PZ-3G2E1',
- speedMbPerS: 6000,
- sizeMb: 4000000,
- energyConsumptionW: 10,
- },
-}