diff --git a/src/studio-home/data/api.js b/src/studio-home/data/api.js index b70af23dd..00d3b17e6 100644 --- a/src/studio-home/data/api.js +++ b/src/studio-home/data/api.js @@ -24,6 +24,7 @@ export async function getStudioHomeCourses(search) { /** * Get's studio home courses. * @param {string} search - Query string parameters for filtering the courses. + * TODO: this should be an object with a list of allowed keys and values; not a string. * @param {object} customParams - Additional custom parameters for the API request. * @returns {Promise} - A Promise that resolves to the response data containing the studio home courses. * Note: We are changing /api/contentstore/v1 to /api/contentstore/v2 due to upcoming breaking changes. diff --git a/src/studio-home/data/thunks.js b/src/studio-home/data/thunks.js index bf2742795..728aa60fb 100644 --- a/src/studio-home/data/thunks.js +++ b/src/studio-home/data/thunks.js @@ -14,6 +14,13 @@ import { fetchCourseDataSuccessV2, } from './slice'; +/** + * Load both the "Studio Home" data and the course list. Store it in the Redux state. + * + * TODO: this should be replaced with two separate React Query hooks - one that calls + * useQuery() to load the "studio home" data, and another that calls useQuery() to + * load the course list. + */ function fetchStudioHomeData( search, hasHomeData, diff --git a/src/studio-home/hooks.jsx b/src/studio-home/hooks.tsx similarity index 69% rename from src/studio-home/hooks.jsx rename to src/studio-home/hooks.tsx index d1673aae9..64abeb3ed 100644 --- a/src/studio-home/hooks.jsx +++ b/src/studio-home/hooks.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; +import { useSearchParams } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { RequestStatus } from '../data/constants'; @@ -15,8 +15,8 @@ import { import { updateSavingStatuses } from './data/slice'; const useStudioHome = () => { - const location = useLocation(); const dispatch = useDispatch(); + const [searchParams] = useSearchParams(); // The query string (location.search) const studioHomeData = useSelector(getStudioHomeData); const studioHomeCoursesParams = useSelector(getStudioHomeCoursesParams); const { isFiltered } = studioHomeCoursesParams; @@ -31,14 +31,31 @@ const useStudioHome = () => { const isLoadingPage = studioHomeLoadingStatus === RequestStatus.IN_PROGRESS; const isFailedLoadingPage = studioHomeLoadingStatus === RequestStatus.FAILED; + // FIXME: data should be loaded with React Query, not useEffect(). + // To avoid a bug where changes in the "search all courses" query would trigger a reload, + // we need to remove the search 'q' from 'searchParams' and just limit this to the search + // parameters like 'active_only' that affect the course list. But really we need to replace + // fetchStudioHomeData() with separate React Query hooks - see docstring on that method. + // TODO: this whole thing is a bit weird; we sort of read the params from the search query, + // so if you enter the URL /home?archived_only=true it only shows archived courses, but the + // UI filters won't match it, and when you change the filters it doesn't update the search query. + // We should either use the search query as the only state / source of truth or ignore it entirely. + const courseListQuery = new URLSearchParams(); + for (const key of ['org', 'search', 'order', 'active_only', 'archived_only', 'page']) { + // istanbul ignore if: this functionality is only partially implemented - see above + if (searchParams.has(key)) { + courseListQuery.set(key, searchParams.get(key)!); + } + } + const courseListQueryString = courseListQuery.size ? `?${courseListQuery.toString()}` : ''; useEffect(() => { - dispatch(fetchStudioHomeData(location.search ?? '')); + dispatch(fetchStudioHomeData(courseListQueryString)); setShowNewCourseContainer(false); - }, [location.search]); + }, [courseListQueryString]); useEffect(() => { const firstPage = 1; - dispatch(fetchStudioHomeData(location.search ?? '', false, { page: firstPage, order: 'display_name' })); + dispatch(fetchStudioHomeData(courseListQueryString, false, { page: firstPage, order: 'display_name' })); }, []); useEffect(() => {