From 3b0c087a2c67160f5fbd8ebce389f952e79d4fc1 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 28 Nov 2024 10:48:13 -0500 Subject: [PATCH] refact: move to RequestStatus for overview data --- src/js/components/BentoAppRouter.tsx | 3 ++- src/js/components/Overview/Counts.tsx | 9 ++++++--- .../components/Overview/Drawer/ManageChartsDrawer.tsx | 2 +- src/js/components/Overview/PublicOverview.tsx | 9 +++++---- src/js/constants/requests.ts | 3 +++ src/js/features/data/data.store.ts | 11 ++++++----- 6 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 src/js/constants/requests.ts diff --git a/src/js/components/BentoAppRouter.tsx b/src/js/components/BentoAppRouter.tsx index 6665a077..8a2e313d 100644 --- a/src/js/components/BentoAppRouter.tsx +++ b/src/js/components/BentoAppRouter.tsx @@ -18,6 +18,7 @@ import { getGenomes } from '@/features/reference/reference.store'; import Loader from '@/components/Loader'; import DefaultLayout from '@/components/Util/DefaultLayout'; import { BEACON_NETWORK_ENABLED } from '@/config'; +import { WAITING_STATES } from '@/constants/requests'; import { RequestStatus } from '@/types/requests'; import { BentoRoute } from '@/types/routes'; import { scopeEqual, validProjectDataset } from '@/utils/router'; @@ -35,7 +36,7 @@ const ScopedRoute = () => { const { selectedScope, projects, projectsStatus } = useMetadata(); useEffect(() => { - if ([RequestStatus.Idle, RequestStatus.Pending].includes(projectsStatus)) return; // Wait for projects to load first + if (WAITING_STATES.includes(projectsStatus)) return; // Wait for projects to load first // Update selectedScope based on URL parameters const valid = validProjectDataset(projects, { project: projectId, dataset: datasetId }); diff --git a/src/js/components/Overview/Counts.tsx b/src/js/components/Overview/Counts.tsx index 3ac2789b..425da8bf 100644 --- a/src/js/components/Overview/Counts.tsx +++ b/src/js/components/Overview/Counts.tsx @@ -5,6 +5,7 @@ import { BiDna } from 'react-icons/bi'; import CountsTitleWithHelp from '@/components/Util/CountsTitleWithHelp'; import { BOX_SHADOW, COUNTS_FILL } from '@/constants/overviewConstants'; +import { WAITING_STATES } from '@/constants/requests'; import { NO_RESULTS_DASHES } from '@/constants/searchConstants'; import { useAppSelector, useTranslationFn } from '@/hooks'; import { useCanSeeUncensoredCounts } from '@/hooks/censorship'; @@ -23,7 +24,7 @@ type CountEntry = { entity: BentoEntity; icon: ReactNode; count: number }; const Counts = () => { const t = useTranslationFn(); - const { counts, isFetchingData } = useAppSelector((state) => state.data); + const { counts, status } = useAppSelector((state) => state.data); const uncensoredCounts = useCanSeeUncensoredCounts(); @@ -46,18 +47,20 @@ const Counts = () => { }, ]; + const waitingForData = WAITING_STATES.includes(status); + return ( <> {t('Counts')} {data.map(({ entity, icon, count }, i) => ( - + } value={count || (uncensoredCounts ? count : NO_RESULTS_DASHES)} valueStyle={{ color: COUNTS_FILL }} prefix={icon} - loading={isFetchingData} + loading={waitingForData} /> ))} diff --git a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx index 3711aef4..f50f2854 100644 --- a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx +++ b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx @@ -13,7 +13,7 @@ const ManageChartsDrawer = ({ onManageDrawerClose, manageDrawerVisible }: Manage const dispatch = useAppDispatch(); - const sections = useAppSelector((state) => state.data.sections); + const { sections } = useAppSelector((state) => state.data); return ( { const [drawerVisible, setDrawerVisible] = useState(false); const [aboutContent, setAboutContent] = useState(''); - const { isFetchingData: isFetchingOverviewData, sections } = useAppSelector((state) => state.data); + const { status: overviewDataStatus, sections } = useAppSelector((state) => state.data); const { status: aboutStatus, about } = useAppSelector((state) => state.content); const selectedProject = useSelectedProject(); @@ -37,9 +38,9 @@ const PublicOverview = () => { useEffect(() => { // Save sections to localStorage when they change - if (isFetchingOverviewData) return; + if (overviewDataStatus != RequestStatus.Fulfilled) return; saveToLocalStorage(sections); - }, [isFetchingOverviewData, sections]); + }, [overviewDataStatus, sections]); useEffect(() => { const activeLanguage = i18n.language; @@ -58,7 +59,7 @@ const PublicOverview = () => { const searchableFields = useSearchableFields(); - return isFetchingOverviewData ? ( + return WAITING_STATES.includes(overviewDataStatus) ? ( ) : ( <> diff --git a/src/js/constants/requests.ts b/src/js/constants/requests.ts new file mode 100644 index 00000000..aedca9b5 --- /dev/null +++ b/src/js/constants/requests.ts @@ -0,0 +1,3 @@ +import { RequestStatus } from '@/types/requests'; + +export const WAITING_STATES = [RequestStatus.Idle, RequestStatus.Pending]; diff --git a/src/js/features/data/data.store.ts b/src/js/features/data/data.store.ts index a7c1fec1..4b285949 100644 --- a/src/js/features/data/data.store.ts +++ b/src/js/features/data/data.store.ts @@ -4,16 +4,17 @@ import { createSlice } from '@reduxjs/toolkit'; import { makeGetDataRequestThunk } from './makeGetDataRequest.thunk'; import type { Sections } from '@/types/data'; import type { Counts } from '@/types/overviewResponse'; +import { RequestStatus } from '@/types/requests'; interface DataState { - isFetchingData: boolean; + status: RequestStatus; defaultLayout: Sections; sections: Sections; counts: Counts; } const initialState: DataState = { - isFetchingData: true, + status: RequestStatus.Idle, defaultLayout: [], sections: [], counts: { @@ -79,16 +80,16 @@ const data = createSlice({ extraReducers: (builder) => { builder .addCase(makeGetDataRequestThunk.pending, (state) => { - state.isFetchingData = true; + state.status = RequestStatus.Pending; }) .addCase(makeGetDataRequestThunk.fulfilled, (state, { payload }) => { state.sections = payload.sectionData; state.defaultLayout = payload.defaultData; state.counts = payload.counts; - state.isFetchingData = false; + state.status = RequestStatus.Fulfilled; }) .addCase(makeGetDataRequestThunk.rejected, (state) => { - state.isFetchingData = false; + state.status = RequestStatus.Rejected; }); }, });