From 3358fe43ec146bcca708e37502f4027d43b77151 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Wed, 9 Oct 2024 00:13:34 +1100 Subject: [PATCH 01/14] Add search by `dag_display_name_pattern` on dag list page. --- airflow/ui/openapi-gen/queries/queries.ts | 4 ++ airflow/ui/package.json | 3 +- airflow/ui/pnpm-lock.yaml | 13 ++++++ .../src/components/DataTable/searchParams.ts | 10 +++-- airflow/ui/src/components/SearchBar.tsx | 19 ++++---- airflow/ui/src/constants/searchParams.ts | 25 +++++++++++ airflow/ui/src/pages/DagsList/DagsFilters.tsx | 3 +- airflow/ui/src/pages/DagsList/DagsList.tsx | 45 ++++++++++++++++--- 8 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 airflow/ui/src/constants/searchParams.ts diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index 01e919cce53..6a566a00550 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -152,6 +152,10 @@ export const useDagServiceGetDags = < paused, tags, }) as TData, + staleTime: 5 * 60 * 1000, + refetchOnWindowFocus: false, + refetchOnMount: true, + refetchOnReconnect: false, ...options, }); /** diff --git a/airflow/ui/package.json b/airflow/ui/package.json index 014564c1604..a7cf90bb573 100644 --- a/airflow/ui/package.json +++ b/airflow/ui/package.json @@ -28,7 +28,8 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.3.0", - "react-router-dom": "^6.26.2" + "react-router-dom": "^6.26.2", + "use-debounce": "^10.0.3" }, "devDependencies": { "@7nohe/openapi-react-query-codegen": "^1.6.0", diff --git a/airflow/ui/pnpm-lock.yaml b/airflow/ui/pnpm-lock.yaml index c9f94d35f73..3b73df0fa80 100644 --- a/airflow/ui/pnpm-lock.yaml +++ b/airflow/ui/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: react-router-dom: specifier: ^6.26.2 version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + use-debounce: + specifier: ^10.0.3 + version: 10.0.3(react@18.3.1) devDependencies: '@7nohe/openapi-react-query-codegen': specifier: ^1.6.0 @@ -3221,6 +3224,12 @@ packages: '@types/react': optional: true + use-debounce@10.0.3: + resolution: {integrity: sha512-DxQSI9ZKso689WM1mjgGU3ozcxU1TJElBJ3X6S4SMzMNcm2lVH0AHmyXB+K7ewjz2BSUKJTDqTcwtSMRfB89dg==} + engines: {node: '>= 16.0.0'} + peerDependencies: + react: '*' + use-isomorphic-layout-effect@1.1.2: resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: @@ -6892,6 +6901,10 @@ snapshots: optionalDependencies: '@types/react': 18.3.5 + use-debounce@10.0.3(react@18.3.1): + dependencies: + react: 18.3.1 + use-isomorphic-layout-effect@1.1.2(@types/react@18.3.5)(react@18.3.1): dependencies: react: 18.3.1 diff --git a/airflow/ui/src/components/DataTable/searchParams.ts b/airflow/ui/src/components/DataTable/searchParams.ts index 8cc57ad7b5b..d62b50b2c55 100644 --- a/airflow/ui/src/components/DataTable/searchParams.ts +++ b/airflow/ui/src/components/DataTable/searchParams.ts @@ -17,12 +17,14 @@ * under the License. */ import type { SortingState } from "@tanstack/react-table"; - import type { TableState } from "./types"; +import { searchParamsKeys } from "src/constants/searchParams"; -export const LIMIT_PARAM = "limit"; -export const OFFSET_PARAM = "offset"; -export const SORT_PARAM = "sort"; +const { + LIMIT: LIMIT_PARAM, + OFFSET: OFFSET_PARAM, + SORT: SORT_PARAM +} = searchParamsKeys; export const stateToSearchParams = ( state: TableState, diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index 830f9426771..a7deaaffb56 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { forwardRef } from "react"; import { Button, type ButtonProps, @@ -28,20 +29,16 @@ import { } from "@chakra-ui/react"; import { FiSearch } from "react-icons/fi"; -export const SearchBar = ({ - buttonProps, - groupProps, - inputProps, -}: { - readonly buttonProps?: ButtonProps; - readonly groupProps?: InputGroupProps; - readonly inputProps?: InputProps; -}) => ( +export const SearchBar = forwardRef(({ buttonProps, groupProps, inputProps }, ref) => ( - + - - -)); +}) => { + + const handleSearchChange = useDebouncedCallback( + (event: ChangeEvent) => { + inputProps?.onChange?.(event); + }, + debounceDelay + ); + + return ( + + + + + + + + + + ); +}; diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 81b9d040493..917f20ff815 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -25,7 +25,7 @@ import { VStack, } from "@chakra-ui/react"; import type { ColumnDef } from "@tanstack/react-table"; -import { type ChangeEventHandler, SyntheticEvent, useCallback, useEffect, useRef, useState } from "react"; +import { type ChangeEventHandler, useCallback, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useDagServiceGetDags } from "openapi/queries"; @@ -42,7 +42,6 @@ import { searchParamsKeys } from "src/constants/searchParams"; import { DagCard } from "./DagCard"; import { DagsFilters } from "./DagsFilters"; -import { useDebouncedCallback } from "use-debounce"; const columns: Array> = [ { @@ -94,7 +93,6 @@ const columns: Array> = [ const { PAUSED: PAUSED_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM } = searchParamsKeys; -// eslint-disable-next-line complexity const cardDef: CardDef = { card: ({ row }) => , meta: { @@ -113,37 +111,32 @@ export const DagsList = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; - - const searchBarRef = useRef(null); + const [dagDisplayNamePattern, setDagDisplayNamePattern] = useState(searchParams.get(NAME_PATTERN_PARAM) ?? undefined); // TODO: update API to accept multiple orderBy params const [sort] = sorting; const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : undefined; - const [dagDisplayNamePattern, setDagDisplayNamePattern] = useState(searchParams.get(NAME_PATTERN_PARAM) ?? undefined); - - const dagDisplayNamePatternDebounceDelay = 200; - - const handleSearchBarChange = useDebouncedCallback( - ({ target }: SyntheticEvent) => { - const { value } = target as HTMLInputElement; + const handleSearchChange = (value: string) => { + if (value) { searchParams.set(NAME_PATTERN_PARAM, value); - setSearchParams(searchParams); - setTableURLState({ - pagination: { ...pagination, pageIndex: 0 }, - sorting, - }); - setDagDisplayNamePattern(value); - }, - dagDisplayNamePatternDebounceDelay - ); + } else { + searchParams.delete(NAME_PATTERN_PARAM); + } + setSearchParams(searchParams); + setTableURLState({ + pagination: { ...pagination, pageIndex: 0 }, + sorting, + }); + setDagDisplayNamePattern(value); + }; const { data, error, isFetching, isLoading } = useDagServiceGetDags({ lastDagRunState, dagDisplayNamePattern: dagDisplayNamePattern !== "" ? dagDisplayNamePattern : undefined, limit: pagination.pageSize, offset: pagination.pageIndex * pagination.pageSize, - onlyActive: false, + onlyActive: true, orderBy, paused: showPaused === null ? undefined : showPaused === "true", }, [dagDisplayNamePattern, showPaused]); @@ -160,18 +153,12 @@ export const DagsList = () => { [pagination, setTableURLState], ); - useEffect(() => { - if (searchBarRef.current) { - searchBarRef.current.value = dagDisplayNamePattern ?? ""; - } - }, [searchBarRef.current]); - return ( <> handleSearchChange(e.target.value) }} buttonProps={{ isDisabled: true }} /> From c4e51fe4627ce011b6df6bd74e53d61a5907e243 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Wed, 9 Oct 2024 22:01:28 +1100 Subject: [PATCH 04/14] Refactor search input change handling for SearchBar and DagsList components --- airflow/ui/src/components/SearchBar.tsx | 6 ++---- airflow/ui/src/pages/DagsList/DagsList.tsx | 10 ++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index 3fa4adf60cf..1381d1e08ed 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { useState, ChangeEvent } from "react"; +import { ChangeEvent } from "react"; import { Button, Input, @@ -43,9 +43,7 @@ export const SearchBar = ({ }) => { const handleSearchChange = useDebouncedCallback( - (event: ChangeEvent) => { - inputProps?.onChange?.(event); - }, + (event: ChangeEvent) => inputProps?.onChange?.(event), debounceDelay ); diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 917f20ff815..e6c156959d6 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -25,7 +25,7 @@ import { VStack, } from "@chakra-ui/react"; import type { ColumnDef } from "@tanstack/react-table"; -import { type ChangeEventHandler, useCallback, useState } from "react"; +import { ChangeEvent, type ChangeEventHandler, useCallback, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useDagServiceGetDags } from "openapi/queries"; @@ -117,7 +117,7 @@ export const DagsList = () => { const [sort] = sorting; const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : undefined; - const handleSearchChange = (value: string) => { + const handleSearchChange = ({ target: { value } }: ChangeEvent) => { if (value) { searchParams.set(NAME_PATTERN_PARAM, value); } else { @@ -157,8 +157,10 @@ export const DagsList = () => { <> handleSearchChange(e.target.value) }} + inputProps={{ + onChange: handleSearchChange, + defaultValue: dagDisplayNamePattern + }} buttonProps={{ isDisabled: true }} /> From 62dc6b1fb616cb8a95fe43f3ef95f986498b9218 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 19:47:13 +1100 Subject: [PATCH 05/14] Update airflow/ui/src/pages/DagsList/DagsList.tsx Co-authored-by: Brent Bovenzi --- airflow/ui/src/pages/DagsList/DagsList.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index e6c156959d6..1e418125e5a 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -133,7 +133,9 @@ export const DagsList = () => { const { data, error, isFetching, isLoading } = useDagServiceGetDags({ lastDagRunState, - dagDisplayNamePattern: dagDisplayNamePattern !== "" ? dagDisplayNamePattern : undefined, + dagDisplayNamePattern: Boolean(dagDisplayNamePattern) + ? `%${dagDisplayNamePattern}%` + : undefined, limit: pagination.pageSize, offset: pagination.pageIndex * pagination.pageSize, onlyActive: true, From ba9c18eb92745aa9cfb6106157a76cb030bfa837 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 22:32:49 +1100 Subject: [PATCH 06/14] Refactor search parameter handling and improve type consistency --- .../src/components/DataTable/searchParams.ts | 4 +- airflow/ui/src/components/SearchBar.tsx | 70 +++++++------------ airflow/ui/src/constants/searchParams.ts | 8 ++- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 5 +- airflow/ui/src/pages/DagsList/DagsList.tsx | 15 ++-- 5 files changed, 44 insertions(+), 58 deletions(-) diff --git a/airflow/ui/src/components/DataTable/searchParams.ts b/airflow/ui/src/components/DataTable/searchParams.ts index d62b50b2c55..a85cfbe040b 100644 --- a/airflow/ui/src/components/DataTable/searchParams.ts +++ b/airflow/ui/src/components/DataTable/searchParams.ts @@ -18,13 +18,13 @@ */ import type { SortingState } from "@tanstack/react-table"; import type { TableState } from "./types"; -import { searchParamsKeys } from "src/constants/searchParams"; +import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; const { LIMIT: LIMIT_PARAM, OFFSET: OFFSET_PARAM, SORT: SORT_PARAM -} = searchParamsKeys; +} : SearchParamsKeysType = SearchParamsKeys; export const stateToSearchParams = ( state: TableState, diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index 1381d1e08ed..a7deaaffb56 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,60 +16,40 @@ * specific language governing permissions and limitations * under the License. */ -import { ChangeEvent } from "react"; +import { forwardRef } from "react"; import { Button, + type ButtonProps, Input, InputGroup, - InputLeftElement, - InputRightElement, - type ButtonProps, type InputGroupProps, + InputLeftElement, type InputProps, + InputRightElement, } from "@chakra-ui/react"; import { FiSearch } from "react-icons/fi"; -import { useDebouncedCallback } from "use-debounce"; - -const debounceDelay = 200; -export const SearchBar = ({ - buttonProps, - groupProps, - inputProps, -}: { +export const SearchBar = forwardRef { - - const handleSearchChange = useDebouncedCallback( - (event: ChangeEvent) => inputProps?.onChange?.(event), - debounceDelay - ); - - return ( - - - - - - - - - - ); -}; +}>(({ buttonProps, groupProps, inputProps }, ref) => ( + + + + + + + + + +)); diff --git a/airflow/ui/src/constants/searchParams.ts b/airflow/ui/src/constants/searchParams.ts index 51606298ce3..4bcae956329 100644 --- a/airflow/ui/src/constants/searchParams.ts +++ b/airflow/ui/src/constants/searchParams.ts @@ -16,10 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -export enum searchParamsKeys { - NAME_PATTERN = "name_pattern", - PAUSED = "paused", +export enum SearchParamsKeys { LIMIT = "limit", + NAME_PATTERN = "name_pattern", OFFSET = "offset", + PAUSED = "paused", SORT = "sort" } + +export type SearchParamsKeysType = Record; diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 9d6799b9cb6..830ce3efe1a 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -25,12 +25,13 @@ import { useTableURLState } from "src/components/DataTable/useTableUrlState"; import { QuickFilterButton } from "src/components/QuickFilterButton"; const STATE_PARAM = "last_dag_run_state"; -import { searchParamsKeys } from "src/constants/searchParams"; +import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; + +const { PAUSED: PAUSED_PARAM }: SearchParamsKeysType = SearchParamsKeys; export const DagsFilters = () => { const [searchParams, setSearchParams] = useSearchParams(); - const { PAUSED: PAUSED_PARAM } = searchParamsKeys; const showPaused = searchParams.get(PAUSED_PARAM); const state = searchParams.get(STATE_PARAM); const isAll = state === null; diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 1e418125e5a..c1037db7acd 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -25,7 +25,7 @@ import { VStack, } from "@chakra-ui/react"; import type { ColumnDef } from "@tanstack/react-table"; -import { ChangeEvent, type ChangeEventHandler, useCallback, useState } from "react"; +import { type ChangeEvent, type ChangeEventHandler, useCallback, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useDagServiceGetDags } from "openapi/queries"; @@ -38,7 +38,7 @@ import { ErrorAlert } from "src/components/ErrorAlert"; import { SearchBar } from "src/components/SearchBar"; import { TogglePause } from "src/components/TogglePause"; import { pluralize } from "src/utils/pluralize"; -import { searchParamsKeys } from "src/constants/searchParams"; +import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; import { DagCard } from "./DagCard"; import { DagsFilters } from "./DagsFilters"; @@ -91,7 +91,10 @@ const columns: Array> = [ }, ]; -const { PAUSED: PAUSED_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM } = searchParamsKeys; +const { + NAME_PATTERN: NAME_PATTERN_PARAM, + PAUSED: PAUSED_PARAM +}: SearchParamsKeysType = SearchParamsKeys; const cardDef: CardDef = { card: ({ row }) => , @@ -159,11 +162,11 @@ export const DagsList = () => { <> From 7ec6a9e9657f294e1fb71ad018c7a62c9b410244 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 22:42:23 +1100 Subject: [PATCH 07/14] Remove typo --- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 830ce3efe1a..47b01e12a74 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -1,4 +1,4 @@ -/*! +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information From 8593d422104f99c332def190ba7f461f039ec25e Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 22:49:33 +1100 Subject: [PATCH 08/14] Add `LAST_DAG_RUN_STATE` to `SearchParamsKeys` and update filters --- airflow/ui/src/constants/searchParams.ts | 1 + airflow/ui/src/pages/DagsList/DagsFilters.tsx | 12 +++++++----- airflow/ui/src/pages/DagsList/DagsList.tsx | 7 +++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/airflow/ui/src/constants/searchParams.ts b/airflow/ui/src/constants/searchParams.ts index 4bcae956329..3fad2386f2c 100644 --- a/airflow/ui/src/constants/searchParams.ts +++ b/airflow/ui/src/constants/searchParams.ts @@ -19,6 +19,7 @@ export enum SearchParamsKeys { LIMIT = "limit", NAME_PATTERN = "name_pattern", + LAST_DAG_RUN_STATE = "last_dag_run_state", OFFSET = "offset", PAUSED = "paused", SORT = "sort" diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 47b01e12a74..f0a238f10c0 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -24,16 +24,18 @@ import { useSearchParams } from "react-router-dom"; import { useTableURLState } from "src/components/DataTable/useTableUrlState"; import { QuickFilterButton } from "src/components/QuickFilterButton"; -const STATE_PARAM = "last_dag_run_state"; import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; -const { PAUSED: PAUSED_PARAM }: SearchParamsKeysType = SearchParamsKeys; +const { + PAUSED: PAUSED_PARAM, + LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM +}: SearchParamsKeysType = SearchParamsKeys; export const DagsFilters = () => { const [searchParams, setSearchParams] = useSearchParams(); const showPaused = searchParams.get(PAUSED_PARAM); - const state = searchParams.get(STATE_PARAM); + const state = searchParams.get(LAST_DAG_RUN_STATE_PARAM); const isAll = state === null; const isRunning = state === "running"; const isFailed = state === "failed"; @@ -63,9 +65,9 @@ export const DagsFilters = () => { useCallback( ({ currentTarget: { value } }) => { if (value === "all") { - searchParams.delete(STATE_PARAM); + searchParams.delete(LAST_DAG_RUN_STATE_PARAM); } else { - searchParams.set(STATE_PARAM, value); + searchParams.set(LAST_DAG_RUN_STATE_PARAM, value); } setSearchParams(searchParams); setTableURLState({ diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index c1037db7acd..33ac3f72e57 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -93,7 +93,8 @@ const columns: Array> = [ const { NAME_PATTERN: NAME_PATTERN_PARAM, - PAUSED: PAUSED_PARAM + PAUSED: PAUSED_PARAM, + LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM }: SearchParamsKeysType = SearchParamsKeys; const cardDef: CardDef = { @@ -103,14 +104,12 @@ const cardDef: CardDef = { }, }; -const STATE_PARAM = "last_dag_run_state"; - export const DagsList = () => { const [searchParams, setSearchParams] = useSearchParams(); const [display, setDisplay] = useState<"card" | "table">("card"); const showPaused = searchParams.get(PAUSED_PARAM); - const lastDagRunState = searchParams.get(STATE_PARAM) as DagRunState; + const lastDagRunState = searchParams.get(LAST_DAG_RUN_STATE_PARAM) as DagRunState; const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; From 25ac099c966beb704087d56340a4e1a9fefd7e68 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 22:59:14 +1100 Subject: [PATCH 09/14] Add LAST_DAG_RUN_STATE to SearchParamsKeys and update filters --- airflow/ui/src/constants/searchParams.ts | 2 +- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 4 ++-- airflow/ui/src/pages/DagsList/DagsList.tsx | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/airflow/ui/src/constants/searchParams.ts b/airflow/ui/src/constants/searchParams.ts index 3fad2386f2c..8fc1382015c 100644 --- a/airflow/ui/src/constants/searchParams.ts +++ b/airflow/ui/src/constants/searchParams.ts @@ -17,9 +17,9 @@ * under the License. */ export enum SearchParamsKeys { + LAST_DAG_RUN_STATE = "last_dag_run_state", LIMIT = "limit", NAME_PATTERN = "name_pattern", - LAST_DAG_RUN_STATE = "last_dag_run_state", OFFSET = "offset", PAUSED = "paused", SORT = "sort" diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index f0a238f10c0..71114baac12 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -27,8 +27,8 @@ import { QuickFilterButton } from "src/components/QuickFilterButton"; import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; const { - PAUSED: PAUSED_PARAM, - LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM + LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, + PAUSED: PAUSED_PARAM }: SearchParamsKeysType = SearchParamsKeys; export const DagsFilters = () => { diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 33ac3f72e57..4b611276309 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -92,9 +92,9 @@ const columns: Array> = [ ]; const { + LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM, - PAUSED: PAUSED_PARAM, - LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM + PAUSED: PAUSED_PARAM }: SearchParamsKeysType = SearchParamsKeys; const cardDef: CardDef = { From 5c6cdf32379ae3c33347df99ff6444673f5678a4 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 22:59:44 +1100 Subject: [PATCH 10/14] Fix missing change for add SearchBar component by removing forwardRef and adding debounced search logic. --- airflow/ui/src/components/SearchBar.tsx | 70 ++++++++++++++++--------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index a7deaaffb56..1381d1e08ed 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,40 +16,60 @@ * specific language governing permissions and limitations * under the License. */ -import { forwardRef } from "react"; +import { ChangeEvent } from "react"; import { Button, - type ButtonProps, Input, InputGroup, - type InputGroupProps, InputLeftElement, - type InputProps, InputRightElement, + type ButtonProps, + type InputGroupProps, + type InputProps, } from "@chakra-ui/react"; import { FiSearch } from "react-icons/fi"; +import { useDebouncedCallback } from "use-debounce"; + +const debounceDelay = 200; -export const SearchBar = forwardRef(({ buttonProps, groupProps, inputProps }, ref) => ( - - - - - - - - - -)); +}) => { + + const handleSearchChange = useDebouncedCallback( + (event: ChangeEvent) => inputProps?.onChange?.(event), + debounceDelay + ); + + return ( + + + + + + + + + + ); +}; From aff284072b3d5ef1819610bc2abcf36d79cfa7f6 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Thu, 10 Oct 2024 23:10:05 +1100 Subject: [PATCH 11/14] minor change for SearchBar and DagsFilters components --- airflow/ui/src/components/SearchBar.tsx | 8 ++++---- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index 1381d1e08ed..a52185e4088 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { ChangeEvent } from "react"; +import type { ChangeEvent } from "react"; import { Button, Input, @@ -37,9 +37,9 @@ export const SearchBar = ({ groupProps, inputProps, }: { - buttonProps?: ButtonProps; - groupProps?: InputGroupProps; - inputProps?: InputProps; + readonly buttonProps?: ButtonProps; + readonly groupProps?: InputGroupProps; + readonly inputProps?: InputProps; }) => { const handleSearchChange = useDebouncedCallback( diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 71114baac12..db53216683a 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information From d8144639d629b8ca0011c36b80d7010bea7bb92d Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Fri, 11 Oct 2024 21:33:35 +1100 Subject: [PATCH 12/14] Optimize imports and improve formatting across components --- .../src/components/DataTable/searchParams.ts | 11 ++++++-- airflow/ui/src/components/SearchBar.tsx | 5 ++-- airflow/ui/src/constants/searchParams.ts | 7 +++-- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 8 ++++-- airflow/ui/src/pages/DagsList/DagsList.tsx | 28 ++++++++++++++----- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/airflow/ui/src/components/DataTable/searchParams.ts b/airflow/ui/src/components/DataTable/searchParams.ts index a85cfbe040b..39001b097f3 100644 --- a/airflow/ui/src/components/DataTable/searchParams.ts +++ b/airflow/ui/src/components/DataTable/searchParams.ts @@ -17,14 +17,19 @@ * under the License. */ import type { SortingState } from "@tanstack/react-table"; + +import { + SearchParamsKeys, + type SearchParamsKeysType, +} from "src/constants/searchParams"; + import type { TableState } from "./types"; -import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; const { LIMIT: LIMIT_PARAM, OFFSET: OFFSET_PARAM, - SORT: SORT_PARAM -} : SearchParamsKeysType = SearchParamsKeys; + SORT: SORT_PARAM, +}: SearchParamsKeysType = SearchParamsKeys; export const stateToSearchParams = ( state: TableState, diff --git a/airflow/ui/src/components/SearchBar.tsx b/airflow/ui/src/components/SearchBar.tsx index a52185e4088..ad50a65b431 100644 --- a/airflow/ui/src/components/SearchBar.tsx +++ b/airflow/ui/src/components/SearchBar.tsx @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import type { ChangeEvent } from "react"; import { Button, Input, @@ -27,6 +26,7 @@ import { type InputGroupProps, type InputProps, } from "@chakra-ui/react"; +import type { ChangeEvent } from "react"; import { FiSearch } from "react-icons/fi"; import { useDebouncedCallback } from "use-debounce"; @@ -41,10 +41,9 @@ export const SearchBar = ({ readonly groupProps?: InputGroupProps; readonly inputProps?: InputProps; }) => { - const handleSearchChange = useDebouncedCallback( (event: ChangeEvent) => inputProps?.onChange?.(event), - debounceDelay + debounceDelay, ); return ( diff --git a/airflow/ui/src/constants/searchParams.ts b/airflow/ui/src/constants/searchParams.ts index 8fc1382015c..893a4461bff 100644 --- a/airflow/ui/src/constants/searchParams.ts +++ b/airflow/ui/src/constants/searchParams.ts @@ -22,7 +22,10 @@ export enum SearchParamsKeys { NAME_PATTERN = "name_pattern", OFFSET = "offset", PAUSED = "paused", - SORT = "sort" + SORT = "sort", } -export type SearchParamsKeysType = Record; +export type SearchParamsKeysType = Record< + keyof typeof SearchParamsKeys, + string +>; diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index db53216683a..3d507ace365 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -23,12 +23,14 @@ import { useSearchParams } from "react-router-dom"; import { useTableURLState } from "src/components/DataTable/useTableUrlState"; import { QuickFilterButton } from "src/components/QuickFilterButton"; - -import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; +import { + SearchParamsKeys, + type SearchParamsKeysType, +} from "src/constants/searchParams"; const { LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, - PAUSED: PAUSED_PARAM + PAUSED: PAUSED_PARAM, }: SearchParamsKeysType = SearchParamsKeys; export const DagsFilters = () => { diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 4b611276309..f5f36bd2484 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -25,7 +25,12 @@ import { VStack, } from "@chakra-ui/react"; import type { ColumnDef } from "@tanstack/react-table"; -import { type ChangeEvent, type ChangeEventHandler, useCallback, useState } from "react"; +import { + type ChangeEvent, + type ChangeEventHandler, + useCallback, + useState, +} from "react"; import { useSearchParams } from "react-router-dom"; import { useDagServiceGetDags } from "openapi/queries"; @@ -37,8 +42,11 @@ import { useTableURLState } from "src/components/DataTable/useTableUrlState"; import { ErrorAlert } from "src/components/ErrorAlert"; import { SearchBar } from "src/components/SearchBar"; import { TogglePause } from "src/components/TogglePause"; +import { + SearchParamsKeys, + type SearchParamsKeysType, +} from "src/constants/searchParams"; import { pluralize } from "src/utils/pluralize"; -import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams"; import { DagCard } from "./DagCard"; import { DagsFilters } from "./DagsFilters"; @@ -94,7 +102,7 @@ const columns: Array> = [ const { LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM, - PAUSED: PAUSED_PARAM + PAUSED: PAUSED_PARAM, }: SearchParamsKeysType = SearchParamsKeys; const cardDef: CardDef = { @@ -109,17 +117,23 @@ export const DagsList = () => { const [display, setDisplay] = useState<"card" | "table">("card"); const showPaused = searchParams.get(PAUSED_PARAM); - const lastDagRunState = searchParams.get(LAST_DAG_RUN_STATE_PARAM) as DagRunState; + const lastDagRunState = searchParams.get( + LAST_DAG_RUN_STATE_PARAM, + ) as DagRunState; const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; - const [dagDisplayNamePattern, setDagDisplayNamePattern] = useState(searchParams.get(NAME_PATTERN_PARAM) ?? undefined); + const [dagDisplayNamePattern, setDagDisplayNamePattern] = useState( + searchParams.get(NAME_PATTERN_PARAM) ?? undefined, + ); // TODO: update API to accept multiple orderBy params const [sort] = sorting; const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : undefined; - const handleSearchChange = ({ target: { value } }: ChangeEvent) => { + const handleSearchChange = ({ + target: { value }, + }: ChangeEvent) => { if (value) { searchParams.set(NAME_PATTERN_PARAM, value); } else { @@ -164,7 +178,7 @@ export const DagsList = () => { buttonProps={{ isDisabled: true }} inputProps={{ defaultValue: dagDisplayNamePattern, - onChange: handleSearchChange + onChange: handleSearchChange, }} /> From afaf1d608b6cf0e05b087befd0015487ae186486 Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Mon, 14 Oct 2024 20:50:24 +1100 Subject: [PATCH 13/14] refactor: move query options from autogenerated useDagServiceGetDags to DagsList. --- airflow/ui/openapi-gen/queries/queries.ts | 4 ---- airflow/ui/src/pages/DagsList/DagsList.tsx | 20 ++++++++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index 6a566a00550..01e919cce53 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -152,10 +152,6 @@ export const useDagServiceGetDags = < paused, tags, }) as TData, - staleTime: 5 * 60 * 1000, - refetchOnWindowFocus: false, - refetchOnMount: true, - refetchOnReconnect: false, ...options, }); /** diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index f5f36bd2484..136c645ef57 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -152,12 +152,20 @@ export const DagsList = () => { dagDisplayNamePattern: Boolean(dagDisplayNamePattern) ? `%${dagDisplayNamePattern}%` : undefined, - limit: pagination.pageSize, - offset: pagination.pageIndex * pagination.pageSize, - onlyActive: true, - orderBy, - paused: showPaused === null ? undefined : showPaused === "true", - }, [dagDisplayNamePattern, showPaused]); + limit: pagination.pageSize, + offset: pagination.pageIndex * pagination.pageSize, + onlyActive: true, + orderBy, + paused: showPaused === null ? undefined : showPaused === "true", + }, + [dagDisplayNamePattern, showPaused], + { + refetchOnMount: true, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + staleTime: 5 * 60 * 1000, + }, + ); const handleSortChange = useCallback>( ({ currentTarget: { value } }) => { From 78153aaf44689098cd70416f745086206bddf54b Mon Sep 17 00:00:00 2001 From: Luyang Liu Date: Mon, 14 Oct 2024 21:15:20 +1100 Subject: [PATCH 14/14] Fix formatting. --- airflow/ui/src/pages/DagsList/DagsList.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 136c645ef57..623b8a3b4ba 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -147,11 +147,12 @@ export const DagsList = () => { setDagDisplayNamePattern(value); }; - const { data, error, isFetching, isLoading } = useDagServiceGetDags({ - lastDagRunState, - dagDisplayNamePattern: Boolean(dagDisplayNamePattern) + const { data, error, isFetching, isLoading } = useDagServiceGetDags( + { + dagDisplayNamePattern: Boolean(dagDisplayNamePattern) ? `%${dagDisplayNamePattern}%` : undefined, + lastDagRunState, limit: pagination.pageSize, offset: pagination.pageIndex * pagination.pageSize, onlyActive: true,