summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-ui/src/containers
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-07-07 16:27:49 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2021-07-07 16:28:25 +0200
commite5e5d2c65e583493870bc0b62fb185c5e757c13f (patch)
treedc9bc25517ce36e155932212f598bf2375519d34 /opendc-web/opendc-web-ui/src/containers
parentaa788a3ad18badfac8beaabdaffc88b9e52f9306 (diff)
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.
Diffstat (limited to 'opendc-web/opendc-web-ui/src/containers')
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js5
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js6
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js4
-rw-r--r--opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js5
-rw-r--r--opendc-web/opendc-web-ui/src/containers/projects/NewProjectContainer.js13
-rw-r--r--opendc-web/opendc-web-ui/src/containers/projects/ProjectActions.js13
-rw-r--r--opendc-web/opendc-web-ui/src/containers/projects/ProjectListContainer.js5
7 files changed, 31 insertions, 20 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 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}`)
}
}
diff --git a/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js b/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
index 6742bc26..ff9f9fe7 100644
--- a/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
@@ -1,9 +1,10 @@
import React from 'react'
import AppNavbarComponent from '../../components/navigation/AppNavbarComponent'
-import { useActiveProject } from '../../data/project'
+import { useActiveProjectId, useProject } from '../../data/project'
const AppNavbarContainer = (props) => {
- const project = useActiveProject()
+ const projectId = useActiveProjectId()
+ const { data: project } = useProject(projectId)
return <AppNavbarComponent {...props} project={project} />
}
diff --git a/opendc-web/opendc-web-ui/src/containers/projects/NewProjectContainer.js b/opendc-web/opendc-web-ui/src/containers/projects/NewProjectContainer.js
index e03b5c07..c844fe2d 100644
--- a/opendc-web/opendc-web-ui/src/containers/projects/NewProjectContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/projects/NewProjectContainer.js
@@ -1,20 +1,25 @@
import React, { useState } from 'react'
-import { useDispatch } from 'react-redux'
-import { addProject } from '../../redux/actions/projects'
import TextInputModal from '../../components/modals/TextInputModal'
import { Button } from 'reactstrap'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
+import { useMutation, useQueryClient } from 'react-query'
+import { addProject } from '../../api/projects'
+import { useAuth } from '../../auth'
/**
* A container for creating a new project.
*/
const NewProjectContainer = () => {
const [isVisible, setVisible] = useState(false)
- const dispatch = useDispatch()
+ const auth = useAuth()
+ const queryClient = useQueryClient()
+ const mutation = useMutation((data) => addProject(auth, data), {
+ onSuccess: (result) => queryClient.setQueryData('projects', (old) => [...(old || []), result]),
+ })
const callback = (text) => {
if (text) {
- dispatch(addProject(text))
+ mutation.mutate({ name: text })
}
setVisible(false)
}
diff --git a/opendc-web/opendc-web-ui/src/containers/projects/ProjectActions.js b/opendc-web/opendc-web-ui/src/containers/projects/ProjectActions.js
index bdb422dc..eba388d6 100644
--- a/opendc-web/opendc-web-ui/src/containers/projects/ProjectActions.js
+++ b/opendc-web/opendc-web-ui/src/containers/projects/ProjectActions.js
@@ -1,13 +1,18 @@
import React from 'react'
-import { useDispatch } from 'react-redux'
-import { deleteProject } from '../../redux/actions/projects'
import ProjectActionButtons from '../../components/projects/ProjectActionButtons'
+import { useMutation, useQueryClient } from 'react-query'
+import { useAuth } from '../../auth'
+import { deleteProject } from '../../api/projects'
const ProjectActions = (props) => {
- const dispatch = useDispatch()
+ const auth = useAuth()
+ const queryClient = useQueryClient()
+ const mutation = useMutation((projectId) => deleteProject(auth, projectId), {
+ onSuccess: () => queryClient.invalidateQueries('projects'),
+ })
const actions = {
onViewUsers: (id) => {}, // TODO implement user viewing
- onDelete: (id) => dispatch(deleteProject(id)),
+ onDelete: (id) => mutation.mutate(id),
}
return <ProjectActionButtons {...props} {...actions} />
}
diff --git a/opendc-web/opendc-web-ui/src/containers/projects/ProjectListContainer.js b/opendc-web/opendc-web-ui/src/containers/projects/ProjectListContainer.js
index 6632a8b5..91e8ac5a 100644
--- a/opendc-web/opendc-web-ui/src/containers/projects/ProjectListContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/projects/ProjectListContainer.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import ProjectList from '../../components/projects/ProjectList'
import { useAuth } from '../../auth'
import { useProjects } from '../../data/project'
+import { useQueryClient } from 'react-query'
const getVisibleProjects = (projects, filter, userId) => {
switch (filter) {
@@ -23,8 +24,8 @@ const getVisibleProjects = (projects, filter, userId) => {
const ProjectListContainer = ({ filter }) => {
const { user } = useAuth()
- const projects = useProjects()
- return <ProjectList projects={getVisibleProjects(projects, filter, user?.sub)} />
+ const { data: projects } = useProjects()
+ return <ProjectList projects={getVisibleProjects(projects ?? [], filter, user?.sub)} />
}
ProjectListContainer.propTypes = {