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. --- opendc-web/opendc-web-ui/src/data/topology.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/data/topology.js') diff --git a/opendc-web/opendc-web-ui/src/data/topology.js b/opendc-web/opendc-web-ui/src/data/topology.js index d3ffb3e1..f6ce1672 100644 --- a/opendc-web/opendc-web-ui/src/data/topology.js +++ b/opendc-web/opendc-web-ui/src/data/topology.js @@ -21,6 +21,7 @@ */ import { useSelector } from 'react-redux' +import { useRouter } from 'next/router' /** * Return the current active topology. @@ -33,8 +34,10 @@ export function useActiveTopology() { * Return the topologies for the active project. */ export function useProjectTopologies() { - return useSelector(({ currentProjectId, objects }) => { - if (currentProjectId === '-1' || !objects.project[currentProjectId]) { + const router = useRouter() + const { project: currentProjectId } = router.query + return useSelector(({ objects }) => { + if (!currentProjectId || !objects.project[currentProjectId]) { return [] } -- 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. --- opendc-web/opendc-web-ui/src/data/topology.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/data/topology.js') diff --git a/opendc-web/opendc-web-ui/src/data/topology.js b/opendc-web/opendc-web-ui/src/data/topology.js index f6ce1672..4c746a7e 100644 --- a/opendc-web/opendc-web-ui/src/data/topology.js +++ b/opendc-web/opendc-web-ui/src/data/topology.js @@ -21,7 +21,7 @@ */ import { useSelector } from 'react-redux' -import { useRouter } from 'next/router' +import { useActiveProjectId, useProject } from './project' /** * Return the current active topology. @@ -34,14 +34,14 @@ export function useActiveTopology() { * Return the topologies for the active project. */ export function useProjectTopologies() { - const router = useRouter() - const { project: currentProjectId } = router.query + const projectId = useActiveProjectId() + const { data: project } = useProject(projectId) return useSelector(({ objects }) => { - if (!currentProjectId || !objects.project[currentProjectId]) { + if (!project) { return [] } - const topologies = objects.project[currentProjectId].topologyIds.map((t) => objects.topology[t]) + const topologies = project.topologyIds.map((t) => objects.topology[t]) if (topologies.filter((t) => !t).length > 0) { return [] -- 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 --- opendc-web/opendc-web-ui/src/data/topology.js | 55 ++++++++++++++++++--------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/data/topology.js') diff --git a/opendc-web/opendc-web-ui/src/data/topology.js b/opendc-web/opendc-web-ui/src/data/topology.js index 4c746a7e..92911a70 100644 --- a/opendc-web/opendc-web-ui/src/data/topology.js +++ b/opendc-web/opendc-web-ui/src/data/topology.js @@ -21,7 +21,40 @@ */ import { useSelector } from 'react-redux' -import { useActiveProjectId, useProject } from './project' +import { useQueries } from 'react-query' +import { addTopology, deleteTopology, fetchTopology, updateTopology } from '../api/topologies' + +/** + * Configure the query defaults for the topology endpoints. + */ +export function configureTopologyClient(queryClient, auth) { + queryClient.setQueryDefaults('topologies', { queryFn: ({ queryKey }) => fetchTopology(auth, queryKey[1]) }) + + queryClient.setMutationDefaults('addTopology', { + mutationFn: (data) => addTopology(auth, data), + onSuccess: async (result) => { + queryClient.setQueryData(['projects', result.projectId], (old) => ({ + ...old, + topologyIds: [...old.topologyIds, result._id], + })) + queryClient.setQueryData(['topologies', result._id], result) + }, + }) + queryClient.setMutationDefaults('updateTopology', { + mutationFn: (data) => updateTopology(auth, data), + onSuccess: async (result) => queryClient.setQueryData(['topologies', result._id], result), + }) + queryClient.setMutationDefaults('deleteTopology', { + mutationFn: (id) => deleteTopology(auth, id), + onSuccess: async (result) => { + queryClient.setQueryData(['projects', result.projectId], (old) => ({ + ...old, + topologyIds: old.topologyIds.filter((id) => id !== result._id), + })) + queryClient.removeQueries(['topologies', result._id]) + }, + }) +} /** * Return the current active topology. @@ -31,22 +64,8 @@ export function useActiveTopology() { } /** - * Return the topologies for the active project. + * Return the scenarios with the specified identifiers. */ -export function useProjectTopologies() { - const projectId = useActiveProjectId() - const { data: project } = useProject(projectId) - return useSelector(({ objects }) => { - if (!project) { - return [] - } - - const topologies = project.topologyIds.map((t) => objects.topology[t]) - - if (topologies.filter((t) => !t).length > 0) { - return [] - } - - return topologies - }) +export function useTopologies(topologyIds) { + return useQueries(topologyIds.map((topologyId) => ({ queryKey: ['topologies', topologyId] }))) } -- 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. --- opendc-web/opendc-web-ui/src/data/topology.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/data/topology.js') diff --git a/opendc-web/opendc-web-ui/src/data/topology.js b/opendc-web/opendc-web-ui/src/data/topology.js index 92911a70..8db75877 100644 --- a/opendc-web/opendc-web-ui/src/data/topology.js +++ b/opendc-web/opendc-web-ui/src/data/topology.js @@ -21,14 +21,17 @@ */ import { useSelector } from 'react-redux' -import { useQueries } from 'react-query' -import { addTopology, deleteTopology, fetchTopology, updateTopology } from '../api/topologies' +import { useQueries, useQuery } from 'react-query' +import { addTopology, deleteTopology, fetchTopologiesOfProject, fetchTopology, updateTopology } from '../api/topologies' /** * Configure the query defaults for the topology endpoints. */ export function configureTopologyClient(queryClient, auth) { queryClient.setQueryDefaults('topologies', { queryFn: ({ queryKey }) => fetchTopology(auth, queryKey[1]) }) + queryClient.setQueryDefaults('project-topologies', { + queryFn: ({ queryKey }) => fetchTopologiesOfProject(auth, queryKey[1]), + }) queryClient.setMutationDefaults('addTopology', { mutationFn: (data) => addTopology(auth, data), @@ -64,8 +67,8 @@ export function useActiveTopology() { } /** - * Return the scenarios with the specified identifiers. + * Return the topologies of the specified project. */ -export function useTopologies(topologyIds) { - return useQueries(topologyIds.map((topologyId) => ({ queryKey: ['topologies', topologyId] }))) +export function useProjectTopologies(projectId) { + return useQuery(['project-topologies', projectId], { enabled: !!projectId }) } -- cgit v1.2.3