diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-07-08 16:08:02 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-08 16:08:02 +0200 |
| commit | 1a2416043f0b877f570e89da74e0d0a4aff1d8ae (patch) | |
| tree | 1bed18bb62d223be954faca87b0736d2a571b443 /opendc-web/opendc-web-ui/src/containers/app/sidebars/project | |
| parent | dfd2ded56780995cec6d91af37443b710d4ddb3b (diff) | |
| parent | 2c8d675c2cf140eac05988065a9d20fd2773399a (diff) | |
ui: Simplify data fetching in frontend
This pull request aims to simplify the data fetching logic in the OpenDC frontend.
Previously, the frontend used Redux extensively to sync the server state with the
client state, which introduced a lot of unnecessary complexity.
With this pull request, we move most of the data fetching logic out of Redux and
instead use React Query to perform the logic for fetching and caching API requests.
* Move all server data except topologies outside Redux
* Use React Query for fetching server data
* (De)normalize topology using Normalizr
* Remove current ids state from Redux
* Combine fetching of project relations
Diffstat (limited to 'opendc-web/opendc-web-ui/src/containers/app/sidebars/project')
3 files changed, 54 insertions, 68 deletions
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..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 @@ -1,43 +1,34 @@ 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 { 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 { useProjectPortfolios } from '../../../../data/project' +import { useMutation } from 'react-query' const PortfolioListContainer = () => { - const currentProjectId = useActiveProject()?._id - const currentPortfolioId = useActivePortfolio()?._id - const portfolios = usePortfolios(currentProjectId) + 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 dispatch = useDispatch() const [isVisible, setVisible] = useState(false) - const router = useRouter() 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}`) + await deletePortfolio(id) + await router.push(`/projects/${currentProjectId}`) } }, } const callback = (name, targets) => { if (name) { - dispatch( - addPortfolio({ - 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 e1be51dc..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 @@ -1,47 +1,39 @@ +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 NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent' import { useProjectTopologies } from '../../../../data/topology' -import { useActiveScenario, useActiveProject, useScenarios } from '../../../../data/project' +import { usePortfolio, usePortfolioScenarios } from '../../../../data/project' import { useSchedulers, useTraces } from '../../../../data/experiments' +import { useMutation } from 'react-query' 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 { 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 dispatch = useDispatch() const [isVisible, setVisible] = useState(false) - const onNewScenario = (currentPortfolioId) => { - dispatch(setCurrentPortfolio(currentPortfolioId)) - setVisible(true) - } - const onChooseScenario = (portfolioId, scenarioId) => { - dispatch(setCurrentScenario(portfolioId, scenarioId)) - } - const onDeleteScenario = (id) => { - if (id) { - dispatch(deleteScenario(id)) - } - } + const onNewScenario = () => setVisible(true) + const onDeleteScenario = (id) => id && deleteScenario(id) const callback = (name, portfolioId, trace, topology, operational) => { if (name) { - dispatch( - addScenario({ - portfolioId, - name, - trace, - topology, - operational, - }) - ) + addScenario({ + portfolioId, + name, + trace, + topology, + operational, + }) } setVisible(false) @@ -51,11 +43,8 @@ const ScenarioListContainer = ({ portfolioId }) => { <> <ScenarioListComponent portfolioId={portfolioId} - currentProjectId={currentProjectId} - currentScenarioId={currentScenarioId} scenarios={scenarios} onNewScenario={onNewScenario} - onChooseScenario={onChooseScenario} onDeleteScenario={onDeleteScenario} /> <NewScenarioModalComponent @@ -71,4 +60,8 @@ const ScenarioListContainer = ({ portfolioId }) => { ) } +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 index 266ca495..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 @@ -3,40 +3,42 @@ 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 { getState } from '../../../../util/state-utils' -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 { useMutation } from 'react-query' const TopologyListContainer = () => { const dispatch = useDispatch() const router = useRouter() - const topologies = useProjectTopologies() + 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)) - const state = await getState(dispatch) - router.push(`/projects/${state.currentProjectId}`) + 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])) - router.push(`/projects/${state.currentProjectId}`) + deleteTopology(id) + 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) } |
