From fe779f5516389dd23c5d5ef8d8a05c99271f62b0 Mon Sep 17 00:00:00 2001 From: Nicholas de Paola <3079166+ndepaola@users.noreply.github.com> Date: Thu, 18 May 2023 23:35:24 +1000 Subject: [PATCH] god fucking dammit bad ugly not good solution to the race condition on page load, but it works perfectly so w/e i'm delaying each query until the backend URL to query is specified the (imo) correct solution here is to correctly invalidate tags in the presence of a race condition. seems like there's a PR to do that here: https://github.com/reduxjs/redux-toolkit/pull/3116 but no movement on it for the last few months related issue: https://github.com/reduxjs/redux-toolkit/issues/3386 --- frontend/jest.config.mjs | 1 + frontend/src/features/backend/backend.tsx | 13 ++++++------ frontend/src/features/backend/backendSlice.ts | 2 ++ frontend/src/features/import/importCSV.tsx | 6 +++++- frontend/src/features/import/importText.tsx | 10 +++++++-- frontend/src/features/import/importURL.tsx | 14 ++++++++++--- .../src/features/support/supportBackend.tsx | 7 ++++++- .../src/features/support/supportDeveloper.tsx | 2 +- frontend/src/features/ui/footer.tsx | 7 ++++++- frontend/src/features/ui/navbar.tsx | 7 +++++-- frontend/src/pages/about.tsx | 7 ++++++- frontend/src/pages/contributions.tsx | 21 +++++++++++++++---- 12 files changed, 74 insertions(+), 23 deletions(-) diff --git a/frontend/jest.config.mjs b/frontend/jest.config.mjs index fce991f31..65948c569 100644 --- a/frontend/jest.config.mjs +++ b/frontend/jest.config.mjs @@ -13,6 +13,7 @@ const config = { testEnvironment: "jest-environment-jsdom", injectGlobals: true, + testTimeout: 20_000, }; // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async diff --git a/frontend/src/features/backend/backend.tsx b/frontend/src/features/backend/backend.tsx index ec73aa138..e3d4edddf 100644 --- a/frontend/src/features/backend/backend.tsx +++ b/frontend/src/features/backend/backend.tsx @@ -21,7 +21,11 @@ import { setLocalStorageBackendURL, } from "@/common/cookies"; import { standardiseURL } from "@/common/processing"; -import { clearURL, setURL } from "@/features/backend/backendSlice"; +import { + clearURL, + selectBackendURL, + setURL, +} from "@/features/backend/backendSlice"; require("bootstrap-icons/font/bootstrap-icons.css"); interface BackendConfigProps { @@ -90,10 +94,7 @@ export function BackendConfig(props: BackendConfigProps) { >([]); const [validating, setValidating] = useState(false); - const [triggerFn, getBackendInfoQuery] = - apiSlice.endpoints.getBackendInfo.useLazyQuery(); - - const backendURL = useSelector((state: RootState) => state.backend.url); + const backendURL = useSelector(selectBackendURL); const clearBackendURL = () => { dispatch(clearURL()); clearLocalStorageBackendURL(); @@ -139,7 +140,6 @@ export function BackendConfig(props: BackendConfigProps) { setLocalStorageBackendURL(formattedURL); dispatch(apiSlice.util.invalidateTags([QueryTags.BackendSpecific])); setLocalBackendURL(""); - triggerFn(); } setValidating(false); }; @@ -149,7 +149,6 @@ export function BackendConfig(props: BackendConfigProps) { if (backendURL != undefined) { dispatch(setURL(backendURL)); dispatch(apiSlice.util.invalidateTags([QueryTags.BackendSpecific])); - triggerFn(); } }, []); diff --git a/frontend/src/features/backend/backendSlice.ts b/frontend/src/features/backend/backendSlice.ts index 127596838..00091391c 100644 --- a/frontend/src/features/backend/backendSlice.ts +++ b/frontend/src/features/backend/backendSlice.ts @@ -27,3 +27,5 @@ export const backendSlice = createSlice({ export const { setURL, clearURL } = backendSlice.actions; export default backendSlice.reducer; + +export const selectBackendURL = (state: RootState) => state.backend.url; diff --git a/frontend/src/features/import/importCSV.tsx b/frontend/src/features/import/importCSV.tsx index 5ee3feeec..5174cd3f5 100644 --- a/frontend/src/features/import/importCSV.tsx +++ b/frontend/src/features/import/importCSV.tsx @@ -24,6 +24,7 @@ import { convertLinesIntoSlotProjectMembers, processLines, } from "@/common/processing"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import { addMembers, selectProjectSize } from "@/features/project/projectSlice"; const BorderedTable = styled(Table)` @@ -138,7 +139,10 @@ function SampleCSV() { export function ImportCSV() { const dispatch = useDispatch(); - const dfcPairsQuery = useGetDFCPairsQuery(); + const backendURL = useSelector(selectBackendURL); + const dfcPairsQuery = useGetDFCPairsQuery(undefined, { + skip: backendURL == null, + }); const [showCSVModal, setShowCSVModal] = useState(false); const handleCloseCSVModal = () => setShowCSVModal(false); const handleShowCSVModal = () => setShowCSVModal(true); diff --git a/frontend/src/features/import/importText.tsx b/frontend/src/features/import/importText.tsx index 9006c45c7..2428d721f 100644 --- a/frontend/src/features/import/importText.tsx +++ b/frontend/src/features/import/importText.tsx @@ -27,12 +27,18 @@ import { stripTextInParentheses, } from "@/common/processing"; import { CardDocument } from "@/common/types"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import { addMembers, selectProjectSize } from "@/features/project/projectSlice"; export function ImportText() { // TODO: add an accordion here for explaining how to search for each different card type with prefixes - const sampleCardsQuery = useGetSampleCardsQuery(); - const dfcPairsQuery = useGetDFCPairsQuery(); + const backendURL = useSelector(selectBackendURL); + const sampleCardsQuery = useGetSampleCardsQuery(undefined, { + skip: backendURL == null, + }); + const dfcPairsQuery = useGetDFCPairsQuery(undefined, { + skip: backendURL == null, + }); const dispatch = useDispatch(); const [showTextModal, setShowTextModal] = useState(false); diff --git a/frontend/src/features/import/importURL.tsx b/frontend/src/features/import/importURL.tsx index ea17eb9ce..d5ec5ebc0 100644 --- a/frontend/src/features/import/importURL.tsx +++ b/frontend/src/features/import/importURL.tsx @@ -26,13 +26,21 @@ import { convertLinesIntoSlotProjectMembers, processStringAsMultipleLines, } from "@/common/processing"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import { addMembers, selectProjectSize } from "@/features/project/projectSlice"; import { Spinner } from "@/features/ui/spinner"; export function ImportURL() { - const dfcPairsQuery = useGetDFCPairsQuery(); - const importSitesQuery = useGetImportSitesQuery(); - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const dfcPairsQuery = useGetDFCPairsQuery(undefined, { + skip: backendURL == null, + }); + const importSitesQuery = useGetImportSitesQuery(undefined, { + skip: backendURL == null, + }); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); const projectSize = useSelector(selectProjectSize); const dispatch = useDispatch(); diff --git a/frontend/src/features/support/supportBackend.tsx b/frontend/src/features/support/supportBackend.tsx index 5d7327f2d..7ce2997ec 100644 --- a/frontend/src/features/support/supportBackend.tsx +++ b/frontend/src/features/support/supportBackend.tsx @@ -1,8 +1,10 @@ import React from "react"; import Button from "react-bootstrap/Button"; import Modal from "react-bootstrap/Modal"; +import { useSelector } from "react-redux"; import { useGetBackendInfoQuery } from "@/app/api"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import { Spinner } from "@/features/ui/spinner"; interface SupportBackendModalProps { @@ -14,7 +16,10 @@ interface SupportBackendModalProps { } export function SupportBackendModal(props: SupportBackendModalProps) { - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); return ( diff --git a/frontend/src/features/support/supportDeveloper.tsx b/frontend/src/features/support/supportDeveloper.tsx index 1f733e324..f3be9e05e 100644 --- a/frontend/src/features/support/supportDeveloper.tsx +++ b/frontend/src/features/support/supportDeveloper.tsx @@ -31,7 +31,7 @@ export function SupportDeveloperModal(props: SupportDeveloperModalProps) {

