diff --git a/package-lock.json b/package-lock.json index d1f8551b98c04d3c936205f06b10cdce800edd09..959f3babc75bb54466f1eb6517621385bf4520c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ahooksjs/use-url-state": "^3.5.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@ess-ics/ce-ui-common": "^0.4.1", + "@ess-ics/ce-ui-common": "^0.4.2", "@fontsource/roboto": "^4.1.0", "@mui/icons-material": "^5.14.1", "@mui/material": "^5.14.1", @@ -2655,9 +2655,9 @@ } }, "node_modules/@ess-ics/ce-ui-common": { - "version": "0.4.1", - "resolved": "https://artifactory.esss.lu.se/artifactory/api/npm/ics-npm/@ess-ics/ce-ui-common/-/ce-ui-common-0.4.1.tgz", - "integrity": "sha1-xsfA4ukUWTChYXrb0J681o7sKmc=", + "version": "0.4.2", + "resolved": "https://artifactory.esss.lu.se/artifactory/api/npm/ics-npm/@ess-ics/ce-ui-common/-/ce-ui-common-0.4.2.tgz", + "integrity": "sha1-bHkj1S9gtfMc3yF9gn1tSzwPJ6E=", "dependencies": { "@fontsource/titillium-web": "^4.5.9", "@mui/x-data-grid-pro": "^6.5.0", @@ -41722,9 +41722,9 @@ "dev": true }, "@ess-ics/ce-ui-common": { - "version": "0.4.1", - "resolved": "https://artifactory.esss.lu.se/artifactory/api/npm/ics-npm/@ess-ics/ce-ui-common/-/ce-ui-common-0.4.1.tgz", - "integrity": "sha1-xsfA4ukUWTChYXrb0J681o7sKmc=", + "version": "0.4.2", + "resolved": "https://artifactory.esss.lu.se/artifactory/api/npm/ics-npm/@ess-ics/ce-ui-common/-/ce-ui-common-0.4.2.tgz", + "integrity": "sha1-bHkj1S9gtfMc3yF9gn1tSzwPJ6E=", "requires": { "@fontsource/titillium-web": "^4.5.9", "@mui/x-data-grid-pro": "^6.5.0", diff --git a/package.json b/package.json index 7a41cc6e3c24f03ef48b7d4bd10d4ca3cfb20b2e..3eedaea6e324fcebac6d891b7c0f5bec54d30d81 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@ahooksjs/use-url-state": "^3.5.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@ess-ics/ce-ui-common": "^0.4.1", + "@ess-ics/ce-ui-common": "^0.4.2", "@fontsource/roboto": "^4.1.0", "@mui/icons-material": "^5.14.1", "@mui/material": "^5.14.1", diff --git a/src/components/IOC/AdministerUndeployment/AdministerUndeployment.js b/src/components/IOC/AdministerUndeployment/AdministerUndeployment.js index c6f175f699f9769e4389f8f00de35656c47e5aa2..4a034dbd8c1a1ef8bd9951b8b246f180efea3657 100644 --- a/src/components/IOC/AdministerUndeployment/AdministerUndeployment.js +++ b/src/components/IOC/AdministerUndeployment/AdministerUndeployment.js @@ -13,12 +13,15 @@ import { Tooltip, LinearProgress } from "@mui/material"; -import { SimpleAccordion, ConfirmationDialog } from "@ess-ics/ce-ui-common"; +import { + SimpleAccordion, + ConfirmationDialog, + useAPIMethod +} from "@ess-ics/ce-ui-common"; import Alert from "@mui/material/Alert"; import AccessControl from "../../auth/AccessControl"; import { IocActiveDeployment } from "../../../api/DataTypes"; import { apiContext } from "../../../api/DeployApi"; -import { useAPIMethod } from "@ess-ics/ce-ui-common/dist/hooks/API"; export default function AdministerUndeployment({ ioc, buttonDisabled }) { const navigate = useNavigate(); diff --git a/src/components/IOC/IOCTable/IOCStatus.js b/src/components/IOC/IOCTable/IOCStatus.js index d67a352b3f2d82cc58f110b6f2bd38d5a20596e8..14e51ff3899f405cdf40bc418c4ac92e04686112 100644 --- a/src/components/IOC/IOCTable/IOCStatus.js +++ b/src/components/IOC/IOCTable/IOCStatus.js @@ -21,8 +21,7 @@ export const IOCStatus = ({ id, activeDeployment }) => { dataReady } = useAPIMethod({ fcn: client.apis.Monitoring.fetchIocStatus, - params, - call: true + params }); return ( diff --git a/src/components/common/User/UserIOCList.js b/src/components/common/User/UserIOCList.js index aac7a9ec3001a8a6613b2aebfa339d86afec3e6d..4f5aa493313f76bde79e6aac63d65fbf6b24cad5 100644 --- a/src/components/common/User/UserIOCList.js +++ b/src/components/common/User/UserIOCList.js @@ -14,7 +14,8 @@ export function UserIocList({ userName }) { value: iocs, wrapper: getIocs, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.IOCs.listIocs, call: false @@ -39,11 +40,16 @@ export function UserIocList({ userName }) { requestParams.created_by = userName; getIocs(requestParams); - }, [getIocs, pagination, userName]); + + return () => { + abort(); + }; + }, [getIocs, pagination, userName, abort]); // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; return ( diff --git a/src/components/common/User/UserOperationList.js b/src/components/common/User/UserOperationList.js index 75372ca270f7e4c7c6fdf41cd38c6ccc5edb1a18..016621e9c1eb1350e8b15e87a4001a9fe3b89bb8 100644 --- a/src/components/common/User/UserOperationList.js +++ b/src/components/common/User/UserOperationList.js @@ -14,7 +14,8 @@ export function UserOperationList({ userName }) { value: operations, wrapper: getOperations, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.Deployments.listOperations, call: false @@ -38,11 +39,16 @@ export function UserOperationList({ userName }) { requestParams.user = userName; getOperations(requestParams); - }, [getOperations, pagination, userName]); + + return () => { + abort(); + }; + }, [getOperations, pagination, userName, abort]); // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; return ( diff --git a/src/components/common/notification/Watchers.js b/src/components/common/notification/Watchers.js index 209783f3fdb19f382445876a93f3a970655d2534..fd0a8867e0f45d9637199ea1a7ca7930787f1af5 100644 --- a/src/components/common/notification/Watchers.js +++ b/src/components/common/notification/Watchers.js @@ -29,7 +29,8 @@ export function DeploymentWatcher({ value: deployment, wrapper: getDeployment, loading: deploymentLoading, - dataReady: deploymentDataReady + dataReady: deploymentDataReady, + abort: abortGetDeployment } = useAPIMethod({ fcn: client.apis.Deployments.fetchOperation, call: false, @@ -45,7 +46,8 @@ export function DeploymentWatcher({ value: deploymentJob, wrapper: getDeploymentJob, loading: jobLoading, - dataReady: jobDataReady + dataReady: jobDataReady, + abort: abortGetDeploymentJob } = useAPIMethod({ fcn: client.apis.Deployments.fetchJobDetails, params: deploymentJobParams @@ -54,13 +56,17 @@ export function DeploymentWatcher({ useSafePolling( getDeployment, deploymentLoading || !deploymentDataReady, - STATUS_POLL_INTERVAL + STATUS_POLL_INTERVAL, + true, + abortGetDeployment ); useSafePolling( getDeploymentJob, jobLoading || !jobDataReady, - STATUS_POLL_INTERVAL + STATUS_POLL_INTERVAL, + true, + abortGetDeploymentJob ); const deploymentStatus = useMemo( diff --git a/src/components/deployments/DeploymentJobOutput.js b/src/components/deployments/DeploymentJobOutput.js index 6356477ede2ac9de95bbeb4a3c547d70a2ce7784..c34141e37fd699390b73d631eb61cdc85d0727ef 100644 --- a/src/components/deployments/DeploymentJobOutput.js +++ b/src/components/deployments/DeploymentJobOutput.js @@ -26,7 +26,8 @@ export function DeploymentJobOutput({ deploymentJob }) { value: log, wrapper: getLogById, loading: logLoading, - dataReady: logDataReady + dataReady: logDataReady, + abort: abortGetLogById } = useAPIMethod({ fcn: client.apis.Deployments.fetchDeploymentJobLog, params @@ -44,7 +45,13 @@ export function DeploymentJobOutput({ deploymentJob }) { finalResultsNeeded.current = !deploymentJob.finished; } }, [deploymentJob.finished, deploymentJob.id, getLogById]); - useSafePolling(getLog, logLoading || !logDataReady, LOG_POLL_INTERVAL); + useSafePolling( + getLog, + logLoading || !logDataReady, + LOG_POLL_INTERVAL, + true, + abortGetLogById + ); const dataReady = useCallback(() => { return deploymentJob?.started; diff --git a/src/components/records/RecordSearch.js b/src/components/records/RecordSearch.js index 2aeba701e6ca6df502d7c49b95dfe4abc79d14cf..39fc9f7bb8682d688f3964e0194c7ab0606b3222 100644 --- a/src/components/records/RecordSearch.js +++ b/src/components/records/RecordSearch.js @@ -22,7 +22,8 @@ export function RecordSearch({ iocName, rowType }) { value: records, wrapper: getRecords, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.Records.findAllRecords, call: false @@ -110,7 +111,11 @@ export function RecordSearch({ iocName, rowType }) { requestParams.pv_status = recordFilter; requestParams.record_name = deserialize(urlState.query); getRecords(requestParams); - }, [getRecords, recordFilter, urlState.query, pagination]); + + return () => { + abort(); + }; + }, [getRecords, recordFilter, urlState.query, pagination, abort]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( @@ -123,6 +128,7 @@ export function RecordSearch({ iocName, rowType }) { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; return ( diff --git a/src/components/statistics/DeploymentLineChart/DeploymentLineChart.js b/src/components/statistics/DeploymentLineChart/DeploymentLineChart.js index 809384c9dd46225433dc6318a372ee21782d7226..b22de827dec8ddea7cbb0e00cd355be9031071ed 100644 --- a/src/components/statistics/DeploymentLineChart/DeploymentLineChart.js +++ b/src/components/statistics/DeploymentLineChart/DeploymentLineChart.js @@ -17,13 +17,18 @@ export default function DeploymentLineChart({ title, chartLabel, iocDeployments, - getIOCDeployments + getIOCDeployments, + abortGetIOCDeployments }) { const theme = useTheme(); useEffect(() => { getIOCDeployments(); - }, [getIOCDeployments]); + + return () => { + abortGetIOCDeployments(); + }; + }, [getIOCDeployments, abortGetIOCDeployments]); const GRAPH_THRESHOLD = 0.05; diff --git a/src/components/statistics/HostStatistics/HostStatistics.js b/src/components/statistics/HostStatistics/HostStatistics.js index 5ffe42dde7ab5bd822700031f8fa413419cc04f6..6b9302fea8e89e427864d778bc855cefc1c8e976 100644 --- a/src/components/statistics/HostStatistics/HostStatistics.js +++ b/src/components/statistics/HostStatistics/HostStatistics.js @@ -12,15 +12,27 @@ export function HostStatistics() { // Do not call on render; when one of these finishes then it and the others // will be called again on the next render; this causes an infinite loop. - const { value: hostsRegistered, wrapper: getHostsRegistered } = useAPIMethod({ + const { + value: hostsRegistered, + wrapper: getHostsRegistered, + abort: abortGetHostsRegistered + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); - const { value: hostsWithIocs, wrapper: getHostsWithIocs } = useAPIMethod({ + const { + value: hostsWithIocs, + wrapper: getHostsWithIocs, + abort: abortGetHostsWithIocs + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); - const { value: hostsReachable, wrapper: getHostsReachable } = useAPIMethod({ + const { + value: hostsReachable, + wrapper: getHostsReachable, + abort: abortGetHostsReachable + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); @@ -29,7 +41,20 @@ export function HostStatistics() { getHostsRegistered({ statistics_type: "HOSTS_REGISTERED" }); getHostsWithIocs({ statistics_type: "HOSTS_WITH_IOCS" }); getHostsReachable({ statistics_type: "HOSTS_REACHABLE" }); - }, [getHostsRegistered, getHostsWithIocs, getHostsReachable]); + + return () => { + abortGetHostsRegistered(); + abortGetHostsWithIocs(); + abortGetHostsReachable(); + }; + }, [ + getHostsRegistered, + getHostsWithIocs, + getHostsReachable, + abortGetHostsRegistered, + abortGetHostsWithIocs, + abortGetHostsReachable + ]); const hostStats = { "Registered IOC-hosts": renderValue(hostsRegistered?.value), diff --git a/src/components/statistics/IOCStatistics/IOCStatistics.js b/src/components/statistics/IOCStatistics/IOCStatistics.js index ced1af4c0b79ef3249a55ff5e04a13712d24d5e8..2da068247d44ec643bd3543423533a2da9c14a21 100644 --- a/src/components/statistics/IOCStatistics/IOCStatistics.js +++ b/src/components/statistics/IOCStatistics/IOCStatistics.js @@ -13,15 +13,27 @@ export function IOCStatistics() { // Do not call on render; when one of these finishes then it and the others // will be called again on the next render; this causes an infinite loop. - const { value: iocsRegistered, wrapper: getIocsRegistered } = useAPIMethod({ + const { + value: iocsRegistered, + wrapper: getIocsRegistered, + abort: abortGetIocsRegistered + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); - const { value: iocsDeployed, wrapper: getIocsDeployed } = useAPIMethod({ + const { + value: iocsDeployed, + wrapper: getIocsDeployed, + abort: abortGetIocsDeployed + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); - const { value: iocsReachable, wrapper: getIocsReachable } = useAPIMethod({ + const { + value: iocsReachable, + wrapper: getIocsReachable, + abort: abortGetIocsReachable + } = useAPIMethod({ fcn: client.apis.Statistics.calculateStatistics, call: false }); @@ -30,7 +42,20 @@ export function IOCStatistics() { getIocsRegistered({ statistics_type: "IOCS_REGISTERED" }); getIocsDeployed({ statistics_type: "IOCS_DEPLOYED" }); getIocsReachable({ statistics_type: "IOCS_RUNNING" }); - }, [getIocsDeployed, getIocsReachable, getIocsRegistered]); + + return () => { + abortGetIocsRegistered(); + abortGetIocsDeployed(); + abortGetIocsReachable(); + }; + }, [ + abortGetIocsDeployed, + abortGetIocsReachable, + abortGetIocsRegistered, + getIocsDeployed, + getIocsReachable, + getIocsRegistered + ]); const iocStats = { "Registered IOCs": renderValue(iocsRegistered?.value), diff --git a/src/components/statistics/OperationChart/OperationChart.js b/src/components/statistics/OperationChart/OperationChart.js index d6198aa4946857d2e82bd31e7dddaa08a22a9d81..8a4236f6c4fd2a38136f335e228295edae14bd4e 100644 --- a/src/components/statistics/OperationChart/OperationChart.js +++ b/src/components/statistics/OperationChart/OperationChart.js @@ -17,13 +17,18 @@ import { export default function OperationChart({ title, iocDeployments, - getIOCDeployments + getIOCDeployments, + abortGetIOCDeployments }) { const theme = useTheme(); useEffect(() => { getIOCDeployments(); - }, [getIOCDeployments]); + + return () => { + abortGetIOCDeployments(); + }; + }, [getIOCDeployments, abortGetIOCDeployments]); return iocDeployments ? ( <> diff --git a/src/hooks/Polling.js b/src/hooks/Polling.js index c8a9de5f330ce9546c7bdeae6264779c0ac1ec9f..bb238475a5bdadf0d5383612670b4830ff43679d 100644 --- a/src/hooks/Polling.js +++ b/src/hooks/Polling.js @@ -1,14 +1,24 @@ import { useCallback, useEffect, useRef } from "react"; -export function useInterval(callback, interval, call = false) { +const defaultCleanup = () => {}; + +export function useInterval( + callback, + interval, + call = false, + cleanup = defaultCleanup +) { useEffect(() => { if (call) callback(); // call the callback right away const id = setInterval(callback, interval); - return () => clearInterval(id); - }, [call, callback, interval]); + return () => { + clearInterval(id); + cleanup(); + }; + }, [call, callback, interval, cleanup]); } -export function useSafePolling(callback, busy, interval, call = true) { +export function useSafePolling(callback, busy, interval, call = true, cleanup) { const busyRef = useRef(busy); busyRef.current = busy; @@ -17,5 +27,5 @@ export function useSafePolling(callback, busy, interval, call = true) { callback(); } }, [callback, busyRef]); - useInterval(poll, interval, call); + useInterval(poll, interval, call, cleanup); } diff --git a/src/stories/views/IOC/IocListView.stories.js b/src/stories/views/IOC/IocListView.stories.js new file mode 100644 index 0000000000000000000000000000000000000000..ab11295422819d2fffb59c4481c3167d9d0a4028 --- /dev/null +++ b/src/stories/views/IOC/IocListView.stories.js @@ -0,0 +1,27 @@ +import React from "react"; +import { AppHarness } from "../../../mocks/AppHarness"; +import { rest } from "msw"; +import { handlers } from "../../../mocks/handlers"; +import { IOCListView } from "../../../views/IOC/IOCListView"; + +export default { + title: "Views/IOC/IocListView" +}; + +const Template = () => ( + <AppHarness> + <IOCListView /> + </AppHarness> +); + +export const Default = () => <Template />; + +export const LoadingAsyncCells = () => <Template />; +LoadingAsyncCells.parameters = { + msw: { + handlers: [ + rest.get("*/iocs/*", (req, res, ctx) => res(ctx.delay("infinite"))), + ...handlers + ] + } +}; diff --git a/src/views/IOC/IOCDetailsContainer.js b/src/views/IOC/IOCDetailsContainer.js index 00aee00486e25dbb5dae9313347195f5f974126c..239c6fccd06b135526e3e88080b56215139e47a9 100644 --- a/src/views/IOC/IOCDetailsContainer.js +++ b/src/views/IOC/IOCDetailsContainer.js @@ -26,7 +26,8 @@ export function IOCDetailsContainer({ id }) { value: ioc, wrapper: getIOC, loading, - error: fetchError + error: fetchError, + abort: abortGetIOC } = useAPIMethod({ fcn: client.apis.IOCs.getIoc, params @@ -59,6 +60,7 @@ export function IOCDetailsContainer({ id }) { <IOCDetailsView ioc={ioc} getIOC={getIOC} + abortGetIOC={abortGetIOC} loading={loading} /> ) : ( diff --git a/src/views/IOC/IOCDetailsView.js b/src/views/IOC/IOCDetailsView.js index 6fe8961a5d729834a0e56cb15d183667782a3bfd..f8be1d64fae8764f7018fce954460bb40d59a706 100644 --- a/src/views/IOC/IOCDetailsView.js +++ b/src/views/IOC/IOCDetailsView.js @@ -27,7 +27,14 @@ import { usePagination } from "../../hooks/pagination"; import { apiContext } from "../../api/DeployApi"; const IOC_POLL_INTERVAL = 10000; -export function IOCDetailsView({ ioc, getIOC, loading }) { +export function IOCDetailsView({ ioc, getIOC, abortGetIOC, loading }) { + const { setTitle } = useContext(GlobalAppBarContext); + useEffect(() => { + if (ioc) { + setTitle(applicationTitle(`IOC Details: ${ioc.namingName}`)); + } + }, [ioc, setTitle]); + const [urlState, setUrlState] = useUrlState( { tab: "Status", @@ -45,7 +52,8 @@ export function IOCDetailsView({ ioc, getIOC, loading }) { value: operations, wrapper: getOperations, loading: operationsLoading, - dataReady: operationsDataReady + dataReady: operationsDataReady, + abort: abortGetOperations } = useAPIMethod({ fcn: client.apis.Deployments.listOperations, call: false @@ -64,7 +72,8 @@ export function IOCDetailsView({ ioc, getIOC, loading }) { value: ongoingCommand, wrapper: getOngoingCommand, loading: ongoingCommandLoading, - dataReady: ongoingCommandDataReady + dataReady: ongoingCommandDataReady, + abort: abortGetOngoingCommand } = useAPIMethod({ fcn: client.apis.Deployments.listOperations, params: ongoingCommandParams, @@ -116,13 +125,16 @@ export function IOCDetailsView({ ioc, getIOC, loading }) { // Invoked by Table on change to pagination const onPage = (params) => { setJobPagination(params); + abortGetOperations(); }; - useSafePolling(getIOC, loading, IOC_POLL_INTERVAL); + useSafePolling(getIOC, loading, IOC_POLL_INTERVAL, true, abortGetIOC); useSafePolling( getOngoingCommand, ongoingCommandLoading || !ongoingCommandDataReady, - IOC_POLL_INTERVAL + IOC_POLL_INTERVAL, + true, + abortGetOngoingCommand ); useEffect(() => { @@ -138,7 +150,11 @@ export function IOCDetailsView({ ioc, getIOC, loading }) { let requestParams = initRequestParams(jobPagination); requestParams.ioc_id = ioc.id; getOperations(requestParams); - }, [getOperations, jobPagination, ioc]); + + return () => { + abortGetOperations(); + }; + }, [getOperations, jobPagination, ioc, abortGetOperations]); const handleClick = () => { navigate(-1); @@ -160,13 +176,6 @@ export function IOCDetailsView({ ioc, getIOC, loading }) { [getIOC] ); - const { setTitle } = useContext(GlobalAppBarContext); - useEffect(() => { - if (ioc) { - setTitle(applicationTitle(`IOC Details: ${ioc.namingName}`)); - } - }, [ioc, setTitle]); - const statusTab = ( <Tab key="Status" diff --git a/src/views/IOC/IOCListView.js b/src/views/IOC/IOCListView.js index 98d2913eb7ee4ea58f17cc43bc13a5986b8adc78..eb64c08e2dbac6217bb31653af3a696e9775c705 100644 --- a/src/views/IOC/IOCListView.js +++ b/src/views/IOC/IOCListView.js @@ -30,7 +30,8 @@ export function IOCListView() { value: iocs, wrapper: getIocs, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.IOCs.listIocs, call: false @@ -118,6 +119,7 @@ export function IOCListView() { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; useEffect(() => { @@ -129,7 +131,18 @@ export function IOCListView() { requestParams.deployment_status = deploymentStatus; getIocs(requestParams); - }, [getIocs, urlPagination, deploymentStatus, urlState.query, pagination]); + + return () => { + abort(); + }; + }, [ + getIocs, + urlPagination, + deploymentStatus, + urlState.query, + pagination, + abort + ]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( diff --git a/src/views/host/HostDetailsView.js b/src/views/host/HostDetailsView.js index d82ac4688584e36cd87ca67a88d55d9eac056537..350f6d6033e735588473dac1cc163077f27ac520 100644 --- a/src/views/host/HostDetailsView.js +++ b/src/views/host/HostDetailsView.js @@ -48,7 +48,8 @@ export function HostDetailsView({ id, host }) { value: iocs, wrapper: getIocs, loading, - dataReady + dataReady, + abort: abortGetIocs } = useAPIMethod({ fcn: client.apis.Hosts.findAssociatedIocsByHostId, call: false @@ -111,6 +112,7 @@ export function HostDetailsView({ id, host }) { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abortGetIocs(); }; useEffect(() => { @@ -119,7 +121,11 @@ export function HostDetailsView({ id, host }) { requestParams.host_csentry_id = id; getIocs(requestParams); - }, [getIocs, urlPagination, id]); + + return () => { + abortGetIocs(); + }; + }, [getIocs, urlPagination, id, abortGetIocs]); function listToString(list) { if (list) { diff --git a/src/views/host/HostListView.js b/src/views/host/HostListView.js index f4a773d8ebf6de9265ebe53da3d36dd6842ef4e7..06a365e304cff16553bddf7f41e2043f7674b0e3 100644 --- a/src/views/host/HostListView.js +++ b/src/views/host/HostListView.js @@ -34,7 +34,8 @@ export function HostListView() { const { value: hosts, wrapper: getHosts, - loading + loading, + abort } = useAPIMethod({ fcn: client.apis.Hosts.listHosts, call: false @@ -128,7 +129,11 @@ export function HostListView() { ); requestParams.filter = hostFilter; getHosts(requestParams); - }, [getHosts, hostFilter, urlState.query, pagination]); + + return () => { + abort(); + }; + }, [getHosts, hostFilter, urlState.query, pagination, abort]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( @@ -141,6 +146,7 @@ export function HostListView() { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; const content = ( diff --git a/src/views/jobs/JobListView.js b/src/views/jobs/JobListView.js index 6c6e0a76939aa75c3f673cb38bf9d4ff03724923..0ac7543df179c508ec01a41b554261ccf8913eec 100644 --- a/src/views/jobs/JobListView.js +++ b/src/views/jobs/JobListView.js @@ -22,7 +22,8 @@ export function JobListView() { value: operations, wrapper: getOperations, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.Deployments.listOperations, call: false @@ -122,12 +123,17 @@ export function JobListView() { } getOperations(requestParams); + + return () => { + abort(); + }; }, [ getOperations, urlPagination, urlState.query, urlState.job_type, - deploymentStatus + deploymentStatus, + abort ]); const setSearch = useCallback( @@ -140,6 +146,7 @@ export function JobListView() { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; const content = ( diff --git a/src/views/records/RecordListView.js b/src/views/records/RecordListView.js index 81f7db29d349b4e9fbbb106e048aa19f686a2517..4f44f34b5240885afee0b0e6afda23da5c5f2386 100644 --- a/src/views/records/RecordListView.js +++ b/src/views/records/RecordListView.js @@ -35,7 +35,8 @@ export function RecordListView() { value: records, wrapper: getRecords, loading, - dataReady + dataReady, + abort } = useAPIMethod({ fcn: client.apis.Records.findAllRecords, call: false @@ -132,7 +133,11 @@ export function RecordListView() { requestParams.pv_status = recordFilter; requestParams.record_name = deserialize(urlState.query); getRecords(requestParams); - }, [getRecords, recordFilter, urlState.query, pagination]); + + return () => { + abort(); + }; + }, [getRecords, recordFilter, urlState.query, pagination, abort]); // Callback for searchbar, called whenever user updates search const setSearch = useCallback( @@ -145,6 +150,7 @@ export function RecordListView() { // Invoked by Table on change to pagination const onPage = (params) => { setPagination(params); + abort(); }; let content = ( diff --git a/src/views/statistics/StatisticsView.js b/src/views/statistics/StatisticsView.js index 414f473184805d4746f9ae96a48b2612cc396231..31d380c30128424f2848257cdfeb6a38e7f4a566 100644 --- a/src/views/statistics/StatisticsView.js +++ b/src/views/statistics/StatisticsView.js @@ -34,16 +34,23 @@ export function StatisticsView() { const theme = useTheme(); - const { value: iocsOverTime, wrapper: getIocsOverTime } = useAPIMethod({ + const { + value: iocsOverTime, + wrapper: getIocsOverTime, + abort: abortGetIocsOverTime + } = useAPIMethod({ fcn: client.apis.Statistics.activeIocHistory, call: false }); - const { value: operationStatistics, wrapper: getOperationStatistics } = - useAPIMethod({ - fcn: client.apis.Statistics.operationHistory, - call: false - }); + const { + value: operationStatistics, + wrapper: getOperationStatistics, + abort: abortGetOperationStatistics + } = useAPIMethod({ + fcn: client.apis.Statistics.operationHistory, + call: false + }); return ( <StyledRootPaper> @@ -74,6 +81,7 @@ export function StatisticsView() { title="Operations over time" iocDeployments={operationStatistics} getIOCDeployments={getOperationStatistics} + abortGetIOCDeployments={abortGetOperationStatistics} /> </Box> </Grid> @@ -95,6 +103,7 @@ export function StatisticsView() { chartLabel="Active IOCs over time" iocDeployments={iocsOverTime} getIOCDeployments={getIocsOverTime} + abortGetIOCDeployments={abortGetIocsOverTime} /> </Box> </Grid>