diff --git a/apps/hpc-ftsadmin/src/app/components/filters/filter-flows-table.tsx b/apps/hpc-ftsadmin/src/app/components/filters/filter-flows-table.tsx index e4df81dd1..6c0a56a55 100644 --- a/apps/hpc-ftsadmin/src/app/components/filters/filter-flows-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/filters/filter-flows-table.tsx @@ -25,7 +25,6 @@ import InfoAlert from '../info-alert'; interface Props { query: Query; setQuery: (newQuery: Query) => void; - handleAbortController: () => void; } export interface FlowsFilterValues { flowID?: string[]; @@ -94,7 +93,7 @@ const StyledDiv = tw.div` gap-x-4 `; export const FilterFlowsTable = (props: Props) => { - const { setQuery, query, handleAbortController } = props; + const { setQuery, query } = props; const { lang, env } = useContext(AppContext); const environment = env(); @@ -104,15 +103,10 @@ export const FilterFlowsTable = (props: Props) => { FLOWS_FILTER_INITIAL_VALUES ); const handleSubmit = (values: FlowsFilterValues) => { - const encodedFilters = encodeFilters(values, FLOWS_FILTER_INITIAL_VALUES); - - if (query.filters !== encodedFilters) { - handleAbortController(); - } setQuery({ ...query, page: 0, - filters: encodedFilters, + filters: encodeFilters(values, FLOWS_FILTER_INITIAL_VALUES), }); }; const handleResetForm = ( @@ -120,16 +114,11 @@ export const FilterFlowsTable = (props: Props) => { nextState?: Partial> ) => void ) => { - const encodedFilters = encodeFilters({}, FLOWS_FILTER_INITIAL_VALUES); formikResetForm(); - - if (query.filters !== encodedFilters) { - handleAbortController(); - } setQuery({ ...query, page: 0, - filters: encodedFilters, + filters: encodeFilters({}, FLOWS_FILTER_INITIAL_VALUES), }); }; return ( diff --git a/apps/hpc-ftsadmin/src/app/components/filters/filter-organization-table.tsx b/apps/hpc-ftsadmin/src/app/components/filters/filter-organization-table.tsx index 4ff25c7a8..1723b24af 100644 --- a/apps/hpc-ftsadmin/src/app/components/filters/filter-organization-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/filters/filter-organization-table.tsx @@ -20,6 +20,7 @@ interface Props { query: Query; setQuery: (newQuery: Query) => void; lang: LanguageKey; + handleAbortController: () => void; } export interface OrganizationFilterValues { organization?: string; @@ -46,7 +47,7 @@ const StyledDiv = tw.div` gap-x-4 `; export const FilterOrganizationsTable = (props: Props) => { - const { environment, setQuery, query, lang } = props; + const { environment, setQuery, query, lang, handleAbortController } = props; const filters = decodeFilters( query.filters, ORGANIZATIONS_FILTER_INITIAL_VALUES @@ -57,10 +58,17 @@ export const FilterOrganizationsTable = (props: Props) => { }); const handleSubmit = (values: OrganizationFilterValues) => { + const encodedFilters = encodeFilters( + values, + ORGANIZATIONS_FILTER_INITIAL_VALUES + ); + if (query.filters !== encodedFilters) { + handleAbortController(); + } setQuery({ ...query, page: 0, - filters: encodeFilters(values, ORGANIZATIONS_FILTER_INITIAL_VALUES), + filters: encodedFilters, }); }; const handleResetForm = ( @@ -68,11 +76,18 @@ export const FilterOrganizationsTable = (props: Props) => { nextState?: Partial> ) => void ) => { + const encodedFilters = encodeFilters( + {}, + ORGANIZATIONS_FILTER_INITIAL_VALUES + ); formikResetForm(); + if (query.filters !== encodedFilters) { + handleAbortController(); + } setQuery({ ...query, page: 0, - filters: encodeFilters({}, ORGANIZATIONS_FILTER_INITIAL_VALUES), + filters: encodedFilters, }); }; return ( diff --git a/apps/hpc-ftsadmin/src/app/components/filters/filter-pending-flows-table.tsx b/apps/hpc-ftsadmin/src/app/components/filters/filter-pending-flows-table.tsx index dd0f531e4..c814493d6 100644 --- a/apps/hpc-ftsadmin/src/app/components/filters/filter-pending-flows-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/filters/filter-pending-flows-table.tsx @@ -16,7 +16,6 @@ import { interface Props { query: Query; setQuery: (newQuery: Query) => void; - handleAbortController: () => void; } export interface PendingFlowsFilterValues { status?: FormObjectValue | null; @@ -49,22 +48,15 @@ const StyledDiv = tw.div` gap-x-4 `; export const FilterPendingFlowsTable = (props: Props) => { - const { setQuery, query, handleAbortController } = props; + const { setQuery, query } = props; const { lang, env } = useContext(AppContext); const environment = env(); const handleSubmit = (values: PendingFlowsFilterValues) => { - const encodedFilters = encodeFilters( - values, - PENDING_FLOWS_FILTER_INITIAL_VALUES - ); - if (query.filters !== encodedFilters) { - handleAbortController(); - } setQuery({ ...query, page: 0, - filters: encodedFilters, + filters: encodeFilters(values, PENDING_FLOWS_FILTER_INITIAL_VALUES), }); }; const handleResetForm = ( @@ -72,18 +64,11 @@ export const FilterPendingFlowsTable = (props: Props) => { nextState?: Partial> ) => void ) => { - const encodedFilters = encodeFilters( - {}, - PENDING_FLOWS_FILTER_INITIAL_VALUES - ); formikResetForm(); - if (query.filters !== encodedFilters) { - handleAbortController(); - } setQuery({ ...query, page: 0, - filters: encodedFilters, + filters: encodeFilters({}, PENDING_FLOWS_FILTER_INITIAL_VALUES), }); }; return ( diff --git a/apps/hpc-ftsadmin/src/app/components/tables/flows-table.tsx b/apps/hpc-ftsadmin/src/app/components/tables/flows-table.tsx index 7a8b5935c..f05ccb099 100644 --- a/apps/hpc-ftsadmin/src/app/components/tables/flows-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/tables/flows-table.tsx @@ -69,7 +69,6 @@ export interface FlowsTableProps { rowsPerPageOption: number[]; query: Query; setQuery: (newQuery: Query) => void; - abortSignal?: AbortSignal; pending?: boolean; } @@ -93,7 +92,6 @@ export default function FlowsTable(props: FlowsTableProps) { sortField: query.orderBy, sortOrder: query.orderDir, ...parsedFilters, - signal: props.abortSignal, prevPageCursor: query.prevPageCursor, nextPageCursor: query.nextPageCursor, }) diff --git a/apps/hpc-ftsadmin/src/app/components/tables/keywords-table.tsx b/apps/hpc-ftsadmin/src/app/components/tables/keywords-table.tsx index 7ecca3685..fac8f2dbf 100644 --- a/apps/hpc-ftsadmin/src/app/components/tables/keywords-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/tables/keywords-table.tsx @@ -57,6 +57,7 @@ export interface KeywordTableProps { headers: TableHeadersProps[]; query: KeywordQuery; setQuery: (newQuery: KeywordQuery) => void; + abortSignal: AbortSignal; } /** @@ -250,7 +251,7 @@ export default function KeywordTable(props: KeywordTableProps) { const [openSettings, setOpenSettings] = useState(false); const [entityEdited, setEntityEdited] = useState(false); const state = dataLoader([entityEdited], () => - env.model.categories.getKeywords() + env.model.categories.getKeywords(props.abortSignal) ); const [errorUpdate, setErrorUpdate] = useState<{ code: keyof Strings['components']['keywordTable']['errors']; diff --git a/apps/hpc-ftsadmin/src/app/components/tables/organizations-table.tsx b/apps/hpc-ftsadmin/src/app/components/tables/organizations-table.tsx index ee2cd9943..22ce7fe1d 100644 --- a/apps/hpc-ftsadmin/src/app/components/tables/organizations-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/tables/organizations-table.tsx @@ -62,6 +62,7 @@ export interface OrganizationTableProps { rowsPerPageOption: number[]; query: Query; setQuery: (newQuery: Query) => void; + abortSignal: AbortSignal; } export default function OrganizationTable(props: OrganizationTableProps) { @@ -87,6 +88,7 @@ export default function OrganizationTable(props: OrganizationTableProps) { offset: query.page * query.rowsPerPage, orderBy: query.orderBy, orderDir: query.orderDir, + signal: props.abortSignal, ...parseOrganizationFilters(parsedFilters).search, }, }) diff --git a/apps/hpc-ftsadmin/src/app/pages/flows/flows-list.tsx b/apps/hpc-ftsadmin/src/app/pages/flows/flows-list.tsx index 1757fed59..9fb979e5a 100644 --- a/apps/hpc-ftsadmin/src/app/pages/flows/flows-list.tsx +++ b/apps/hpc-ftsadmin/src/app/pages/flows/flows-list.tsx @@ -23,7 +23,6 @@ import FlowsTable, { import FilterFlowsTable, { FLOWS_FILTER_INITIAL_VALUES, } from '../../components/filters/filter-flows-table'; -import { useCallback, useEffect, useState } from 'react'; interface Props { className?: string; @@ -39,30 +38,6 @@ const LandingContainer = tw.div` `; export default (props: Props) => { const rowsPerPageOptions = [10, 25, 50, 100]; - const [abortController, setAbortController] = useState( - new AbortController() - ); - - const handleAbortController = useCallback(() => { - // Abort the ongoing requests - abortController.abort(); - - // Create a new AbortController for the next requests - const newAbortController = new AbortController(); - setAbortController(newAbortController); - - // Perform actions with the updated filter values - - // Pass the new AbortSignal to FlowsTableGraphQL - // This can be part of your state or directly passed as a prop - }, [abortController]); - - useEffect(() => { - return () => { - handleAbortController(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); const [query, setQuery] = useQueryParams({ page: withDefault(NumberParam, 0), @@ -106,7 +81,6 @@ export default (props: Props) => { initialValues: FLOWS_FILTER_INITIAL_VALUES, query: query, setQuery: setQuery, - abortSignal: abortController.signal, }; return ( @@ -117,11 +91,7 @@ export default (props: Props) => { > s.routes.flows.title)]} /> - + {t.t(lang, (s) => s.routes.flows.title)} diff --git a/apps/hpc-ftsadmin/src/app/pages/flows/pending-flows-list.tsx b/apps/hpc-ftsadmin/src/app/pages/flows/pending-flows-list.tsx index fd651fa6e..39d19d42e 100644 --- a/apps/hpc-ftsadmin/src/app/pages/flows/pending-flows-list.tsx +++ b/apps/hpc-ftsadmin/src/app/pages/flows/pending-flows-list.tsx @@ -22,7 +22,6 @@ import { import FlowsTable, { FlowsTableProps, } from '../../components/tables/flows-table'; -import { useCallback, useEffect, useState } from 'react'; interface Props { className?: string; @@ -35,10 +34,6 @@ const LandingContainer = tw.div` `; export default (props: Props) => { - const [abortController, setAbortController] = useState( - new AbortController() - ); - const [query, setQuery] = useQueryParams({ page: withDefault(NumberParam, 0), rowsPerPage: withDefault( @@ -72,27 +67,6 @@ export default (props: Props) => { nextPageCursor: withDefault(NumberParam, 0), }); - const handleAbortController = useCallback(() => { - // Abort the ongoing requests - abortController.abort(); - - // Create a new AbortController for the next requests - const newAbortController = new AbortController(); - setAbortController(newAbortController); - - // Perform actions with the updated filter values - - // Pass the new AbortSignal to FlowsTableGraphQL - // This can be part of your state or directly passed as a prop - }, [abortController]); - - useEffect(() => { - return () => { - handleAbortController(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - const pendingFlowsTableProps: FlowsTableProps = { headers: DEFAULT_FLOW_TABLE_HEADERS, initialValues: PENDING_FLOWS_FILTER_INITIAL_VALUES, @@ -100,7 +74,6 @@ export default (props: Props) => { query: query, setQuery: setQuery, pending: true, - abortSignal: abortController.signal, }; return ( @@ -111,11 +84,7 @@ export default (props: Props) => { > s.routes.flows.title)]} /> - + {t.t(lang, (s) => s.routes.pendingFlows.title)} diff --git a/apps/hpc-ftsadmin/src/app/pages/keywords/keyword-list.tsx b/apps/hpc-ftsadmin/src/app/pages/keywords/keyword-list.tsx index 8d1aec373..b16c752a6 100644 --- a/apps/hpc-ftsadmin/src/app/pages/keywords/keyword-list.tsx +++ b/apps/hpc-ftsadmin/src/app/pages/keywords/keyword-list.tsx @@ -16,6 +16,7 @@ import { import KeywordTable, { KeywordTableProps, } from '../../components/tables/keywords-table'; +import { useCallback, useEffect, useState } from 'react'; interface Props { className?: string; @@ -46,10 +47,35 @@ export default (props: Props) => { tableHeaders: withDefault(StringParam, encodeTableHeaders([], 'keywords')), }); + const [abortController, setAbortController] = useState( + new AbortController() + ); + const handleAbortController = useCallback(() => { + // Abort the ongoing requests + abortController.abort(); + + // Create a new AbortController for the next requests + const newAbortController = new AbortController(); + setAbortController(newAbortController); + + // Perform actions with the updated filter values + + // Pass the new AbortSignal to FlowsTableGraphQL + // This can be part of your state or directly passed as a prop + }, [abortController]); + + useEffect(() => { + return () => { + handleAbortController(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const keywordTableProps: KeywordTableProps = { headers: DEFAULT_KEYWORD_TABLE_HEADERS, query, setQuery, + abortSignal: abortController.signal, }; return ( diff --git a/apps/hpc-ftsadmin/src/app/pages/organizations/organization-list.tsx b/apps/hpc-ftsadmin/src/app/pages/organizations/organization-list.tsx index 42f9e1a95..fdecd5d22 100644 --- a/apps/hpc-ftsadmin/src/app/pages/organizations/organization-list.tsx +++ b/apps/hpc-ftsadmin/src/app/pages/organizations/organization-list.tsx @@ -22,6 +22,7 @@ import OrganizationTable, { import FilterOrganizationsTable, { ORGANIZATIONS_FILTER_INITIAL_VALUES, } from '../../components/filters/filter-organization-table'; +import { useCallback, useEffect, useState } from 'react'; interface Props { className?: string; @@ -35,6 +36,29 @@ const LandingContainer = tw.div` `; export default (props: Props) => { const rowsPerPageOptions = [10, 25, 50, 100]; + const [abortController, setAbortController] = useState( + new AbortController() + ); + const handleAbortController = useCallback(() => { + // Abort the ongoing requests + abortController.abort(); + + // Create a new AbortController for the next requests + const newAbortController = new AbortController(); + setAbortController(newAbortController); + + // Perform actions with the updated filter values + + // Pass the new AbortSignal to FlowsTableGraphQL + // This can be part of your state or directly passed as a prop + }, [abortController]); + + useEffect(() => { + return () => { + handleAbortController(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const [query, setQuery] = useQueryParams({ page: withDefault(NumberParam, 0), @@ -78,6 +102,7 @@ export default (props: Props) => { initialValues: ORGANIZATIONS_FILTER_INITIAL_VALUES, query: query, setQuery: setQuery, + abortSignal: abortController.signal, }; const env = getEnv(); @@ -94,6 +119,7 @@ export default (props: Props) => { setQuery={setQuery} query={query} lang={lang} + handleAbortController={handleAbortController} /> diff --git a/libs/hpc-data/src/lib/categories.ts b/libs/hpc-data/src/lib/categories.ts index 6fcb3d9a6..0d8d0e8cd 100644 --- a/libs/hpc-data/src/lib/categories.ts +++ b/libs/hpc-data/src/lib/categories.ts @@ -1,4 +1,5 @@ import * as t from 'io-ts'; +import type { AbortSignalType } from './util'; export type CategoryGroup = | 'flowType' @@ -82,7 +83,7 @@ export type MergeKeywordResult = t.TypeOf; export interface Model { getCategories(params: GetCategoriesParams): Promise; - getKeywords(): Promise; + getKeywords(abortSignal?: AbortSignalType): Promise; deleteKeyword(params: DeleteKeywordParams): Promise; updateKeyword(params: Keyword): Promise; mergeKeywords(params: MergeKeywordParams): Promise; diff --git a/libs/hpc-data/src/lib/flows.ts b/libs/hpc-data/src/lib/flows.ts index 1dfe9f2d5..fb6bf4eb2 100644 --- a/libs/hpc-data/src/lib/flows.ts +++ b/libs/hpc-data/src/lib/flows.ts @@ -294,13 +294,6 @@ const FLOW_FILTERS = t.partial({ }); export type FlowFilters = t.TypeOf; -const AbortSignalType = new t.Type( - 'AbortSignal', - (input: unknown): input is AbortSignal => input instanceof AbortSignal, - (input, context) => - input instanceof AbortSignal ? t.success(input) : t.failure(input, context), - t.identity -); export const NESTED_FLOW_FILTERS = t.partial({ reporterRefCode: t.string, @@ -316,7 +309,6 @@ export const SEARCH_FLOWS_PARAMS = t.partial({ sortOrder: t.string, sortField: t.string, ...FLOW_FILTERS.props, - signal: AbortSignalType, }); export type SearchFlowsParams = t.TypeOf; diff --git a/libs/hpc-data/src/lib/organizations.ts b/libs/hpc-data/src/lib/organizations.ts index 057324b20..948054473 100644 --- a/libs/hpc-data/src/lib/organizations.ts +++ b/libs/hpc-data/src/lib/organizations.ts @@ -1,5 +1,6 @@ import * as t from 'io-ts'; import { LOCATION_BUILDER } from './locations'; +import { ABORT_SIGNAL } from './util'; const ORGANIZATION_CATEGORY = t.type({ id: t.number, @@ -125,6 +126,7 @@ export const SEARCH_ORGANIZATION_PARAMS = t.type({ orderDir: t.union([t.string, t.null]), limit: t.number, offset: t.number, + signal: ABORT_SIGNAL, }), }); export type SearchOrganizationParams = t.TypeOf< diff --git a/libs/hpc-data/src/lib/util.ts b/libs/hpc-data/src/lib/util.ts index a2634cbbd..c2e360cb8 100644 --- a/libs/hpc-data/src/lib/util.ts +++ b/libs/hpc-data/src/lib/util.ts @@ -381,3 +381,13 @@ export const VALID_DAYJS_DATE = new t.Type( }, t.identity ); + +export const ABORT_SIGNAL = new t.Type( + 'AbortSignal', + (input: unknown): input is AbortSignal => input instanceof AbortSignal, + (input, context) => + input instanceof AbortSignal ? t.success(input) : t.failure(input, context), + t.identity +); + +export type AbortSignalType = t.TypeOf; diff --git a/libs/hpc-live/src/lib/model.ts b/libs/hpc-live/src/lib/model.ts index d8a4f1aaf..cc158c3be 100644 --- a/libs/hpc-live/src/lib/model.ts +++ b/libs/hpc-live/src/lib/model.ts @@ -587,7 +587,7 @@ export class LiveModel implements Model { }, resultType: categories.GET_CATEGORIES_RESULT, }), - getKeywords: () => + getKeywords: (signal) => this.call({ pathname: '/v2/category', queryParams: { @@ -595,6 +595,7 @@ export class LiveModel implements Model { scopes: 'relatedCount', }, resultType: categories.GET_KEYWORDS_RESULT, + signal, }), deleteKeyword: (params) => this.call({ @@ -754,6 +755,7 @@ export class LiveModel implements Model { type: 'json', data: params, }, + signal: params.search.signal, resultType: organizations.SEARCH_ORGANIZATION_RESULT, }), getOrganization: (params) => diff --git a/libs/hpc-live/src/lib/utils.ts b/libs/hpc-live/src/lib/utils.ts index cba38a81d..713716a98 100644 --- a/libs/hpc-live/src/lib/utils.ts +++ b/libs/hpc-live/src/lib/utils.ts @@ -28,7 +28,7 @@ export const searchFlowsParams = (params: flows.SearchFlowsParams): string => { break; } default: { - if (key !== 'signal' && params[key]) { + if (params[key]) { queryParams += `${key}: ${stringify(params[key])} `; } break;