diff --git a/src/views/IOC/CreateIOCAccessControl.tsx b/src/views/IOC/CreateIOCAccessControl.tsx index 1af87b467455115fa9f7d6749caa7c8969851cee..16c7bf4c2b1e444d5dc7350c0dd0e595ef1bc59c 100644 --- a/src/views/IOC/CreateIOCAccessControl.tsx +++ b/src/views/IOC/CreateIOCAccessControl.tsx @@ -9,7 +9,7 @@ export const CreateIOCAccessControl = () => { renderNoAccess={() => ( <Navigate to="/" - push + replace /> )} > diff --git a/src/views/IOC/CreateIOCView.tsx b/src/views/IOC/CreateIOCView.tsx index 667a9ab3f5d3caed01faedbf6ea52a34fe3d2744..37d4d4918b8a3de0a6540506a1946bfa6d099f2d 100644 --- a/src/views/IOC/CreateIOCView.tsx +++ b/src/views/IOC/CreateIOCView.tsx @@ -2,9 +2,10 @@ import { GlobalAppBarContext } from "@ess-ics/ce-ui-common"; import { useContext, useEffect } from "react"; import { applicationTitle } from "../../components/common/Helper"; import { CreateIOC } from "../../components/IOC/CreateIOC"; +import { GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; export const CreateIOCView = () => { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("Create IOC")), [setTitle]); return <CreateIOC />; diff --git a/src/views/IOC/IOCDetailsContainer.tsx b/src/views/IOC/IOCDetailsContainer.tsx index 638b6cd06cb281fac03e015780950b3a4b839ef6..38bfccdfe8131d6d427d3e5a5010b56ca62c64e0 100644 --- a/src/views/IOC/IOCDetailsContainer.tsx +++ b/src/views/IOC/IOCDetailsContainer.tsx @@ -8,12 +8,15 @@ import { ApiAlertError } from "../../components/common/Alerts/ApiAlertError"; const IOC_POLL_INTERVAL = 5000; -export function IOCDetailsContainer({ id }) { +export function IOCDetailsContainer({ id }: { id?: string }) { const { data: ioc, isLoading, error - } = useGetIocQuery({ iocId: id }, { pollingInterval: IOC_POLL_INTERVAL }); + } = useGetIocQuery( + { iocId: Number(id) || 0 }, + { skip: !id, pollingInterval: IOC_POLL_INTERVAL } + ); if (error && "status" in error && error.status === 404) { return <NotFoundView />; diff --git a/src/views/IOC/IOCListView.tsx b/src/views/IOC/IOCListView.tsx index b28bb7724b77aaebd5d625fb826593268727c4e5..b439afcd21a2d46a4dc7d1ac35392d670a4dc4dc 100644 --- a/src/views/IOC/IOCListView.tsx +++ b/src/views/IOC/IOCListView.tsx @@ -65,7 +65,10 @@ export const IOCListView = () => { useEffect(() => { const requestParams = Object.assign( {}, - initRequestParams(pagination, searchParams.get("query")), + initRequestParams({ + pagination, + filter: searchParams.get("query") || "" + }), { deploymentStatus: deploymentStatus } ); diff --git a/src/views/UserPage/UserDetailsContainer.tsx b/src/views/UserPage/UserDetailsContainer.tsx index 40b2b575158aed237a9df7b92660d291302c97a0..94dceab9f2af3660a941f929bd9ffc02970cf3d1 100644 --- a/src/views/UserPage/UserDetailsContainer.tsx +++ b/src/views/UserPage/UserDetailsContainer.tsx @@ -5,11 +5,15 @@ import { userContext, RootPaper } from "@ess-ics/ce-ui-common"; import { UserPageView } from "./UserPageView"; import { NotFoundView } from "../../components/navigation/NotFoundView/NotFoundView"; import { useInfoFromUserNameQuery } from "../../store/deployApi"; +import { UserContext } from "../../types/common"; +import { getErrorState } from "../../components/common/Alerts/AlertsData"; export function UserDetailsContainer() { const { userName } = useParams(); - const { user } = useContext(userContext); - const [error, setError] = useState(null); + const { user } = useContext<UserContext>(userContext); + const [error, setError] = useState< + { message: string; status: string } | undefined + >(undefined); const { data: userInfo, @@ -19,7 +23,7 @@ export function UserDetailsContainer() { useEffect(() => { if (userInfoResponseError) { - const { status } = userInfoResponseError; + const { status } = getErrorState(userInfoResponseError); if (status === 404) { setError({ message: "Page not found", status: `${status}` }); } @@ -56,7 +60,6 @@ export function UserDetailsContainer() { <RootPaper> <UserPageView userName={userName} - user={user} userInfo={userInfo} /> </RootPaper> diff --git a/src/views/UserPage/UserPageView.tsx b/src/views/UserPage/UserPageView.tsx index 2f92f8b5254515befb6dec10706b4a1783a52fd0..566425d97b56999d2bfef579f2e150e8262a72bb 100644 --- a/src/views/UserPage/UserPageView.tsx +++ b/src/views/UserPage/UserPageView.tsx @@ -4,9 +4,16 @@ import { GlobalAppBarContext } from "@ess-ics/ce-ui-common"; import { applicationTitle } from "../../components/common/Helper"; import { UserProfile } from "../../components/common/User/UserProfile"; import { UserOperationList } from "../../components/common/User/UserOperationList"; +import { UserInfoResponse } from "../../store/deployApi"; +import { GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; -export function UserPageView({ userName, userInfo }) { - const { setTitle } = useContext(GlobalAppBarContext); +interface UserPageViewProps { + userName?: string; + userInfo: UserInfoResponse; +} + +export function UserPageView({ userName, userInfo }: UserPageViewProps) { + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle(userName)), [setTitle, userName]); return ( diff --git a/src/views/help/HelpView.tsx b/src/views/help/HelpView.tsx index 46b392ab01762a1c1b6f6ee803825b31ffbb8777..dab63530710fe2de76b61d666612a2e59eb8dea2 100644 --- a/src/views/help/HelpView.tsx +++ b/src/views/help/HelpView.tsx @@ -3,9 +3,10 @@ import { RootPaper, Help, GlobalAppBarContext } from "@ess-ics/ce-ui-common"; import { Stack, Typography } from "@mui/material"; import { applicationTitle } from "../../components/common/Helper"; import env from "../../config/env"; +import { GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; export function HelpView() { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("Help")), [setTitle]); return ( diff --git a/src/views/host/HostListView.tsx b/src/views/host/HostListView.tsx index 7262615e467dd7d2ae0a4219bbd4d6170d1216a7..62e7e8a2dbc5b47f37e422550b0cbbd8efdb6b61 100644 --- a/src/views/host/HostListView.tsx +++ b/src/views/host/HostListView.tsx @@ -14,9 +14,13 @@ import { } from "../../components/common/Helper"; import { ROWS_PER_PAGE } from "../../constants"; import { useLazyListHostsQuery } from "../../store/deployApi"; +import { + GlobalAppBarContext as GlobalAppBarContextType, + OnPageParams +} from "../../types/common"; export function HostListView() { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("IOC hosts")), [setTitle]); const [callListHostsQuery, { data: hosts, isFetching }] = @@ -24,9 +28,11 @@ export function HostListView() { const [searchParams, setSearchParams] = useSearchParams({ query: "" }); const [tabIndex, setTabIndex] = useState(0); - const [hostFilter, setHostFilter] = useState("ALL"); + const [hostFilter, setHostFilter] = useState< + "ALL" | "IOCS_DEPLOYED" | "NO_IOCS" | "OWN" + >("ALL"); - const handleTabChange = (tab) => { + const handleTabChange = (tab: number) => { if (tab === 0) { setHostFilter("ALL"); } else if (tab === 1) { @@ -51,21 +57,24 @@ export function HostListView() { // Request new search results whenever search or pagination changes useEffect(() => { const requestParams = initRequestParams(pagination); - requestParams.filter = hostFilter; - requestParams.text = searchParams.get("query"); - callListHostsQuery(requestParams); + callListHostsQuery({ + filter: hostFilter, + text: searchParams.get("query") || "", + limit: requestParams.limit.toString(), + page: requestParams.page + }); }, [callListHostsQuery, hostFilter, searchParams, pagination]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( - (query) => { + (query: string) => { setSearchParams({ query }, { replace: true }); }, [setSearchParams] ); // Invoked by Table on change to pagination - const onPage = (params) => { + const onPage = (params: OnPageParams) => { setPagination(params); }; diff --git a/src/views/host/details/HostDetailsContainer.tsx b/src/views/host/details/HostDetailsContainer.tsx index 0ee394937cd2db5e44ea6087bf65a97cc7355602..be22b0604b8da2304f6be4004b80d3a4738c58c7 100644 --- a/src/views/host/details/HostDetailsContainer.tsx +++ b/src/views/host/details/HostDetailsContainer.tsx @@ -1,41 +1,38 @@ -import { useState, useEffect } from "react"; import { LinearProgress } from "@mui/material"; import { RootPaper } from "@ess-ics/ce-ui-common"; import { HostDetailsView } from "./HostDetailsView"; -import { onFetchEntityError } from "../../../components/common/Helper"; import { NotFoundView } from "../../../components/navigation/NotFoundView/NotFoundView"; import { useFindHostAlertsQuery, useFindNetBoxHostByHostIdQuery } from "../../../store/deployApi"; +import { getErrorState } from "../../../components/common/Alerts/AlertsData"; -export function HostDetailsContainer({ hostId }) { - const [error, setError] = useState(null); - - const { data: host, error: fetchError } = useFindNetBoxHostByHostIdQuery({ - hostId - }); - const { data: alert, error: alertError } = useFindHostAlertsQuery({ hostId }); - - useEffect(() => { - if (fetchError || alertError) { - const message = - fetchError?.data?.description || alertError?.data?.description; - const status = fetchError?.status || alertError?.status; - onFetchEntityError(message, status, setError); - } - }, [fetchError, alertError]); +export function HostDetailsContainer({ hostId }: { hostId?: string }) { + const { data: host, error: fetchError } = useFindNetBoxHostByHostIdQuery( + { + hostId: hostId ?? "" + }, + { skip: !hostId } + ); + const { data: alert, error: alertError } = useFindHostAlertsQuery( + { + hostId: hostId ?? "" + }, + { skip: !hostId } + ); + const { status, message } = getErrorState(fetchError || alertError); - if (error) { + if (status === "404" || status === 404) { return ( <NotFoundView - message={error?.message} - status={error?.status} + message={message} + status={status} /> ); } - if (!host || !alert) { + if (!hostId || !host || !alert) { return ( <RootPaper> <LinearProgress color="primary" /> diff --git a/src/views/host/details/HostDetailsTable.tsx b/src/views/host/details/HostDetailsTable.tsx index 7300842d8a0931989ea5c8ccc8e1419e460caa6a..3316c75ca88267a7897e188f2de9bb1b18a030ca 100644 --- a/src/views/host/details/HostDetailsTable.tsx +++ b/src/views/host/details/HostDetailsTable.tsx @@ -1,7 +1,8 @@ import { KeyValueTable, EmptyValue } from "@ess-ics/ce-ui-common"; import { Chip, Stack } from "@mui/material"; +import { HostInfoWithId } from "../../../store/deployApi"; -const Tags = ({ tags }) => ( +const Tags = ({ tags }: { tags: string[] }) => ( <Stack direction="row" gap={1.5} @@ -17,14 +18,14 @@ const Tags = ({ tags }) => ( </Stack> ); -const getTableData = (host) => ({ +const getTableData = (host: HostInfoWithId) => ({ "device type": host.vm ? "Virtual machine" : host.deviceType, description: host.description ? host.description : <EmptyValue />, scope: host.scope, tags: host.tags ? <Tags tags={host.tags} /> : <EmptyValue /> }); -export const HostDetailsTable = ({ host }) => ( +export const HostDetailsTable = ({ host }: { host: HostInfoWithId }) => ( <KeyValueTable obj={getTableData(host)} variant="overline" diff --git a/src/views/host/details/HostDetailsView.tsx b/src/views/host/details/HostDetailsView.tsx index 619c4e642d99cd74e80b225ac96bf1917825dbe2..d01286c1a2410c212d06057e5bd49e74052a7c68 100644 --- a/src/views/host/details/HostDetailsView.tsx +++ b/src/views/host/details/HostDetailsView.tsx @@ -1,4 +1,4 @@ -import { useEffect, useContext, useState } from "react"; +import { useEffect, useContext, useState, ChangeEvent } from "react"; import { Box, IconButton, Typography, Stack } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { @@ -17,9 +17,17 @@ import { applicationTitle } from "../../../components/common/Helper"; import { AccessControl } from "../../../components/auth/AccessControl"; import { HostStatus } from "../../../components/host/HostStatus"; import env from "../../../config/env"; +import { HostAlertResponse, HostInfoWithId } from "../../../store/deployApi"; +import { GlobalAppBarContext as GlobalAppBarContextType } from "../../../types/common"; -export function HostDetailsView({ hostId, host, alert }) { - const { setTitle } = useContext(GlobalAppBarContext); +interface HostDetailsViewProps { + hostId: string; + host: HostInfoWithId; + alert: HostAlertResponse; +} + +export function HostDetailsView({ hostId, host, alert }: HostDetailsViewProps) { + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); const [accordionState, setAccordionState] = useState({ detailsOpen: false, logStreamOpen: false @@ -100,7 +108,7 @@ export function HostDetailsView({ hostId, host, alert }) { </Typography> } expanded={accordionState.detailsOpen} - onChange={(_, expanded) => { + onChange={(_: ChangeEvent, expanded: boolean) => { setAccordionState((prevState) => ({ ...prevState, detailsOpen: expanded @@ -120,7 +128,7 @@ export function HostDetailsView({ hostId, host, alert }) { </Typography> } expanded={accordionState.logStreamOpen} - onChange={(_, expanded) => { + onChange={(_: ChangeEvent, expanded: boolean) => { setAccordionState((prevState) => ({ ...prevState, logStreamOpen: expanded diff --git a/src/views/host/details/HostIocSection.tsx b/src/views/host/details/HostIocSection.tsx index cc9e8d40279a67c1dd07e1953990e66209e49559..9e0547b0a0167b50b91bd04df89719647ee5d9d1 100644 --- a/src/views/host/details/HostIocSection.tsx +++ b/src/views/host/details/HostIocSection.tsx @@ -6,12 +6,13 @@ import { IOCTable } from "../../../components/IOC/IOCTable"; import { initRequestParams } from "../../../components/common/Helper"; import { ROWS_PER_PAGE } from "../../../constants"; import { useLazyFindAssociatedIocsByHostIdQuery } from "../../../store/deployApi"; +import { OnPageParams } from "../../../types/common"; const propTypes = { hostId: string }; -export const HostIocSection = ({ hostId }) => { +export const HostIocSection = ({ hostId }: { hostId: string }) => { const { pagination, setPagination, setTotalCount } = usePagination({ initLimit: ROWS_PER_PAGE[0], initPage: 0 @@ -21,16 +22,19 @@ export const HostIocSection = ({ hostId }) => { useLazyFindAssociatedIocsByHostIdQuery(); const onPage = useCallback( - (params) => { + (params: OnPageParams) => { setPagination(params); }, [setPagination] ); const getIocs = useCallback(() => { - const requestParams = initRequestParams(pagination, null); - requestParams.hostId = hostId; - callGetIocs(requestParams); + const requestParams = initRequestParams({ pagination }); + callGetIocs({ + hostId, + limit: requestParams.limit.toString(), + page: requestParams.page + }); }, [callGetIocs, hostId, pagination]); // update pagination whenever search result total pages change diff --git a/src/views/host/details/HostJobsSection.tsx b/src/views/host/details/HostJobsSection.tsx index 4dd305693ada73830a5d221c4503370c5809e449..1225c60ed2c997ad94ef6584613cb9eee1002262 100644 --- a/src/views/host/details/HostJobsSection.tsx +++ b/src/views/host/details/HostJobsSection.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useCallback, useState } from "react"; +import { useEffect, useMemo, useCallback, useState, ChangeEvent } from "react"; import { string } from "prop-types"; import { SimpleAccordion, usePagination } from "@ess-ics/ce-ui-common"; import { Typography } from "@mui/material"; @@ -6,12 +6,13 @@ import { JobTable } from "../../../components/Job"; import { ROWS_PER_PAGE } from "../../../constants"; import { useLazyListJobsQuery } from "../../../store/deployApi"; import { ApiAlertError } from "../../../components/common/Alerts/ApiAlertError"; +import { OnPageParams } from "../../../types/common"; const propTypes = { hostId: string.isRequired }; -export const HostJobsSection = ({ hostId }) => { +export const HostJobsSection = ({ hostId }: { hostId: string }) => { const { pagination, setPagination } = usePagination({ rowsPerPageOptions: ROWS_PER_PAGE, initLimit: ROWS_PER_PAGE[0], @@ -34,7 +35,7 @@ export const HostJobsSection = ({ hostId }) => { }, [expanded, pagination, getHostLog, params]); const onPage = useCallback( - (params) => { + (params: OnPageParams) => { setPagination(params); }, [setPagination] @@ -55,12 +56,12 @@ export const HostJobsSection = ({ hostId }) => { Job log </Typography> } - onChange={(_, expanded) => setExpanded(expanded)} + onChange={(_: ChangeEvent, expanded: boolean) => setExpanded(expanded)} > {error && <ApiAlertError error={error} />} {hostLog ? ( <JobTable - jobs={!error && hostLog ? hostLog?.jobs : null} + jobs={!error && hostLog ? hostLog?.jobs : undefined} customColumns={[ { field: "status" }, { field: "job" }, diff --git a/src/views/jobs/JobDetailsContainer.tsx b/src/views/jobs/JobDetailsContainer.tsx index b137f869ec7144feec8d4edcc9bdfb00bbb8b5c2..8bf045e3b529005d2c7d3c2eeb7945b7057ac8b9 100644 --- a/src/views/jobs/JobDetailsContainer.tsx +++ b/src/views/jobs/JobDetailsContainer.tsx @@ -3,12 +3,11 @@ import { LinearProgress } from "@mui/material"; import { RootPaper } from "@ess-ics/ce-ui-common"; import { JobDetailsView } from "./JobDetailsView"; import { NotFoundView } from "../../components/navigation/NotFoundView/NotFoundView"; -import { onFetchEntityError } from "../../components/common/Helper"; import { useFetchJobQuery } from "../../store/deployApi"; +import { getErrorState } from "../../components/common/Alerts/AlertsData"; const POLL_DEPLOYMENT_INTERVAL = 5000; -export function JobDetailsContainer({ id }) { - const [notFoundError, setNotFoundError] = useState(null); +export function JobDetailsContainer({ id }: { id?: string }) { const [jobFinished, setJobFinished] = useState(false); const { @@ -16,9 +15,10 @@ export function JobDetailsContainer({ id }) { isLoading, error: jobError } = useFetchJobQuery( - { jobId: id }, + { jobId: Number(id) ?? 0 }, { - pollingInterval: !jobFinished && POLL_DEPLOYMENT_INTERVAL + skip: !id, + pollingInterval: !jobFinished ? POLL_DEPLOYMENT_INTERVAL : undefined } ); @@ -28,21 +28,13 @@ export function JobDetailsContainer({ id }) { } }, [job?.finishedAt]); - useEffect(() => { - if (jobError) { - onFetchEntityError( - jobError?.data?.description, - jobError?.status, - setNotFoundError - ); - } - }, [jobError]); + const { status, message } = getErrorState(jobError); - if (notFoundError) { + if (status === "404" || status === 404) { return ( <NotFoundView - message={notFoundError?.message} - status={notFoundError?.status} + message={message} + status={status} /> ); } diff --git a/src/views/jobs/JobDetailsView.tsx b/src/views/jobs/JobDetailsView.tsx index e3bb156286e28f5c80aa56e66c08c179834449bc..bc23194b5b2679b91e40977641f224c92508c6d1 100644 --- a/src/views/jobs/JobDetailsView.tsx +++ b/src/views/jobs/JobDetailsView.tsx @@ -5,15 +5,17 @@ import { useNavigate } from "react-router-dom"; import { GlobalAppBarContext } from "@ess-ics/ce-ui-common"; import { JobsDetails } from "../../components/Job/JobDetails"; import { applicationTitle } from "../../components/common/Helper"; +import { GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; +import { JobDetails } from "../../store/deployApi"; -export function JobDetailsView({ job }) { +export function JobDetailsView({ job }: { job: JobDetails }) { const navigate = useNavigate(); const handleClick = () => { navigate(-1); }; - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect( () => job && setTitle(applicationTitle(`Job Details: ${job.iocName}`)), [setTitle, job] diff --git a/src/views/jobs/JobListView.tsx b/src/views/jobs/JobListView.tsx index bf569dc9ab5885d0accb5f403401901e7af778a9..2f92321c32b6a01747a103ca1d821be5c11cfc3d 100644 --- a/src/views/jobs/JobListView.tsx +++ b/src/views/jobs/JobListView.tsx @@ -5,6 +5,7 @@ import { initRequestParams } from "../../components/common/Helper"; import { JobTable } from "../../components/Job/JobTable"; import { ROWS_PER_PAGE } from "../../constants"; import { useLazyListJobsQuery } from "../../store/deployApi"; +import { OnPageParams } from "../../types/common"; export function JobListView() { const [getJobs, { data: jobs, isLoading }] = useLazyListJobsQuery(); @@ -31,7 +32,7 @@ export function JobListView() { }, [callGetOperations, pagination]); // Invoked by Table on change to pagination - const onPage = (params) => { + const onPage = (params: OnPageParams) => { setPagination(params); }; diff --git a/src/views/jobs/JobLogAccessControl.tsx b/src/views/jobs/JobLogAccessControl.tsx index a65cbeecf97373070626672c6bc7367ffd0bccf7..14cc01eab8486d20f978d1016fb98ac7b0843938 100644 --- a/src/views/jobs/JobLogAccessControl.tsx +++ b/src/views/jobs/JobLogAccessControl.tsx @@ -3,9 +3,10 @@ import { GlobalAppBarContext } from "@ess-ics/ce-ui-common"; import { JobListView } from "./JobListView"; import { AccessControl } from "../../components/auth/AccessControl"; import { applicationTitle } from "../../components/common/Helper"; +import { type GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; export function JobLogAccessControl() { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("Log")), [setTitle]); return ( diff --git a/src/views/login/LoginView.tsx b/src/views/login/LoginView.tsx index bd49cf28701b3fc2b84f1f97c4a08af2361019f1..4a2a8fa5027d22d624c03cecf430c0342bcee380 100644 --- a/src/views/login/LoginView.tsx +++ b/src/views/login/LoginView.tsx @@ -8,15 +8,20 @@ import { } from "@ess-ics/ce-ui-common"; import { useRedirect } from "../../hooks/Redirect"; import { applicationTitle } from "../../components/common/Helper"; +import { + GlobalAppBarContext as GlobalAppBarContextType, + UserContext +} from "../../types/common"; export function LoginView() { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("Login")), [setTitle]); const redirect = useRedirect(); - const { user, login, loginError, resetLoginError } = useContext(userContext); + const { user, login, loginError, resetLoginError } = + useContext<UserContext>(userContext); const location = useLocation(); useEffect(() => { diff --git a/src/views/records/Alias.tsx b/src/views/records/Alias.tsx index fa57dfd7cfa04a04592606b7cb50a9c6c6ae6a20..37fb5709b222d12444f04a7ed695aadaaf0f6320 100644 --- a/src/views/records/Alias.tsx +++ b/src/views/records/Alias.tsx @@ -1,7 +1,7 @@ import { EmptyValue, InternalLink, useUniqueKeys } from "@ess-ics/ce-ui-common"; import { Stack } from "@mui/material"; -export const Alias = ({ aliases }) => { +export const Alias = ({ aliases }: { aliases?: string[] }) => { const itemsKeys = useUniqueKeys(aliases); if (!aliases || aliases.length === 0) { diff --git a/src/views/records/RecordDetailsView.tsx b/src/views/records/RecordDetailsView.tsx index 98249458f530ff0c2091f80887323ceb69247c5b..bb6465780471cddd6a0195a2944c74bfe3932b2b 100644 --- a/src/views/records/RecordDetailsView.tsx +++ b/src/views/records/RecordDetailsView.tsx @@ -18,12 +18,14 @@ import { } from "../../components/common/Helper"; import { NotFoundView } from "../../components/navigation/NotFoundView/NotFoundView"; -import { useGetRecordQuery } from "../../store/deployApi"; +import { RecordDetails, useGetRecordQuery } from "../../store/deployApi"; +import { type GlobalAppBarContext as GlobalAppBarContextType } from "../../types/common"; +import { getErrorState } from "../../components/common/Alerts/AlertsData"; export function RecordDetailsView() { const { name } = useParams(); - const decodedName = decodeURIComponent(name); - const [error, setError] = useState(null); + const decodedName = decodeURIComponent(name ?? ""); + const [error, setError] = useState<string | null>(null); const { data: record, @@ -35,17 +37,14 @@ export function RecordDetailsView() { useEffect(() => { if (fetchError) { - onFetchEntityError( - fetchError?.data?.description, - fetchError?.status, - setError - ); + const { message, status } = getErrorState(fetchError); + onFetchEntityError({ message, status, setNotFoundError: setError }); } }, [fetchError]); const navigate = useNavigate(); - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => { if (record) { @@ -57,7 +56,7 @@ export function RecordDetailsView() { navigate(-1); }; - const getSubset = useCallback((record) => { + const getSubset = useCallback((record: RecordDetails) => { const subset = { "Alias for": ( <Alias aliases={record?.aliasFor ? [record?.aliasFor] : []} /> @@ -77,27 +76,25 @@ export function RecordDetailsView() { ) : ( record?.hostName ), - "Alias to": <Alias aliases={record?.aliasTo} /> + "Alias to": <Alias aliases={record?.aliasTo} />, + "Last updated": "", + "IOC Revision": "" }; - for (const [key, value] of Object.entries(record.properties)) { - if (key.toLowerCase().includes("time")) { - subset["Last updated"] = formatDateAndTime(value); - } else if (key.toLowerCase().includes("recordtype")) { - subset["Record type"] = value; - } else if (key.toLowerCase().includes("recorddesc")) { - subset.Description = value; - } else if (key.toLowerCase() === "iocversion") { - subset["IOC Revision"] = value; - } else if ( - key.toLowerCase() !== "iocid" && - key.toLowerCase() !== "alias" - ) { - subset[key.replaceAll("_", " ")] = value; + if (record?.properties) { + for (const [key, value] of Object.entries(record.properties)) { + if (key.toLowerCase().includes("time")) { + subset["Last updated"] = formatDateAndTime(value); + } else if (key.toLowerCase().includes("recordtype")) { + subset["Record type"] = value; + } else if (key.toLowerCase().includes("recorddesc")) { + subset.Description = value; + } else if (key.toLowerCase() === "iocversion") { + subset["IOC Revision"] = value; + } } + return subset; } - - return subset; }, []); if (decodedName.includes(";") || error) { diff --git a/src/views/records/RecordListView.tsx b/src/views/records/RecordListView.tsx index 7878b9b4d9c1a7d71890d323ae09fcfb7fa80fa7..9b2ad6bf9e20a55c35c4d691cc718294b2453b1b 100644 --- a/src/views/records/RecordListView.tsx +++ b/src/views/records/RecordListView.tsx @@ -14,9 +14,13 @@ import { import { RecordTable } from "../../components/records/RecordTable"; import { ROWS_PER_PAGE } from "../../constants"; import { useLazyFindAllRecordsQuery } from "../../store/deployApi"; +import { + GlobalAppBarContext as GlobalAppBarContextType, + OnPageParams +} from "../../types/common"; export function RecordListView() { - const { setTitle } = useContext(GlobalAppBarContext); + const { setTitle } = useContext<GlobalAppBarContextType>(GlobalAppBarContext); useEffect(() => setTitle(applicationTitle("Records")), [setTitle]); const [getRecords, { data: records, isFetching }] = @@ -24,12 +28,14 @@ export function RecordListView() { const [searchParams, setSearchParams] = useSearchParams({ query: "" }); const [tabIndex, setTabIndex] = useState(0); - const [recordFilter, setRecordFilter] = useState(""); + const [recordFilter, setRecordFilter] = useState< + "ACTIVE" | "INACTIVE" | undefined + >(undefined); // used to request record list again when tab is switched, but request it only once! (totalRecord is a random number that is generated by ChannelFinder) - const handleTabChange = (tab) => { + const handleTabChange = (tab: number) => { if (tab === 0) { - setRecordFilter(""); + setRecordFilter(undefined); } else if (tab === 1) { setRecordFilter("ACTIVE"); } else if (tab === 2) { @@ -52,21 +58,24 @@ export function RecordListView() { // Request new search results whenever search or pagination changes useEffect(() => { const requestParams = initRequestParams(pagination); - requestParams.pvStatus = recordFilter; - requestParams.text = searchParams.get("query"); - getRecords(requestParams); + getRecords({ + pvStatus: recordFilter, + text: searchParams.get("query") || "", + limit: requestParams.limit.toString(), + page: requestParams.page + }); }, [getRecords, recordFilter, pagination, searchParams]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( - (query) => { + (query: string) => { setSearchParams({ query }, { replace: true }); }, [setSearchParams] ); // Invoked by Table on change to pagination - const onPage = (params) => { + const onPage = (params: OnPageParams) => { setPagination(params); };