I'm responsible for this website, the code that image repository - servers run on, and the desktop tool that automates + servers run on, and the desktop tool that automates{" "} {MakePlayingCards} diff --git a/frontend/src/features/ui/footer.tsx b/frontend/src/features/ui/footer.tsx index 1991e54c2..c57ec6c10 100644 --- a/frontend/src/features/ui/footer.tsx +++ b/frontend/src/features/ui/footer.tsx @@ -1,6 +1,8 @@ import Link from "next/link"; +import { useSelector } from "react-redux"; import { useGetBackendInfoQuery } from "@/app/api"; +import { selectBackendURL } from "@/features/backend/backendSlice"; function Spacer() { return ( @@ -9,7 +11,10 @@ function Spacer() { } export default function Footer() { - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); return ( <>


diff --git a/frontend/src/features/ui/navbar.tsx b/frontend/src/features/ui/navbar.tsx index 8b5eaf41b..b37779b88 100644 --- a/frontend/src/features/ui/navbar.tsx +++ b/frontend/src/features/ui/navbar.tsx @@ -13,6 +13,7 @@ import { useGetBackendInfoQuery } from "@/app/api"; import { RootState } from "@/app/store"; import { ProjectName } from "@/common/constants"; import { BackendConfig } from "@/features/backend/backend"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import { SupportBackendModal } from "@/features/support/supportBackend"; import { SupportDeveloperModal } from "@/features/support/supportDeveloper"; import DisableSSR from "@/features/ui/disableSSR"; @@ -30,7 +31,10 @@ const BoldCollapse = styled(BSNavbar.Collapse)` `; export default function Navbar() { - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); const [showBackendConfig, setShowBackendConfig] = useState(false); const [showSupportDeveloperModal, setShowSupportDeveloperModal] = @@ -47,7 +51,6 @@ export default function Navbar() { setShowSupportBackendModal(false); const handleShowSupportBackendModal = () => setShowSupportBackendModal(true); - const backendURL = useSelector((state: RootState) => state.backend.url); const name = (backendInfoQuery.isSuccess ? backendInfoQuery.data?.name : null) ?? ProjectName; diff --git a/frontend/src/pages/about.tsx b/frontend/src/pages/about.tsx index ba796e8ef..fa3a7f593 100644 --- a/frontend/src/pages/about.tsx +++ b/frontend/src/pages/about.tsx @@ -1,9 +1,11 @@ import Head from "next/head"; +import { useSelector } from "react-redux"; import styled from "styled-components"; import { useGetBackendInfoQuery } from "@/app/api"; import { ProjectName } from "@/common/constants"; import { MakePlayingCards, MakePlayingCardsURL } from "@/common/constants"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import Footer from "@/features/ui/footer"; import Layout from "@/features/ui/layout"; @@ -12,7 +14,10 @@ const CentreAligned = styled.div` `; function BackendDescription() { - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); return ( <> diff --git a/frontend/src/pages/contributions.tsx b/frontend/src/pages/contributions.tsx index fac63596f..2f18b8420 100644 --- a/frontend/src/pages/contributions.tsx +++ b/frontend/src/pages/contributions.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import React from "react"; import Alert from "react-bootstrap/Alert"; import Table from "react-bootstrap/Table"; +import { useSelector } from "react-redux"; import styled from "styled-components"; import { useGetBackendInfoQuery, useGetContributionsQuery } from "@/app/api"; @@ -15,6 +16,7 @@ import { Token, } from "@/common/constants"; import { SourceContribution } from "@/common/types"; +import { selectBackendURL } from "@/features/backend/backendSlice"; import Footer from "@/features/ui/footer"; import Layout from "@/features/ui/layout"; import { Spinner } from "@/features/ui/spinner"; @@ -24,8 +26,13 @@ const AutoLayoutTable = styled(Table)` `; function ContributionsSummary() { - const contributionsQuery = useGetContributionsQuery(); - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const contributionsQuery = useGetContributionsQuery(undefined, { + skip: backendURL == null, + }); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); const totalImages = contributionsQuery.data?.card_count_by_type != null @@ -73,7 +80,10 @@ function ContributionsSummary() { } function ContributionGuidelines() { - const backendInfoQuery = useGetBackendInfoQuery(); + const backendURL = useSelector(selectBackendURL); + const backendInfoQuery = useGetBackendInfoQuery(undefined, { + skip: backendURL == null, + }); const name = backendInfoQuery.data?.name ?? ProjectName; @@ -166,7 +176,10 @@ function sourceContributionRow(contribution: SourceContribution) { } function ContributionsPerSource() { - const contributionsQuery = useGetContributionsQuery(); + const backendURL = useSelector(selectBackendURL); + const contributionsQuery = useGetContributionsQuery(undefined, { + skip: backendURL == null, + }); return contributionsQuery.isSuccess ? ( contributionsQuery.isLoading || contributionsQuery.data?.sources == null ? (