diff --git a/ui/src/Components/MainModal/Configuration/GridLabelName.tsx b/ui/src/Components/MainModal/Configuration/GridLabelName.tsx index fe73f2fbe..13068d55d 100644 --- a/ui/src/Components/MainModal/Configuration/GridLabelName.tsx +++ b/ui/src/Components/MainModal/Configuration/GridLabelName.tsx @@ -6,7 +6,7 @@ import { useFetchGet } from "Hooks/useFetchGet"; import { FormatBackendURI } from "Stores/AlertStore"; import { Settings } from "Stores/Settings"; import { ThemeContext } from "Components/Theme"; -import { NewLabelName, StringToOption } from "Common/Select"; +import { NewLabelName, StringToOption, OptionT } from "Common/Select"; const disabledLabel = "Disable multi-grid"; @@ -25,7 +25,9 @@ const staticValues = [ const GridLabelName: FC<{ settingsStore: Settings; }> = ({ settingsStore }) => { - const { response } = useFetchGet(FormatBackendURI(`labelNames.json`)); + const { response } = useFetchGet( + FormatBackendURI(`labelNames.json`) + ); const context = React.useContext(ThemeContext); @@ -46,8 +48,8 @@ const GridLabelName: FC<{ ] : staticValues } - onChange={({ value }) => { - settingsStore.multiGridConfig.config.gridLabel = value; + onChange={(option) => { + settingsStore.multiGridConfig.config.gridLabel = (option as OptionT).value; }} /> ); diff --git a/ui/src/Components/MainModal/Configuration/SortLabelName.tsx b/ui/src/Components/MainModal/Configuration/SortLabelName.tsx index 66416073c..915c4ec22 100644 --- a/ui/src/Components/MainModal/Configuration/SortLabelName.tsx +++ b/ui/src/Components/MainModal/Configuration/SortLabelName.tsx @@ -13,7 +13,9 @@ import { NewLabelName, StringToOption } from "Common/Select"; const SortLabelName: FC<{ settingsStore: Settings; }> = ({ settingsStore }) => { - const { response } = useFetchGet(FormatBackendURI(`labelNames.json`)); + const { response } = useFetchGet( + FormatBackendURI(`labelNames.json`) + ); if (!settingsStore.gridConfig.config.sortLabel) { settingsStore.gridConfig.config.sortLabel = StaticLabels.AlertName; diff --git a/ui/src/Components/NavBar/FilterInput/index.tsx b/ui/src/Components/NavBar/FilterInput/index.tsx index dab401a63..5b28d11c4 100644 --- a/ui/src/Components/NavBar/FilterInput/index.tsx +++ b/ui/src/Components/NavBar/FilterInput/index.tsx @@ -26,7 +26,7 @@ const FilterInput: FC<{ const inputRef = useRef(null as null | HTMLElement); const formRef = useRef(null); - const [suggestions, setSuggestions] = useState([]); + const [suggestions, setSuggestions] = useState([] as string[]); const [value, setValue] = useState(""); const [isFocused, setIsFocused] = useState(false); @@ -68,13 +68,7 @@ const FilterInput: FC<{ const [term, setTerm] = useState(""); const debouncedSearchTerm = useDebounce(term, 300); - const { - response, - error, - isLoading, - get, - cancelGet, - } = useFetchGet( + const { response, error, isLoading, get, cancelGet } = useFetchGet( FormatBackendURI(`autocomplete.json?term=${debouncedSearchTerm}`), { autorun: false } ); @@ -89,7 +83,7 @@ const FilterInput: FC<{ useEffect(() => { if (error) { onSuggestionsClearRequested(); - } else if (!isLoading) { + } else if (!isLoading && response !== null) { setSuggestions(response); } }, [response, error, isLoading, onSuggestionsClearRequested]); diff --git a/ui/src/Components/PaginatedAlertList/index.tsx b/ui/src/Components/PaginatedAlertList/index.tsx index 63301451c..688ff0a7a 100644 --- a/ui/src/Components/PaginatedAlertList/index.tsx +++ b/ui/src/Components/PaginatedAlertList/index.tsx @@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; +import { APIAlertsResponseT } from "Models/APITypes"; import { AlertStore, FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore"; import { LabelSetList, @@ -33,13 +34,13 @@ const PaginatedAlertList: FC<{ filters: string[]; title?: string; }> = ({ alertStore, filters, title }) => { - const { response, error, isLoading } = useFetchGet( + const { response, error, isLoading } = useFetchGet( FormatBackendURI("alerts.json?") + FormatAlertsQ(filters) ); return isLoading ? ( - ) : error ? ( + ) : error || response === null ? ( ) : ( ( FormatBackendURI( `silences.json?sortReverse=${sortReverse ? "1" : "0"}&showExpired=${ showExpired ? "1" : "0" @@ -139,13 +136,13 @@ const Browser: FC<{ /> } /> - ) : error ? ( + ) : error || response === null ? ( ) : response.length === 0 ? ( ) : ( - {(response as APIManagedSilenceT[]) + {response .slice((activePage - 1) * maxPerPage, activePage * maxPerPage) .map((silence) => ( = ({ matcher, isValid }) => { - const { response } = useFetchGet(FormatBackendURI(`labelNames.json`)); + const { response } = useFetchGet( + FormatBackendURI(`labelNames.json`) + ); const context = React.useContext(ThemeContext); diff --git a/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.tsx b/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.tsx index e9df4ec66..b298e1185 100644 --- a/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.tsx +++ b/ui/src/Components/SilenceModal/SilenceMatch/LabelValueInput.tsx @@ -68,7 +68,7 @@ const LabelValueInput: FC<{ matcher: MatcherWithIDT; isValid: boolean; }> = observer(({ silenceFormStore, matcher, isValid }) => { - const { response, get, cancelGet } = useFetchGet( + const { response, get, cancelGet } = useFetchGet( FormatBackendURI(`labelValues.json?name=${matcher.name}`), { autorun: false } ); diff --git a/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.tsx b/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.tsx index 96e9d8a29..7aee53e0f 100644 --- a/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.tsx +++ b/ui/src/Components/SilenceModal/SilenceMatch/MatchCounter.tsx @@ -6,6 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; +import { APIAlertsResponseT } from "Models/APITypes"; import { FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore"; import { SilenceFormStore, MatcherWithIDT } from "Stores/SilenceFormStore"; import { TooltipWrapper } from "Components/TooltipWrapper"; @@ -21,9 +22,9 @@ const MatchCounter: FC<{ filters.push(AlertManagersToFilter(silenceFormStore.data.alertmanagers)); } - const { response, error, isLoading, isRetrying } = useFetchGet( - FormatBackendURI("alerts.json?") + FormatAlertsQ(filters) - ); + const { response, error, isLoading, isRetrying } = useFetchGet< + APIAlertsResponseT + >(FormatBackendURI("alerts.json?") + FormatAlertsQ(filters)); return useObserver(() => error ? ( @@ -39,7 +40,7 @@ const MatchCounter: FC<{ style={{ fontSize: "85%", lineHeight: "1rem" }} data-am={silenceFormStore.data.alertmanagers.length} > - {isLoading ? ( + {isLoading || response === null ? ( = ({ alertStore, silenceFormStore, cluster, members, payload }) => { const [upstreams, setUpstreams] = useState([] as UpstreamT[]); - const { response, error, inProgress, responseURI } = useFetchAny(upstreams); + const { response, error, inProgress, responseURI } = useFetchAny< + PostResponseT + >(upstreams); const [publicURIs, setPublicURIs] = useState({} as { [key: string]: string }); useEffect(() => { @@ -63,12 +65,11 @@ const SilenceSubmitProgress: FC<{ silenceFormStore.data.requestsByCluster[cluster].error = error; } else if (!inProgress && response !== null) { silenceFormStore.data.requestsByCluster[cluster].isDone = true; - silenceFormStore.data.requestsByCluster[ - cluster - ].silenceID = (response as PostResponseT).silenceID; + silenceFormStore.data.requestsByCluster[cluster].silenceID = + response.silenceID; silenceFormStore.data.requestsByCluster[cluster].silenceLink = `${ publicURIs[responseURI as string] - }/#/silences/${(response as PostResponseT).silenceID}`; + }/#/silences/${response.silenceID}`; } }, [cluster, error, inProgress, publicURIs, response, responseURI]); // eslint-disable-line react-hooks/exhaustive-deps diff --git a/ui/src/Hooks/useFetchAny.ts b/ui/src/Hooks/useFetchAny.ts index dfd705554..b043e805e 100644 --- a/ui/src/Hooks/useFetchAny.ts +++ b/ui/src/Hooks/useFetchAny.ts @@ -15,18 +15,18 @@ export interface FetchAnyOptionsT { fetcher?: null | FetchFunctionT; } -interface ResponseState { - response: string | { [key: string]: any } | null; +interface ResponseState { + response: T | null; error: string | null; responseURI: string | null; inProgress: boolean; } -const useFetchAny = ( +const useFetchAny = ( upstreams: UpstreamT[], { fetcher = null }: FetchAnyOptionsT = {} ): { - response: string | { [key: string]: any } | null; + response: T | null; error: string | null; responseURI: string | null; inProgress: boolean; @@ -38,7 +38,7 @@ const useFetchAny = ( error: null, responseURI: null, inProgress: false, - } as ResponseState); + } as ResponseState); const reset = useCallback(() => { setIndex(0); diff --git a/ui/src/Hooks/useFetchGet.ts b/ui/src/Hooks/useFetchGet.ts index 3b7ffc8cd..8d391c3f8 100644 --- a/ui/src/Hooks/useFetchGet.ts +++ b/ui/src/Hooks/useFetchGet.ts @@ -14,11 +14,11 @@ export interface FetchGetOptionsT { fetcher?: null | FetchFunctionT; } -const useFetchGet = ( +const useFetchGet = ( uri: string, { autorun = true, deps = [], fetcher = null }: FetchGetOptionsT = {} ): { - response: null | any; + response: null | T; error: null | string; isLoading: boolean; isRetrying: boolean; @@ -26,7 +26,7 @@ const useFetchGet = ( get: () => void; cancelGet: () => void; } => { - const [response, setResponse] = useState(null as any); + const [response, setResponse] = useState(null as null | T); const [error, setError] = useState(null as string | null); const [isLoading, setIsLoading] = useState(true); const [isRetrying, setIsRetrying] = useState(false);