From 7a167f7b8ba47c35dc79e6c1769f37fd07cf267c Mon Sep 17 00:00:00 2001 From: Gregor Billing Date: Tue, 31 Dec 2024 16:46:40 +0900 Subject: [PATCH 1/4] Remove toggle for registration status in comp overview --- .../CompetitionsFilters.js | 52 +++++++++---------- .../CompetitionsOverview/CompetitionsView.js | 38 ++------------ .../CompetitionsOverview/ListView.js | 16 ------ .../CompetitionsOverview/ListViewSection.js | 48 ++--------------- 4 files changed, 30 insertions(+), 124 deletions(-) diff --git a/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js b/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js index 9145b98a90..a285cb7cc6 100644 --- a/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js +++ b/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js @@ -16,6 +16,7 @@ import UtcDatePicker from '../wca/UtcDatePicker'; function CompetitionsFilters({ filterState, dispatchFilter, + displayMode, shouldShowAdminDetails, canViewAdminDetails, }) { @@ -49,6 +50,16 @@ function CompetitionsFilters({ + + + + {canViewAdminDetails && shouldShowAdminDetails && ( @@ -428,8 +439,6 @@ function CustomDateSelector({ filterState, dispatchFilter }) { export function CompDisplayCheckboxes({ shouldIncludeCancelled, dispatchFilter, - shouldShowRegStatus, - setShouldShowRegStatus, shouldShowAdminDetails, canViewAdminDetails, displayMode, @@ -449,32 +458,19 @@ export function CompDisplayCheckboxes({ { - displayMode === 'list' && ( - <> -
- setShouldShowRegStatus(!shouldShowRegStatus)} - /> -
- {canViewAdminDetails && ( -
- dispatchFilter( - { shouldShowAdminDetails: !shouldShowAdminDetails }, - )} - /> -
- )} - + displayMode === 'list' && canViewAdminDetails && ( +
+ dispatchFilter( + { shouldShowAdminDetails: !shouldShowAdminDetails }, + )} + /> +
) } diff --git a/app/webpacker/components/CompetitionsOverview/CompetitionsView.js b/app/webpacker/components/CompetitionsOverview/CompetitionsView.js index 859df26b0c..e679017947 100644 --- a/app/webpacker/components/CompetitionsOverview/CompetitionsView.js +++ b/app/webpacker/components/CompetitionsOverview/CompetitionsView.js @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useReducer, useState, } from 'react'; -import { keepPreviousData, useInfiniteQuery, useQuery } from '@tanstack/react-query'; +import { useInfiniteQuery } from '@tanstack/react-query'; import { Button, Container, @@ -44,7 +44,7 @@ function CompetitionsView({ canViewAdminDetails = false }) { ); const debouncedFilterState = useDebounce(filterState, DEBOUNCE_MS); const [displayMode, setDisplayMode] = useState(() => getDisplayMode(searchParams)); - const [shouldShowRegStatus, setShouldShowRegStatus] = useState(false); + const competitionQueryKey = useMemo( () => calculateQueryKey(debouncedFilterState, canViewAdminDetails), [debouncedFilterState, canViewAdminDetails], @@ -84,35 +84,7 @@ function CompetitionsView({ canViewAdminDetails = false }) { }, }); - const baseCompetitions = rawCompetitionData?.pages.flatMap((page) => page.data); - const compIds = baseCompetitions?.map((comp) => comp.id) || []; - - const { - data: compRegistrationData, - isFetching: regDataIsPending, - } = useQuery({ - queryFn: () => fetchJsonOrError(apiV0Urls.competitions.registrationData, { - headers: { - 'Content-Type': 'application/json', - }, - method: 'POST', - body: JSON.stringify({ ids: compIds }), - }), - queryKey: ['registration-info', ...compIds], - enabled: shouldShowRegStatus && compIds.length > 0, - // This is where the magic happens: Using `keepPreviousData` makes it so that - // all previously loaded indicators are held in-cache while the fetcher for the next - // batch is running in the background. (Adding comment here because it's not in the docs) - placeholderData: keepPreviousData, - select: (data) => data.data, - }); - - const competitions = useMemo(() => (shouldShowRegStatus ? ( - baseCompetitions?.map((comp) => { - const regData = compRegistrationData?.find((reg) => reg.id === comp.id); - return regData ? { ...comp, ...regData } : comp; - }) - ) : baseCompetitions), [baseCompetitions, compRegistrationData, shouldShowRegStatus]); + const competitions = rawCompetitionData?.pages.flatMap((page) => page.data); const [showFilters, setShowFilters] = useState(true); @@ -162,8 +134,6 @@ function CompetitionsView({ canViewAdminDetails = false }) { diff --git a/app/webpacker/components/CompetitionsOverview/ListView.js b/app/webpacker/components/CompetitionsOverview/ListView.js index 4bbd66e5a5..0eff01641f 100644 --- a/app/webpacker/components/CompetitionsOverview/ListView.js +++ b/app/webpacker/components/CompetitionsOverview/ListView.js @@ -11,10 +11,8 @@ import { isInProgress, isProbablyOver } from '../../lib/utils/competition-table' function ListView({ competitions, filterState, - shouldShowRegStatus, shouldShowAdminDetails, isLoading, - regStatusLoading, fetchMoreCompetitions, hasMoreCompsToLoad, }) { @@ -39,10 +37,8 @@ function ListView({ @@ -68,9 +64,7 @@ function ListView({ @@ -78,9 +72,7 @@ function ListView({ @@ -99,11 +91,9 @@ function ListView({ @@ -163,11 +149,9 @@ function ListView({ ) : ( @@ -59,8 +55,6 @@ function ListViewSection({ competitions={competitions} isLoading={isLoading} hasMoreCompsToLoad={hasMoreCompsToLoad} - shouldShowRegStatus={shouldShowRegStatus} - regStatusLoading={regStatusLoading} isSortedByAnnouncement={isSortedByAnnouncement} /> )} @@ -73,8 +67,6 @@ function ResponsiveCompetitionsTables({ competitions, isLoading, hasMoreCompsToLoad, - shouldShowRegStatus, - regStatusLoading, isSortedByAnnouncement, }) { const noCompetitions = !competitions || competitions.length === 0; @@ -91,8 +83,6 @@ function ResponsiveCompetitionsTables({ @@ -100,8 +90,6 @@ function ResponsiveCompetitionsTables({ @@ -109,8 +97,6 @@ function ResponsiveCompetitionsTables({ @@ -120,8 +106,6 @@ function ResponsiveCompetitionsTables({ export function CompetitionsTable({ competitions, - shouldShowRegStatus, - regStatusLoading, isSortedByAnnouncement = false, }) { return ( @@ -148,9 +132,7 @@ export function CompetitionsTable({ @@ -177,8 +159,6 @@ export function CompetitionsTable({ export function CompetitionsTabletTable({ competitions, - shouldShowRegStatus, - regStatusLoading, isSortedByAnnouncement = false, }) { return ( @@ -204,9 +184,7 @@ export function CompetitionsTabletTable({ @@ -233,8 +211,6 @@ export function CompetitionsTabletTable({ export function CompetitionsMobileTable({ competitions, - shouldShowRegStatus, - regStatusLoading, isSortedByAnnouncement = false, }) { return ( @@ -253,9 +229,7 @@ export function CompetitionsMobileTable({ @@ -288,9 +262,7 @@ function AdminCompetitionsTable({ competitions, isLoading, hasMoreCompsToLoad, - shouldShowRegStatus, selectedDelegate, - regStatusLoading, isSortedByAnnouncement, }) { const noCompetitions = !competitions || competitions.length === 0; @@ -333,9 +305,7 @@ function AdminCompetitionsTable({ @@ -437,14 +407,7 @@ function ConditionalYearHeader({ } } -function RegistrationStatus({ comp, isLoading }) { - // It is important that we check both conditions, because the query hook - // uses a `keepPreviousData` trick that holds existing data in-memory while - // also executing the query for the next batch of rows in the background. - if (isLoading && !comp.registration_status) { - return (); - } - +function RegistrationStatus({ comp }) { if (comp.registration_status === 'not_yet_opened') { return ( ; } else if (isSortedByAnnouncement) { tooltipInfo = I18n.t('competitions.index.tooltips.hourglass.announced_on', { announcement_date: comp.announced_at }); iconClass = 'hourglass start'; } else { - tooltipInfo = I18n.t('competitions.index.tooltips.hourglass.starts_in', { days: I18n.t('common.days', { count: dayDifferenceFromToday(comp.start_date) }) }); - iconClass = 'hourglass start'; + return ; } return ( From bbe5ee239ee05890ae4be16ab4635dfa7df9caaa Mon Sep 17 00:00:00 2001 From: Gregor Billing Date: Tue, 31 Dec 2024 16:55:11 +0900 Subject: [PATCH 2/4] Include registration status by default in competitions_index --- app/controllers/api/v0/competitions_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/v0/competitions_controller.rb b/app/controllers/api/v0/competitions_controller.rb index d37b345614..d16540777a 100644 --- a/app/controllers/api/v0/competitions_controller.rb +++ b/app/controllers/api/v0/competitions_controller.rb @@ -25,7 +25,7 @@ def competition_index competitions = competitions_scope.search(params[:q], params: params) - serial_methods = ["short_display_name", "city", "country_iso2", "event_ids", "date_range", "latitude_degrees", "longitude_degrees"] + serial_methods = ["short_display_name", "city", "country_iso2", "event_ids", "date_range", "latitude_degrees", "longitude_degrees", "registration_status"] serial_includes = {} serial_includes["delegates"] = { only: ["id", "name"], methods: [], include: ["avatar"] } if admin_mode From 233918706c7513c13088530e418876882f14aafb Mon Sep 17 00:00:00 2001 From: Gregor Billing Date: Sat, 4 Jan 2025 19:53:09 +0900 Subject: [PATCH 3/4] Use cached registration status in list_index --- app/controllers/api/v0/competitions_controller.rb | 2 +- app/models/competition.rb | 6 ++++++ .../components/CompetitionsOverview/ListViewSection.js | 8 ++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v0/competitions_controller.rb b/app/controllers/api/v0/competitions_controller.rb index d16540777a..4fa21ad8da 100644 --- a/app/controllers/api/v0/competitions_controller.rb +++ b/app/controllers/api/v0/competitions_controller.rb @@ -25,7 +25,7 @@ def competition_index competitions = competitions_scope.search(params[:q], params: params) - serial_methods = ["short_display_name", "city", "country_iso2", "event_ids", "date_range", "latitude_degrees", "longitude_degrees", "registration_status"] + serial_methods = ["short_display_name", "city", "country_iso2", "event_ids", "date_range", "latitude_degrees", "longitude_degrees", "cached_registration_status"] serial_includes = {} serial_includes["delegates"] = { only: ["id", "name"], methods: [], include: ["avatar"] } if admin_mode diff --git a/app/models/competition.rb b/app/models/competition.rb index 358ad74b69..1e95a247ea 100644 --- a/app/models/competition.rb +++ b/app/models/competition.rb @@ -1008,6 +1008,12 @@ def registration_status end end + def cached_registration_status + Rails.cache.fetch(["comp-registration-status", self.id], expires_in: 5.minutes) do + self.registration_status + end + end + def any_registrations? self.registrations.any? end diff --git a/app/webpacker/components/CompetitionsOverview/ListViewSection.js b/app/webpacker/components/CompetitionsOverview/ListViewSection.js index 3f76a5d9b6..b375bf6090 100644 --- a/app/webpacker/components/CompetitionsOverview/ListViewSection.js +++ b/app/webpacker/components/CompetitionsOverview/ListViewSection.js @@ -408,7 +408,7 @@ function ConditionalYearHeader({ } function RegistrationStatus({ comp }) { - if (comp.registration_status === 'not_yet_opened') { + if (comp.cached_registration_status === 'not_yet_opened') { return ( } @@ -418,7 +418,7 @@ function RegistrationStatus({ comp }) { /> ); } - if (comp.registration_status === 'past') { + if (comp.cached_registration_status === 'past') { return ( } @@ -428,7 +428,7 @@ function RegistrationStatus({ comp }) { /> ); } - if (comp.registration_status === 'full') { + if (comp.cached_registration_status === 'full') { return ( } @@ -438,7 +438,7 @@ function RegistrationStatus({ comp }) { /> ); } - if (comp.registration_status === 'open') { + if (comp.cached_registration_status === 'open') { return ( } From fa8cbd4c153370911fc497c573a9a7bc0629d7eb Mon Sep 17 00:00:00 2001 From: Gregor Billing Date: Mon, 6 Jan 2025 12:13:31 +0900 Subject: [PATCH 4/4] Clean up merge whoopsie --- .../CompetitionsFilters.js | 16 ++++++------ .../CompetitionsOverview/CompetitionsView.js | 25 +++++-------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js b/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js index a285cb7cc6..b2f8c8c85d 100644 --- a/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js +++ b/app/webpacker/components/CompetitionsOverview/CompetitionsFilters.js @@ -31,17 +31,17 @@ function CompetitionsFilters({ />
- - + + - + {shouldShowAdminDetails && ( - + )} @@ -61,11 +61,9 @@ function CompetitionsFilters({ {canViewAdminDetails && shouldShowAdminDetails && ( - - - - - + + + )} ); diff --git a/app/webpacker/components/CompetitionsOverview/CompetitionsView.js b/app/webpacker/components/CompetitionsOverview/CompetitionsView.js index e679017947..45d33caaf0 100644 --- a/app/webpacker/components/CompetitionsOverview/CompetitionsView.js +++ b/app/webpacker/components/CompetitionsOverview/CompetitionsView.js @@ -5,7 +5,6 @@ import { useInfiniteQuery } from '@tanstack/react-query'; import { Button, Container, - Form, Header, Icon, Segment, @@ -16,7 +15,7 @@ import I18n from '../../lib/i18n'; import { apiV0Urls, WCA_API_PAGINATION } from '../../lib/requests/routes.js.erb'; import { fetchJsonOrError } from '../../lib/requests/fetchWithAuthenticityToken'; -import CompetitionsFilters, { CompDisplayCheckboxes, ToggleListOrMapDisplay } from './CompetitionsFilters'; +import CompetitionsFilters, { ToggleListOrMapDisplay } from './CompetitionsFilters'; import ListView from './ListView'; import MapView from './MapView'; import { @@ -125,27 +124,15 @@ function CompetitionsView({ canViewAdminDetails = false }) { dispatchFilter={dispatchFilter} shouldShowAdminDetails={shouldShowAdminDetails} canViewAdminDetails={canViewAdminDetails} + displayMode={displayMode} /> -
- - - - - - -
+ {