From 6d5a2eebb609da67239ea37d12d6b2d3bbfef76e Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 28 Oct 2020 16:41:53 +0100 Subject: ui: Do not clutter component tree with Redux connects This change refactors the frontend to use hooks for obtaining state within the Redux store as opposed to using Higher-Order Components (HOCs). This eliminates a lot of clutter in the components. --- .../app/sidebars/project/PortfolioListContainer.js | 42 ++++++------ .../sidebars/project/ProjectSidebarContainer.js | 9 +-- .../app/sidebars/project/ScenarioListContainer.js | 68 +++++++++++--------- .../app/sidebars/project/TopologyListContainer.js | 74 ++++++++++++---------- 4 files changed, 106 insertions(+), 87 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index b32c8b1d..86f465b6 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -1,28 +1,31 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { useHistory } from 'react-router-dom' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' import { deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios' import { openNewPortfolioModal } from '../../../../actions/modals/portfolios' import { getState } from '../../../../util/state-utils' import { setCurrentTopology } from '../../../../actions/topology/building' -const mapStateToProps = (state) => { - let portfolios = state.objects.project[state.currentProjectId] - ? state.objects.project[state.currentProjectId].portfolioIds.map((t) => state.objects.portfolio[t]) - : [] - if (portfolios.filter((t) => !t).length > 0) { - portfolios = [] - } +const PortfolioListContainer = (props) => { + const state = useSelector((state) => { + let portfolios = state.objects.project[state.currentProjectId] + ? state.objects.project[state.currentProjectId].portfolioIds.map((t) => state.objects.portfolio[t]) + : [] + if (portfolios.filter((t) => !t).length > 0) { + portfolios = [] + } - return { - currentProjectId: state.currentProjectId, - currentPortfolioId: state.currentPortfolioId, - portfolios, - } -} + return { + currentProjectId: state.currentProjectId, + currentPortfolioId: state.currentPortfolioId, + portfolios, + } + }) -const mapDispatchToProps = (dispatch, ownProps) => { - return { + const dispatch = useDispatch() + const history = useHistory() + const actions = { onNewPortfolio: () => { dispatch(openNewPortfolioModal()) }, @@ -34,12 +37,11 @@ const mapDispatchToProps = (dispatch, ownProps) => { const state = await getState(dispatch) dispatch(deletePortfolio(id)) dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - ownProps.history.push(`/projects/${state.currentProjectId}`) + history.push(`/projects/${state.currentProjectId}`) } }, } + return } -const PortfolioListContainer = withRouter(connect(mapStateToProps, mapDispatchToProps)(PortfolioListComponent)) - export default PortfolioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js index 49001099..35e6c52b 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js @@ -1,10 +1,11 @@ import React from 'react' -import { withRouter } from 'react-router-dom' +import { useLocation } from 'react-router-dom' import ProjectSidebarComponent from '../../../../components/app/sidebars/project/ProjectSidebarComponent' import { isCollapsible } from '../../../../util/sidebar-space' -const ProjectSidebarContainer = withRouter(({ location, ...props }) => ( - -)) +const ProjectSidebarContainer = (props) => { + const location = useLocation() + return +} export default ProjectSidebarContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 415e2792..18d0735e 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -1,41 +1,49 @@ -import { connect } from 'react-redux' +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' import { openNewScenarioModal } from '../../../../actions/modals/scenarios' import { deleteScenario, setCurrentScenario } from '../../../../actions/scenarios' import { setCurrentPortfolio } from '../../../../actions/portfolios' -const mapStateToProps = (state, ownProps) => { - let scenarios = state.objects.portfolio[ownProps.portfolioId] - ? state.objects.portfolio[ownProps.portfolioId].scenarioIds.map((t) => state.objects.scenario[t]) - : [] - if (scenarios.filter((t) => !t).length > 0) { - scenarios = [] - } +const ScenarioListContainer = ({ portfolioId, children }) => { + const currentProjectId = useSelector((state) => state.currentProjectId) + const currentScenarioId = useSelector((state) => state.currentScenarioId) + const scenarios = useSelector((state) => { + let scenarios = state.objects.portfolio[portfolioId] + ? state.objects.portfolio[portfolioId].scenarioIds.map((t) => state.objects.scenario[t]) + : [] + if (scenarios.filter((t) => !t).length > 0) { + scenarios = [] + } - return { - currentProjectId: state.currentProjectId, - currentScenarioId: state.currentScenarioId, - scenarios, - } -} + return scenarios + }) -const mapDispatchToProps = (dispatch) => { - return { - onNewScenario: (currentPortfolioId) => { - dispatch(setCurrentPortfolio(currentPortfolioId)) - dispatch(openNewScenarioModal()) - }, - onChooseScenario: (portfolioId, scenarioId) => { - dispatch(setCurrentScenario(portfolioId, scenarioId)) - }, - onDeleteScenario: (id) => { - if (id) { - dispatch(deleteScenario(id)) - } - }, + const dispatch = useDispatch() + const onNewScenario = (currentPortfolioId) => { + dispatch(setCurrentPortfolio(currentPortfolioId)) + dispatch(openNewScenarioModal()) + } + const onChooseScenario = (portfolioId, scenarioId) => { + dispatch(setCurrentScenario(portfolioId, scenarioId)) + } + const onDeleteScenario = (id) => { + if (id) { + dispatch(deleteScenario(id)) + } } -} -const ScenarioListContainer = connect(mapStateToProps, mapDispatchToProps)(ScenarioListComponent) + return ( + + ) +} export default ScenarioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index e1de18f9..954284a6 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -1,46 +1,54 @@ -import { connect } from 'react-redux' +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' import { setCurrentTopology } from '../../../../actions/topology/building' import { openNewTopologyModal } from '../../../../actions/modals/topology' -import { withRouter } from 'react-router-dom' +import { useHistory } from 'react-router-dom' import { getState } from '../../../../util/state-utils' import { deleteTopology } from '../../../../actions/topologies' -const mapStateToProps = (state) => { - let topologies = state.objects.project[state.currentProjectId] - ? state.objects.project[state.currentProjectId].topologyIds.map((t) => state.objects.topology[t]) - : [] - if (topologies.filter((t) => !t).length > 0) { - topologies = [] - } +const TopologyListContainer = () => { + const dispatch = useDispatch() + const history = useHistory() - return { - currentTopologyId: state.currentTopologyId, - topologies, - } -} + const topologies = useSelector((state) => { + let topologies = state.objects.project[state.currentProjectId] + ? state.objects.project[state.currentProjectId].topologyIds.map((t) => state.objects.topology[t]) + : [] + if (topologies.filter((t) => !t).length > 0) { + topologies = [] + } + + return topologies + }) + const currentTopologyId = useSelector((state) => state.currentTopologyId) -const mapDispatchToProps = (dispatch, ownProps) => { - return { - onChooseTopology: async (id) => { - dispatch(setCurrentTopology(id)) + const onChooseTopology = async (id) => { + dispatch(setCurrentTopology(id)) + const state = await getState(dispatch) + history.push(`/projects/${state.currentProjectId}`) + } + const onNewTopology = () => { + dispatch(openNewTopologyModal()) + } + const onDeleteTopology = async (id) => { + if (id) { const state = await getState(dispatch) - ownProps.history.push(`/projects/${state.currentProjectId}`) - }, - onNewTopology: () => { - dispatch(openNewTopologyModal()) - }, - onDeleteTopology: async (id) => { - if (id) { - const state = await getState(dispatch) - dispatch(deleteTopology(id)) - dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - ownProps.history.push(`/projects/${state.currentProjectId}`) - } - }, + dispatch(deleteTopology(id)) + dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) + history.push(`/projects/${state.currentProjectId}`) + } } -} -const TopologyListContainer = withRouter(connect(mapStateToProps, mapDispatchToProps)(TopologyListComponent)) + return ( + + ) +} export default TopologyListContainer -- cgit v1.2.3 From 4397a959e806bf476be4c81bc804616adf58b969 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 12 May 2021 22:42:12 +0200 Subject: ui: Migrate from CRA to Next.js This change updates the web frontend to use Next.js instead of Create React App (CRA). Next.js enables the possibility of rendering pages on the server side (which reduces the time to first frame) and overall provides a better development experience. Future commits will try to futher optimize the implementation for Next.js. --- .../src/containers/app/sidebars/project/PortfolioListContainer.js | 6 +++--- .../containers/app/sidebars/project/ProjectSidebarContainer.js | 6 +++--- .../src/containers/app/sidebars/project/TopologyListContainer.js | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index 86f465b6..ce295f03 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -1,6 +1,6 @@ import React from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useHistory } from 'react-router-dom' +import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' import { deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios' import { openNewPortfolioModal } from '../../../../actions/modals/portfolios' @@ -24,7 +24,7 @@ const PortfolioListContainer = (props) => { }) const dispatch = useDispatch() - const history = useHistory() + const router = useRouter() const actions = { onNewPortfolio: () => { dispatch(openNewPortfolioModal()) @@ -37,7 +37,7 @@ const PortfolioListContainer = (props) => { const state = await getState(dispatch) dispatch(deletePortfolio(id)) dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - history.push(`/projects/${state.currentProjectId}`) + router.push(`/projects/${state.currentProjectId}`) } }, } diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js index 35e6c52b..06c7f0f7 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js @@ -1,11 +1,11 @@ import React from 'react' -import { useLocation } from 'react-router-dom' +import { useRouter } from 'next/router' import ProjectSidebarComponent from '../../../../components/app/sidebars/project/ProjectSidebarComponent' import { isCollapsible } from '../../../../util/sidebar-space' const ProjectSidebarContainer = (props) => { - const location = useLocation() - return + const router = useRouter() + return } export default ProjectSidebarContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 954284a6..e9c05f17 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -3,13 +3,13 @@ import { useDispatch, useSelector } from 'react-redux' import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' import { setCurrentTopology } from '../../../../actions/topology/building' import { openNewTopologyModal } from '../../../../actions/modals/topology' -import { useHistory } from 'react-router-dom' +import { useRouter } from 'next/router' import { getState } from '../../../../util/state-utils' import { deleteTopology } from '../../../../actions/topologies' const TopologyListContainer = () => { const dispatch = useDispatch() - const history = useHistory() + const router = useRouter() const topologies = useSelector((state) => { let topologies = state.objects.project[state.currentProjectId] @@ -26,7 +26,7 @@ const TopologyListContainer = () => { const onChooseTopology = async (id) => { dispatch(setCurrentTopology(id)) const state = await getState(dispatch) - history.push(`/projects/${state.currentProjectId}`) + router.push(`/projects/${state.currentProjectId}`) } const onNewTopology = () => { dispatch(openNewTopologyModal()) @@ -36,7 +36,7 @@ const TopologyListContainer = () => { const state = await getState(dispatch) dispatch(deleteTopology(id)) dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - history.push(`/projects/${state.currentProjectId}`) + router.push(`/projects/${state.currentProjectId}`) } } -- cgit v1.2.3 From 1edbae1a0224e30bafb98638f419e1f967a9286f Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 13 May 2021 17:42:53 +0200 Subject: ui: Move modal state outside of Redux This change updates the frontend so that the modal state is not stored inside Redux but instead is stored using the useState hook. This simplifies the design of the modal components. --- .../app/sidebars/project/PortfolioListContainer.js | 56 ++++++++------- .../app/sidebars/project/ScenarioListContainer.js | 79 ++++++++++++++-------- .../app/sidebars/project/TopologyListContainer.js | 63 ++++++++++------- 3 files changed, 122 insertions(+), 76 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index ce295f03..dca7d7db 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -1,34 +1,23 @@ -import React from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useState } from 'react' +import { useDispatch } from 'react-redux' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' -import { deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios' -import { openNewPortfolioModal } from '../../../../actions/modals/portfolios' +import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios' import { getState } from '../../../../util/state-utils' import { setCurrentTopology } from '../../../../actions/topology/building' +import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' +import { useActivePortfolio, useActiveProject, usePortfolios } from '../../../../store/hooks/project' -const PortfolioListContainer = (props) => { - const state = useSelector((state) => { - let portfolios = state.objects.project[state.currentProjectId] - ? state.objects.project[state.currentProjectId].portfolioIds.map((t) => state.objects.portfolio[t]) - : [] - if (portfolios.filter((t) => !t).length > 0) { - portfolios = [] - } - - return { - currentProjectId: state.currentProjectId, - currentPortfolioId: state.currentPortfolioId, - portfolios, - } - }) +const PortfolioListContainer = () => { + const currentProjectId = useActiveProject()?._id + const currentPortfolioId = useActivePortfolio()?._id + const portfolios = usePortfolios(currentProjectId) const dispatch = useDispatch() + const [isVisible, setVisible] = useState(false) const router = useRouter() const actions = { - onNewPortfolio: () => { - dispatch(openNewPortfolioModal()) - }, + onNewPortfolio: () => setVisible(true), onChoosePortfolio: (portfolioId) => { dispatch(setCurrentPortfolio(portfolioId)) }, @@ -41,7 +30,28 @@ const PortfolioListContainer = (props) => { } }, } - return + const callback = (name, targets) => { + if (name) { + dispatch( + addPortfolio({ + name, + targets, + }) + ) + } + setVisible(false) + } + return ( + <> + + + + ) } export default PortfolioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 18d0735e..5d747820 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -1,28 +1,27 @@ -import React from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useState } from 'react' +import { useDispatch } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' -import { openNewScenarioModal } from '../../../../actions/modals/scenarios' -import { deleteScenario, setCurrentScenario } from '../../../../actions/scenarios' +import { addScenario, deleteScenario, setCurrentScenario } from '../../../../actions/scenarios' import { setCurrentPortfolio } from '../../../../actions/portfolios' +import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' +import { useProjectTopologies } from '../../../../store/hooks/topology' +import { useActiveScenario, useActiveProject, useScenarios } from '../../../../store/hooks/project' +import { useSchedulers, useTraces } from '../../../../store/hooks/experiments' -const ScenarioListContainer = ({ portfolioId, children }) => { - const currentProjectId = useSelector((state) => state.currentProjectId) - const currentScenarioId = useSelector((state) => state.currentScenarioId) - const scenarios = useSelector((state) => { - let scenarios = state.objects.portfolio[portfolioId] - ? state.objects.portfolio[portfolioId].scenarioIds.map((t) => state.objects.scenario[t]) - : [] - if (scenarios.filter((t) => !t).length > 0) { - scenarios = [] - } - - return scenarios - }) +const ScenarioListContainer = ({ portfolioId }) => { + const currentProjectId = useActiveProject()?._id + const currentScenarioId = useActiveScenario()?._id + const scenarios = useScenarios(portfolioId) + const topologies = useProjectTopologies() + const traces = useTraces() + const schedulers = useSchedulers() const dispatch = useDispatch() + const [isVisible, setVisible] = useState(false) + const onNewScenario = (currentPortfolioId) => { dispatch(setCurrentPortfolio(currentPortfolioId)) - dispatch(openNewScenarioModal()) + setVisible(true) } const onChooseScenario = (portfolioId, scenarioId) => { dispatch(setCurrentScenario(portfolioId, scenarioId)) @@ -32,17 +31,43 @@ const ScenarioListContainer = ({ portfolioId, children }) => { dispatch(deleteScenario(id)) } } + const callback = (name, portfolioId, trace, topology, operational) => { + if (name) { + dispatch( + addScenario({ + portfolioId, + name, + trace, + topology, + operational, + }) + ) + } + + setVisible(false) + } return ( - + <> + + s._id)} + traces={traces} + schedulers={schedulers} + topologies={topologies} + callback={callback} + /> + ) } diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index e9c05f17..3779705a 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -1,36 +1,25 @@ -import React from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useState } from 'react' +import { useDispatch } from 'react-redux' import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' import { setCurrentTopology } from '../../../../actions/topology/building' -import { openNewTopologyModal } from '../../../../actions/modals/topology' import { useRouter } from 'next/router' import { getState } from '../../../../util/state-utils' -import { deleteTopology } from '../../../../actions/topologies' +import { addTopology, deleteTopology } from '../../../../actions/topologies' +import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' +import { useActiveTopology, useProjectTopologies } from '../../../../store/hooks/topology' const TopologyListContainer = () => { const dispatch = useDispatch() const router = useRouter() - - const topologies = useSelector((state) => { - let topologies = state.objects.project[state.currentProjectId] - ? state.objects.project[state.currentProjectId].topologyIds.map((t) => state.objects.topology[t]) - : [] - if (topologies.filter((t) => !t).length > 0) { - topologies = [] - } - - return topologies - }) - const currentTopologyId = useSelector((state) => state.currentTopologyId) + const topologies = useProjectTopologies() + const currentTopologyId = useActiveTopology()?._id + const [isVisible, setVisible] = useState(false) const onChooseTopology = async (id) => { dispatch(setCurrentTopology(id)) const state = await getState(dispatch) router.push(`/projects/${state.currentProjectId}`) } - const onNewTopology = () => { - dispatch(openNewTopologyModal()) - } const onDeleteTopology = async (id) => { if (id) { const state = await getState(dispatch) @@ -39,15 +28,37 @@ const TopologyListContainer = () => { router.push(`/projects/${state.currentProjectId}`) } } + const onCreateTopology = (name) => { + if (name) { + dispatch(addTopology(name, undefined)) + } + setVisible(false) + } + const onDuplicateTopology = (name, id) => { + if (name) { + dispatch(addTopology(name, id)) + } + setVisible(false) + } + const onCancel = () => setVisible(false) return ( - + <> + setVisible(true)} + onDeleteTopology={onDeleteTopology} + /> + + ) } -- cgit v1.2.3 From d9e65dceb38cdb8dc4e464d388755f9456620566 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 17:07:58 +0200 Subject: ui: Restructure OpenDC frontend This change updates the structure of the OpenDC frontend in order to improve the maintainability of the frontend. --- .../containers/app/sidebars/project/PortfolioListContainer.js | 6 +++--- .../containers/app/sidebars/project/ScenarioListContainer.js | 10 +++++----- .../containers/app/sidebars/project/TopologyListContainer.js | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index dca7d7db..a36997ff 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -2,11 +2,11 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' -import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios' +import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../redux/actions/portfolios' import { getState } from '../../../../util/state-utils' -import { setCurrentTopology } from '../../../../actions/topology/building' +import { setCurrentTopology } from '../../../../redux/actions/topology/building' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { useActivePortfolio, useActiveProject, usePortfolios } from '../../../../store/hooks/project' +import { useActivePortfolio, useActiveProject, usePortfolios } from '../../../../data/project' const PortfolioListContainer = () => { const currentProjectId = useActiveProject()?._id diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 5d747820..7aaa1886 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -1,12 +1,12 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' -import { addScenario, deleteScenario, setCurrentScenario } from '../../../../actions/scenarios' -import { setCurrentPortfolio } from '../../../../actions/portfolios' +import { addScenario, deleteScenario, setCurrentScenario } from '../../../../redux/actions/scenarios' +import { setCurrentPortfolio } from '../../../../redux/actions/portfolios' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' -import { useProjectTopologies } from '../../../../store/hooks/topology' -import { useActiveScenario, useActiveProject, useScenarios } from '../../../../store/hooks/project' -import { useSchedulers, useTraces } from '../../../../store/hooks/experiments' +import { useProjectTopologies } from '../../../../data/topology' +import { useActiveScenario, useActiveProject, useScenarios } from '../../../../data/project' +import { useSchedulers, useTraces } from '../../../../data/experiments' const ScenarioListContainer = ({ portfolioId }) => { const currentProjectId = useActiveProject()?._id diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 3779705a..266ca495 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -1,12 +1,12 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' -import { setCurrentTopology } from '../../../../actions/topology/building' +import { setCurrentTopology } from '../../../../redux/actions/topology/building' import { useRouter } from 'next/router' import { getState } from '../../../../util/state-utils' -import { addTopology, deleteTopology } from '../../../../actions/topologies' +import { addTopology, deleteTopology } from '../../../../redux/actions/topologies' import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' -import { useActiveTopology, useProjectTopologies } from '../../../../store/hooks/topology' +import { useActiveTopology, useProjectTopologies } from '../../../../data/topology' const TopologyListContainer = () => { const dispatch = useDispatch() -- cgit v1.2.3 From a6865b86cc8d710374fc0b6cfcbd2b863f1942a9 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 23:18:02 +0200 Subject: ui: Migrate to Auth0 as Identity Provider This change updates the frontend codebase to move away from the Google login and instead use Auth0 as generic Identity Provider. This allows users to login with other accounts as well. Since Auth0 has a free tier, users can experiment themselves with OpenDC locally without having to pay for the login functionality. The code has been written so that we should be able to migrate away from Auth0 once it is not a suitable Identity Provider for OpenDC anymore. --- .../src/containers/app/sidebars/project/ScenarioListContainer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 7aaa1886..e1be51dc 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -60,7 +60,7 @@ const ScenarioListContainer = ({ portfolioId }) => { /> s._id)} traces={traces} schedulers={schedulers} -- cgit v1.2.3 From 1ce8bf170cda2afab334cd330325cd4fbb97dab4 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 11:46:57 +0200 Subject: ui: Split App container into separate components This change splits the App container into separate pages, as a starting point for removing much of the unnecessary state from Redux. --- .../containers/app/sidebars/project/PortfolioListContainer.js | 7 +++---- .../containers/app/sidebars/project/ScenarioListContainer.js | 11 +++++++++-- .../containers/app/sidebars/project/TopologyListContainer.js | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index a36997ff..28d7f0d1 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -6,16 +6,15 @@ import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../ import { getState } from '../../../../util/state-utils' import { setCurrentTopology } from '../../../../redux/actions/topology/building' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { useActivePortfolio, useActiveProject, usePortfolios } from '../../../../data/project' +import { usePortfolios } from '../../../../data/project' const PortfolioListContainer = () => { - const currentProjectId = useActiveProject()?._id - const currentPortfolioId = useActivePortfolio()?._id + const router = useRouter() + const { project: currentProjectId, portfolio: currentPortfolioId } = router.query const portfolios = usePortfolios(currentProjectId) const dispatch = useDispatch() const [isVisible, setVisible] = useState(false) - const router = useRouter() const actions = { onNewPortfolio: () => setVisible(true), onChoosePortfolio: (portfolioId) => { diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index e1be51dc..10743401 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types' import React, { useState } from 'react' import { useDispatch } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' @@ -5,11 +6,13 @@ import { addScenario, deleteScenario, setCurrentScenario } from '../../../../red import { setCurrentPortfolio } from '../../../../redux/actions/portfolios' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' import { useProjectTopologies } from '../../../../data/topology' -import { useActiveScenario, useActiveProject, useScenarios } from '../../../../data/project' +import { useActiveScenario, useScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' +import { useRouter } from 'next/router' const ScenarioListContainer = ({ portfolioId }) => { - const currentProjectId = useActiveProject()?._id + const router = useRouter() + const { project: currentProjectId } = router.query const currentScenarioId = useActiveScenario()?._id const scenarios = useScenarios(portfolioId) const topologies = useProjectTopologies() @@ -71,4 +74,8 @@ const ScenarioListContainer = ({ portfolioId }) => { ) } +ScenarioListContainer.propTypes = { + portfolioId: PropTypes.string.isRequired, +} + export default ScenarioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 266ca495..648c4500 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -18,14 +18,14 @@ const TopologyListContainer = () => { const onChooseTopology = async (id) => { dispatch(setCurrentTopology(id)) const state = await getState(dispatch) - router.push(`/projects/${state.currentProjectId}`) + await router.push(`/projects/${state.currentProjectId}/topologies/${id}`) } const onDeleteTopology = async (id) => { if (id) { const state = await getState(dispatch) dispatch(deleteTopology(id)) dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - router.push(`/projects/${state.currentProjectId}`) + await router.push(`/projects/${state.currentProjectId}`) } } const onCreateTopology = (name) => { -- cgit v1.2.3 From aa788a3ad18badfac8beaabdaffc88b9e52f9306 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 15:07:11 +0200 Subject: ui: Remove current ids state from Redux This change removes the current active identifiers from the Redux state. Instead, we use the router query to track the active project, portfolio and topology. --- .../app/sidebars/project/PortfolioListContainer.js | 12 ++++++------ .../app/sidebars/project/ScenarioListContainer.js | 14 +++----------- .../app/sidebars/project/TopologyListContainer.js | 14 ++++++-------- 3 files changed, 15 insertions(+), 25 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index 28d7f0d1..b5bade98 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -2,7 +2,7 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' -import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../redux/actions/portfolios' +import { addPortfolio, deletePortfolio } from '../../../../redux/actions/portfolios' import { getState } from '../../../../util/state-utils' import { setCurrentTopology } from '../../../../redux/actions/topology/building' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' @@ -17,22 +17,22 @@ const PortfolioListContainer = () => { const [isVisible, setVisible] = useState(false) const actions = { onNewPortfolio: () => setVisible(true), - onChoosePortfolio: (portfolioId) => { - dispatch(setCurrentPortfolio(portfolioId)) + onChoosePortfolio: async (portfolioId) => { + await router.push(`/projects/${currentProjectId}/portfolios/${portfolioId}`) }, onDeletePortfolio: async (id) => { if (id) { const state = await getState(dispatch) dispatch(deletePortfolio(id)) - dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - router.push(`/projects/${state.currentProjectId}`) + dispatch(setCurrentTopology(state.objects.project[currentProjectId].topologyIds[0])) + await router.push(`/projects/${currentProjectId}`) } }, } const callback = (name, targets) => { if (name) { dispatch( - addPortfolio({ + addPortfolio(currentProjectId, { name, targets, }) diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 10743401..0eb61026 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -2,18 +2,16 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' import { useDispatch } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' -import { addScenario, deleteScenario, setCurrentScenario } from '../../../../redux/actions/scenarios' -import { setCurrentPortfolio } from '../../../../redux/actions/portfolios' +import { addScenario, deleteScenario } from '../../../../redux/actions/scenarios' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' import { useProjectTopologies } from '../../../../data/topology' -import { useActiveScenario, useScenarios } from '../../../../data/project' +import { useScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' import { useRouter } from 'next/router' const ScenarioListContainer = ({ portfolioId }) => { const router = useRouter() const { project: currentProjectId } = router.query - const currentScenarioId = useActiveScenario()?._id const scenarios = useScenarios(portfolioId) const topologies = useProjectTopologies() const traces = useTraces() @@ -23,12 +21,9 @@ const ScenarioListContainer = ({ portfolioId }) => { const [isVisible, setVisible] = useState(false) const onNewScenario = (currentPortfolioId) => { - dispatch(setCurrentPortfolio(currentPortfolioId)) setVisible(true) } - const onChooseScenario = (portfolioId, scenarioId) => { - dispatch(setCurrentScenario(portfolioId, scenarioId)) - } + const onChooseScenario = (portfolioId, scenarioId) => {} const onDeleteScenario = (id) => { if (id) { dispatch(deleteScenario(id)) @@ -54,11 +49,8 @@ const ScenarioListContainer = ({ portfolioId }) => { <> { const dispatch = useDispatch() const router = useRouter() + const { project: currentProjectId } = router.query const topologies = useProjectTopologies() const currentTopologyId = useActiveTopology()?._id const [isVisible, setVisible] = useState(false) const onChooseTopology = async (id) => { dispatch(setCurrentTopology(id)) - const state = await getState(dispatch) - await router.push(`/projects/${state.currentProjectId}/topologies/${id}`) + await router.push(`/projects/${currentProjectId}/topologies/${id}`) } const onDeleteTopology = async (id) => { if (id) { - const state = await getState(dispatch) dispatch(deleteTopology(id)) - dispatch(setCurrentTopology(state.objects.project[state.currentProjectId].topologyIds[0])) - await router.push(`/projects/${state.currentProjectId}`) + dispatch(setCurrentTopology(state.objects.project[currentProjectId].topologyIds[0])) + await router.push(`/projects/${currentProjectId}`) } } const onCreateTopology = (name) => { if (name) { - dispatch(addTopology(name, undefined)) + dispatch(addTopology(currentProjectId, name, undefined)) } setVisible(false) } const onDuplicateTopology = (name, id) => { if (name) { - dispatch(addTopology(name, id)) + dispatch(addTopology(currentProjectId, name, id)) } setVisible(false) } -- cgit v1.2.3 From e5e5d2c65e583493870bc0b62fb185c5e757c13f Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 16:27:49 +0200 Subject: ui: Migrate project APIs to React Query This change updates the OpenDC frontend to use React Query for fetching and mutating project data. Previously, this state was tracked and synchronized via Redux. Migrating to React Query greatly simplifies the state synchronization logic necessary in the frontend. --- .../src/containers/app/sidebars/project/PortfolioListContainer.js | 5 +++-- .../src/containers/app/sidebars/project/ScenarioListContainer.js | 6 +----- .../src/containers/app/sidebars/project/TopologyListContainer.js | 4 +++- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index b5bade98..1b539b8f 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -6,11 +6,12 @@ import { addPortfolio, deletePortfolio } from '../../../../redux/actions/portfol import { getState } from '../../../../util/state-utils' import { setCurrentTopology } from '../../../../redux/actions/topology/building' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { usePortfolios } from '../../../../data/project' +import { useActivePortfolioId, useActiveProjectId, usePortfolios, useProject } from '../../../../data/project' const PortfolioListContainer = () => { const router = useRouter() const { project: currentProjectId, portfolio: currentPortfolioId } = router.query + const { data: currentProject } = useProject(currentProjectId) const portfolios = usePortfolios(currentProjectId) const dispatch = useDispatch() @@ -24,7 +25,7 @@ const PortfolioListContainer = () => { if (id) { const state = await getState(dispatch) dispatch(deletePortfolio(id)) - dispatch(setCurrentTopology(state.objects.project[currentProjectId].topologyIds[0])) + dispatch(setCurrentTopology(currentProject.topologyIds[0])) await router.push(`/projects/${currentProjectId}`) } }, diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 0eb61026..c474c56e 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -7,11 +7,8 @@ import NewScenarioModalComponent from '../../../../components/modals/custom-comp import { useProjectTopologies } from '../../../../data/topology' import { useScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' -import { useRouter } from 'next/router' const ScenarioListContainer = ({ portfolioId }) => { - const router = useRouter() - const { project: currentProjectId } = router.query const scenarios = useScenarios(portfolioId) const topologies = useProjectTopologies() const traces = useTraces() @@ -23,7 +20,6 @@ const ScenarioListContainer = ({ portfolioId }) => { const onNewScenario = (currentPortfolioId) => { setVisible(true) } - const onChooseScenario = (portfolioId, scenarioId) => {} const onDeleteScenario = (id) => { if (id) { dispatch(deleteScenario(id)) @@ -67,7 +63,7 @@ const ScenarioListContainer = ({ portfolioId }) => { } ScenarioListContainer.propTypes = { - portfolioId: PropTypes.string.isRequired, + portfolioId: PropTypes.string, } export default ScenarioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 69367b5f..55f8bd00 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -6,11 +6,13 @@ import { useRouter } from 'next/router' import { addTopology, deleteTopology } from '../../../../redux/actions/topologies' import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' import { useActiveTopology, useProjectTopologies } from '../../../../data/topology' +import { useProject } from '../../../../data/project' const TopologyListContainer = () => { const dispatch = useDispatch() const router = useRouter() const { project: currentProjectId } = router.query + const { data: currentProject } = useProject(currentProjectId) const topologies = useProjectTopologies() const currentTopologyId = useActiveTopology()?._id const [isVisible, setVisible] = useState(false) @@ -22,7 +24,7 @@ const TopologyListContainer = () => { const onDeleteTopology = async (id) => { if (id) { dispatch(deleteTopology(id)) - dispatch(setCurrentTopology(state.objects.project[currentProjectId].topologyIds[0])) + dispatch(setCurrentTopology(currentProject.topologyIds[0])) await router.push(`/projects/${currentProjectId}`) } } -- cgit v1.2.3 From d28a2f194a75eb86095485ae4f88be349bcc18b6 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 16:36:54 +0200 Subject: ui: Fetch schedulers and traces using React Query This change updates the OpenDC frontend to fetch schedulers and traces using React Query, removing its dependency on Redux. --- .../src/containers/app/sidebars/project/ScenarioListContainer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index c474c56e..7acc13ee 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -11,8 +11,8 @@ import { useSchedulers, useTraces } from '../../../../data/experiments' const ScenarioListContainer = ({ portfolioId }) => { const scenarios = useScenarios(portfolioId) const topologies = useProjectTopologies() - const traces = useTraces() - const schedulers = useSchedulers() + const traces = useTraces().data ?? [] + const schedulers = useSchedulers().data ?? [] const dispatch = useDispatch() const [isVisible, setVisible] = useState(false) -- cgit v1.2.3 From 9c8a987556d0fb0cdf0eb67e0c191a8dcc5593b9 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 17:30:15 +0200 Subject: ui: Fetch scenarios and portfolios using React Query --- .../app/sidebars/project/PortfolioListContainer.js | 40 +++++++++++------- .../app/sidebars/project/ScenarioListContainer.js | 48 +++++++++++++++------- 2 files changed, 59 insertions(+), 29 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index 1b539b8f..01183724 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -2,17 +2,36 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' -import { addPortfolio, deletePortfolio } from '../../../../redux/actions/portfolios' -import { getState } from '../../../../util/state-utils' -import { setCurrentTopology } from '../../../../redux/actions/topology/building' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { useActivePortfolioId, useActiveProjectId, usePortfolios, useProject } from '../../../../data/project' +import { usePortfolios, useProject } from '../../../../data/project' +import { useMutation, useQueryClient } from 'react-query' +import { addPortfolio, deletePortfolio } from '../../../../api/portfolios' +import { useAuth } from '../../../../auth' const PortfolioListContainer = () => { const router = useRouter() const { project: currentProjectId, portfolio: currentPortfolioId } = router.query const { data: currentProject } = useProject(currentProjectId) - const portfolios = usePortfolios(currentProjectId) + const portfolios = usePortfolios(currentProject?.portfolioIds ?? []) + .filter((res) => res.data) + .map((res) => res.data) + + const auth = useAuth() + const queryClient = useQueryClient() + const addMutation = useMutation((data) => addPortfolio(auth, data), { + onSuccess: async (result) => { + await queryClient.invalidateQueries(['projects', currentProjectId]) + }, + }) + const deleteMutation = useMutation((id) => deletePortfolio(auth, id), { + onSuccess: async (result) => { + queryClient.setQueryData(['projects', currentProjectId], (old) => ({ + ...old, + portfolioIds: old.portfolioIds.filter((id) => id !== result._id), + })) + queryClient.removeQueries(['portfolios', result._id]) + }, + }) const dispatch = useDispatch() const [isVisible, setVisible] = useState(false) @@ -23,21 +42,14 @@ const PortfolioListContainer = () => { }, onDeletePortfolio: async (id) => { if (id) { - const state = await getState(dispatch) - dispatch(deletePortfolio(id)) - dispatch(setCurrentTopology(currentProject.topologyIds[0])) + await deleteMutation.mutateAsync(id) await router.push(`/projects/${currentProjectId}`) } }, } const callback = (name, targets) => { if (name) { - dispatch( - addPortfolio(currentProjectId, { - name, - targets, - }) - ) + addMutation.mutate({ projectId: currentProjectId, name, targets }) } setVisible(false) } diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 7acc13ee..6bfc8599 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -1,20 +1,40 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' -import { useDispatch } from 'react-redux' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' -import { addScenario, deleteScenario } from '../../../../redux/actions/scenarios' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' import { useProjectTopologies } from '../../../../data/topology' -import { useScenarios } from '../../../../data/project' +import { usePortfolio, useScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' +import { useAuth } from '../../../../auth' +import { useMutation, useQueryClient } from 'react-query' +import { addScenario, deleteScenario } from '../../../../api/scenarios' const ScenarioListContainer = ({ portfolioId }) => { - const scenarios = useScenarios(portfolioId) + const { data: portfolio } = usePortfolio(portfolioId) + const scenarios = useScenarios(portfolio?.scenarioIds ?? []) + .filter((res) => res.data) + .map((res) => res.data) const topologies = useProjectTopologies() const traces = useTraces().data ?? [] const schedulers = useSchedulers().data ?? [] - const dispatch = useDispatch() + const auth = useAuth() + const queryClient = useQueryClient() + const addMutation = useMutation((data) => addScenario(auth, data), { + onSuccess: async (result) => { + await queryClient.invalidateQueries(['portfolios', portfolioId]) + }, + }) + const deleteMutation = useMutation((id) => deleteScenario(auth, id), { + onSuccess: async (result) => { + queryClient.setQueryData(['portfolios', portfolioId], (old) => ({ + ...old, + scenarioIds: old.scenarioIds.filter((id) => id !== result._id), + })) + queryClient.removeQueries(['scenarios', result._id]) + }, + }) + const [isVisible, setVisible] = useState(false) const onNewScenario = (currentPortfolioId) => { @@ -22,20 +42,18 @@ const ScenarioListContainer = ({ portfolioId }) => { } const onDeleteScenario = (id) => { if (id) { - dispatch(deleteScenario(id)) + deleteMutation.mutate(id) } } const callback = (name, portfolioId, trace, topology, operational) => { if (name) { - dispatch( - addScenario({ - portfolioId, - name, - trace, - topology, - operational, - }) - ) + addMutation.mutate({ + portfolioId, + name, + trace, + topology, + operational, + }) } setVisible(false) -- cgit v1.2.3 From 02a2f0f89cb1f39a5f8856bca1971a4e1b12374f Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 7 Jul 2021 20:13:30 +0200 Subject: ui: Use React Query defaults to reduce duplication --- .../app/sidebars/project/PortfolioListContainer.js | 28 +++----------- .../app/sidebars/project/ScenarioListContainer.js | 43 ++++++---------------- .../app/sidebars/project/TopologyListContainer.js | 14 ++++--- 3 files changed, 26 insertions(+), 59 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index 01183724..1fb88253 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -1,12 +1,9 @@ import React, { useState } from 'react' -import { useDispatch } from 'react-redux' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' import { usePortfolios, useProject } from '../../../../data/project' -import { useMutation, useQueryClient } from 'react-query' -import { addPortfolio, deletePortfolio } from '../../../../api/portfolios' -import { useAuth } from '../../../../auth' +import { useMutation } from 'react-query' const PortfolioListContainer = () => { const router = useRouter() @@ -16,24 +13,9 @@ const PortfolioListContainer = () => { .filter((res) => res.data) .map((res) => res.data) - const auth = useAuth() - const queryClient = useQueryClient() - const addMutation = useMutation((data) => addPortfolio(auth, data), { - onSuccess: async (result) => { - await queryClient.invalidateQueries(['projects', currentProjectId]) - }, - }) - const deleteMutation = useMutation((id) => deletePortfolio(auth, id), { - onSuccess: async (result) => { - queryClient.setQueryData(['projects', currentProjectId], (old) => ({ - ...old, - portfolioIds: old.portfolioIds.filter((id) => id !== result._id), - })) - queryClient.removeQueries(['portfolios', result._id]) - }, - }) + const { mutate: addPortfolio } = useMutation('addPortfolio') + const { mutateAsync: deletePortfolio } = useMutation('deletePortfolio') - const dispatch = useDispatch() const [isVisible, setVisible] = useState(false) const actions = { onNewPortfolio: () => setVisible(true), @@ -42,14 +24,14 @@ const PortfolioListContainer = () => { }, onDeletePortfolio: async (id) => { if (id) { - await deleteMutation.mutateAsync(id) + await deletePortfolio(id) await router.push(`/projects/${currentProjectId}`) } }, } const callback = (name, targets) => { if (name) { - addMutation.mutate({ projectId: currentProjectId, name, targets }) + addPortfolio({ projectId: currentProjectId, name, targets }) } setVisible(false) } diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 6bfc8599..62761583 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -2,52 +2,33 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' -import { useProjectTopologies } from '../../../../data/topology' -import { usePortfolio, useScenarios } from '../../../../data/project' +import { useTopologies } from '../../../../data/topology' +import { usePortfolio, useProject, useScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' -import { useAuth } from '../../../../auth' -import { useMutation, useQueryClient } from 'react-query' -import { addScenario, deleteScenario } from '../../../../api/scenarios' +import { useMutation } from 'react-query' const ScenarioListContainer = ({ portfolioId }) => { const { data: portfolio } = usePortfolio(portfolioId) + const { data: project } = useProject(portfolio?.projectId) const scenarios = useScenarios(portfolio?.scenarioIds ?? []) .filter((res) => res.data) .map((res) => res.data) - const topologies = useProjectTopologies() + const topologies = useTopologies(project?.topologyIds ?? []) + .filter((res) => res.data) + .map((res) => res.data) const traces = useTraces().data ?? [] const schedulers = useSchedulers().data ?? [] - const auth = useAuth() - const queryClient = useQueryClient() - const addMutation = useMutation((data) => addScenario(auth, data), { - onSuccess: async (result) => { - await queryClient.invalidateQueries(['portfolios', portfolioId]) - }, - }) - const deleteMutation = useMutation((id) => deleteScenario(auth, id), { - onSuccess: async (result) => { - queryClient.setQueryData(['portfolios', portfolioId], (old) => ({ - ...old, - scenarioIds: old.scenarioIds.filter((id) => id !== result._id), - })) - queryClient.removeQueries(['scenarios', result._id]) - }, - }) + const { mutate: addScenario } = useMutation('addScenario') + const { mutate: deleteScenario } = useMutation('deleteScenario') const [isVisible, setVisible] = useState(false) - const onNewScenario = (currentPortfolioId) => { - setVisible(true) - } - const onDeleteScenario = (id) => { - if (id) { - deleteMutation.mutate(id) - } - } + const onNewScenario = () => setVisible(true) + const onDeleteScenario = (id) => id && deleteScenario(id) const callback = (name, portfolioId, trace, topology, operational) => { if (name) { - addMutation.mutate({ + addScenario({ portfolioId, name, trace, diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 55f8bd00..78db166c 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -3,28 +3,32 @@ import { useDispatch } from 'react-redux' import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' import { setCurrentTopology } from '../../../../redux/actions/topology/building' import { useRouter } from 'next/router' -import { addTopology, deleteTopology } from '../../../../redux/actions/topologies' +import { addTopology } from '../../../../redux/actions/topologies' import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' -import { useActiveTopology, useProjectTopologies } from '../../../../data/topology' +import { useActiveTopology, useTopologies } from '../../../../data/topology' import { useProject } from '../../../../data/project' +import { useMutation } from 'react-query' const TopologyListContainer = () => { const dispatch = useDispatch() const router = useRouter() const { project: currentProjectId } = router.query const { data: currentProject } = useProject(currentProjectId) - const topologies = useProjectTopologies() + const topologies = useTopologies(currentProject?.topologyIds ?? []) + .filter((res) => res.data) + .map((res) => res.data) const currentTopologyId = useActiveTopology()?._id const [isVisible, setVisible] = useState(false) + const { mutate: deleteTopology } = useMutation('deleteTopology') + const onChooseTopology = async (id) => { dispatch(setCurrentTopology(id)) await router.push(`/projects/${currentProjectId}/topologies/${id}`) } const onDeleteTopology = async (id) => { if (id) { - dispatch(deleteTopology(id)) - dispatch(setCurrentTopology(currentProject.topologyIds[0])) + deleteTopology(id) await router.push(`/projects/${currentProjectId}`) } } -- cgit v1.2.3 From 29196842447d841d2e21462adcfc8c2ed1d851ad Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 8 Jul 2021 13:15:28 +0200 Subject: ui: Simplify normalization of topology This change updates the OpenDC frontend to use the normalizr library for normalizing the user topology. --- .../src/containers/app/sidebars/project/ScenarioListContainer.js | 2 +- .../src/containers/app/sidebars/project/TopologyListContainer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index 62761583..fd55582f 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -15,7 +15,7 @@ const ScenarioListContainer = ({ portfolioId }) => { .map((res) => res.data) const topologies = useTopologies(project?.topologyIds ?? []) .filter((res) => res.data) - .map((res) => res.data) + .map((res) => ({ _id: res.data._id, name: res.data.name })) const traces = useTraces().data ?? [] const schedulers = useSchedulers().data ?? [] diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 78db166c..55eab23a 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -16,7 +16,7 @@ const TopologyListContainer = () => { const { data: currentProject } = useProject(currentProjectId) const topologies = useTopologies(currentProject?.topologyIds ?? []) .filter((res) => res.data) - .map((res) => res.data) + .map((res) => ({ _id: res.data._id, name: res.data.name })) const currentTopologyId = useActiveTopology()?._id const [isVisible, setVisible] = useState(false) -- cgit v1.2.3 From 2c8d675c2cf140eac05988065a9d20fd2773399a Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 8 Jul 2021 13:36:39 +0200 Subject: ui: Combine fetching of project relations This change updates the OpenDC frontend to combine the fetching of project relations. This means that for a single project, we make only one additional request to retrieve all its topologies. --- .../app/sidebars/project/PortfolioListContainer.js | 7 ++----- .../app/sidebars/project/ScenarioListContainer.js | 17 ++++++++--------- .../app/sidebars/project/TopologyListContainer.js | 10 ++++------ 3 files changed, 14 insertions(+), 20 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js index 1fb88253..60ac666c 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js @@ -2,16 +2,13 @@ import React, { useState } from 'react' import { useRouter } from 'next/router' import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { usePortfolios, useProject } from '../../../../data/project' +import { useProjectPortfolios } from '../../../../data/project' import { useMutation } from 'react-query' const PortfolioListContainer = () => { const router = useRouter() const { project: currentProjectId, portfolio: currentPortfolioId } = router.query - const { data: currentProject } = useProject(currentProjectId) - const portfolios = usePortfolios(currentProject?.portfolioIds ?? []) - .filter((res) => res.data) - .map((res) => res.data) + const portfolios = useProjectPortfolios(currentProjectId).data ?? [] const { mutate: addPortfolio } = useMutation('addPortfolio') const { mutateAsync: deletePortfolio } = useMutation('deletePortfolio') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js index fd55582f..3b68df38 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js @@ -2,20 +2,19 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' -import { useTopologies } from '../../../../data/topology' -import { usePortfolio, useProject, useScenarios } from '../../../../data/project' +import { useProjectTopologies } from '../../../../data/topology' +import { usePortfolio, usePortfolioScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' import { useMutation } from 'react-query' const ScenarioListContainer = ({ portfolioId }) => { const { data: portfolio } = usePortfolio(portfolioId) - const { data: project } = useProject(portfolio?.projectId) - const scenarios = useScenarios(portfolio?.scenarioIds ?? []) - .filter((res) => res.data) - .map((res) => res.data) - const topologies = useTopologies(project?.topologyIds ?? []) - .filter((res) => res.data) - .map((res) => ({ _id: res.data._id, name: res.data.name })) + const scenarios = usePortfolioScenarios(portfolioId).data ?? [] + const topologies = + useProjectTopologies(portfolio?.projectId).data?.map((topology) => ({ + _id: topology._id, + name: topology.name, + })) ?? [] const traces = useTraces().data ?? [] const schedulers = useSchedulers().data ?? [] diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js index 55eab23a..a2244a30 100644 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js @@ -5,18 +5,16 @@ import { setCurrentTopology } from '../../../../redux/actions/topology/building' import { useRouter } from 'next/router' import { addTopology } from '../../../../redux/actions/topologies' import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' -import { useActiveTopology, useTopologies } from '../../../../data/topology' -import { useProject } from '../../../../data/project' +import { useActiveTopology, useProjectTopologies } from '../../../../data/topology' import { useMutation } from 'react-query' const TopologyListContainer = () => { const dispatch = useDispatch() const router = useRouter() const { project: currentProjectId } = router.query - const { data: currentProject } = useProject(currentProjectId) - const topologies = useTopologies(currentProject?.topologyIds ?? []) - .filter((res) => res.data) - .map((res) => ({ _id: res.data._id, name: res.data.name })) + const topologies = + useProjectTopologies(currentProjectId).data?.map((topology) => ({ _id: topology._id, name: topology.name })) ?? + [] const currentTopologyId = useActiveTopology()?._id const [isVisible, setVisible] = useState(false) -- cgit v1.2.3 From 803e13b32cf0ff8b496649fb0a4d6e32400e98a4 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 14 Jul 2021 22:23:40 +0200 Subject: feat(ui): Migrate to PatternFly 4 design framework This change is a rewrite of the existing OpenDC frontend in order to migrate to the PatternFly 4 design framework. PatternFly is used by Red Hat for various computing related services such as OpenShift, Red Hat Virtualization and Cockpit. Since their design requirements are very similar to those of OpenDC (modeling computing services), migrating to PatternFly 4 allows us to re-use design choices from these services. See https://www.patternfly.org/v4/ for more information about PatternFly. --- .../app/sidebars/project/PortfolioListContainer.js | 48 ---------------- .../sidebars/project/ProjectSidebarContainer.js | 11 ---- .../app/sidebars/project/ScenarioListContainer.js | 67 ---------------------- .../app/sidebars/project/TopologyListContainer.js | 67 ---------------------- 4 files changed, 193 deletions(-) delete mode 100644 opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js delete mode 100644 opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js delete mode 100644 opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js delete mode 100644 opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project') diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js deleted file mode 100644 index 60ac666c..00000000 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js +++ /dev/null @@ -1,48 +0,0 @@ -import React, { useState } from 'react' -import { useRouter } from 'next/router' -import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent' -import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent' -import { useProjectPortfolios } from '../../../../data/project' -import { useMutation } from 'react-query' - -const PortfolioListContainer = () => { - const router = useRouter() - const { project: currentProjectId, portfolio: currentPortfolioId } = router.query - const portfolios = useProjectPortfolios(currentProjectId).data ?? [] - - const { mutate: addPortfolio } = useMutation('addPortfolio') - const { mutateAsync: deletePortfolio } = useMutation('deletePortfolio') - - const [isVisible, setVisible] = useState(false) - const actions = { - onNewPortfolio: () => setVisible(true), - onChoosePortfolio: async (portfolioId) => { - await router.push(`/projects/${currentProjectId}/portfolios/${portfolioId}`) - }, - onDeletePortfolio: async (id) => { - if (id) { - await deletePortfolio(id) - await router.push(`/projects/${currentProjectId}`) - } - }, - } - const callback = (name, targets) => { - if (name) { - addPortfolio({ projectId: currentProjectId, name, targets }) - } - setVisible(false) - } - return ( - <> - - - - ) -} - -export default PortfolioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js deleted file mode 100644 index 06c7f0f7..00000000 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ProjectSidebarContainer.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' -import { useRouter } from 'next/router' -import ProjectSidebarComponent from '../../../../components/app/sidebars/project/ProjectSidebarComponent' -import { isCollapsible } from '../../../../util/sidebar-space' - -const ProjectSidebarContainer = (props) => { - const router = useRouter() - return -} - -export default ProjectSidebarContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js deleted file mode 100644 index 3b68df38..00000000 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js +++ /dev/null @@ -1,67 +0,0 @@ -import PropTypes from 'prop-types' -import React, { useState } from 'react' -import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent' -import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' -import { useProjectTopologies } from '../../../../data/topology' -import { usePortfolio, usePortfolioScenarios } from '../../../../data/project' -import { useSchedulers, useTraces } from '../../../../data/experiments' -import { useMutation } from 'react-query' - -const ScenarioListContainer = ({ portfolioId }) => { - const { data: portfolio } = usePortfolio(portfolioId) - const scenarios = usePortfolioScenarios(portfolioId).data ?? [] - const topologies = - useProjectTopologies(portfolio?.projectId).data?.map((topology) => ({ - _id: topology._id, - name: topology.name, - })) ?? [] - const traces = useTraces().data ?? [] - const schedulers = useSchedulers().data ?? [] - - const { mutate: addScenario } = useMutation('addScenario') - const { mutate: deleteScenario } = useMutation('deleteScenario') - - const [isVisible, setVisible] = useState(false) - - const onNewScenario = () => setVisible(true) - const onDeleteScenario = (id) => id && deleteScenario(id) - const callback = (name, portfolioId, trace, topology, operational) => { - if (name) { - addScenario({ - portfolioId, - name, - trace, - topology, - operational, - }) - } - - setVisible(false) - } - - return ( - <> - - s._id)} - traces={traces} - schedulers={schedulers} - topologies={topologies} - callback={callback} - /> - - ) -} - -ScenarioListContainer.propTypes = { - portfolioId: PropTypes.string, -} - -export default ScenarioListContainer diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js deleted file mode 100644 index a2244a30..00000000 --- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js +++ /dev/null @@ -1,67 +0,0 @@ -import React, { useState } from 'react' -import { useDispatch } from 'react-redux' -import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent' -import { setCurrentTopology } from '../../../../redux/actions/topology/building' -import { useRouter } from 'next/router' -import { addTopology } from '../../../../redux/actions/topologies' -import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent' -import { useActiveTopology, useProjectTopologies } from '../../../../data/topology' -import { useMutation } from 'react-query' - -const TopologyListContainer = () => { - const dispatch = useDispatch() - const router = useRouter() - const { project: currentProjectId } = router.query - const topologies = - useProjectTopologies(currentProjectId).data?.map((topology) => ({ _id: topology._id, name: topology.name })) ?? - [] - const currentTopologyId = useActiveTopology()?._id - const [isVisible, setVisible] = useState(false) - - const { mutate: deleteTopology } = useMutation('deleteTopology') - - const onChooseTopology = async (id) => { - dispatch(setCurrentTopology(id)) - await router.push(`/projects/${currentProjectId}/topologies/${id}`) - } - const onDeleteTopology = async (id) => { - if (id) { - deleteTopology(id) - await router.push(`/projects/${currentProjectId}`) - } - } - const onCreateTopology = (name) => { - if (name) { - dispatch(addTopology(currentProjectId, name, undefined)) - } - setVisible(false) - } - const onDuplicateTopology = (name, id) => { - if (name) { - dispatch(addTopology(currentProjectId, name, id)) - } - setVisible(false) - } - const onCancel = () => setVisible(false) - - return ( - <> - setVisible(true)} - onDeleteTopology={onDeleteTopology} - /> - - - ) -} - -export default TopologyListContainer -- cgit v1.2.3