From 7825418f8047ea49bd7780aad73342b207dfc56f Mon Sep 17 00:00:00 2001 From: josix Date: Wed, 23 Oct 2024 17:21:58 +0800 Subject: [PATCH 1/3] feat(pages/DagsList): add tags filter to dags list --- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 27 +++++++++++++++++-- airflow/ui/src/pages/DagsList/DagsList.tsx | 13 +++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 3d507ace365db..f0ce4be5dc64c 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -21,6 +21,7 @@ import { Select as ReactSelect } from "chakra-react-select"; import { useCallback } from "react"; import { useSearchParams } from "react-router-dom"; +import { useDagServiceGetDagTags } from "openapi/queries"; import { useTableURLState } from "src/components/DataTable/useTableUrlState"; import { QuickFilterButton } from "src/components/QuickFilterButton"; import { @@ -33,7 +34,11 @@ const { PAUSED: PAUSED_PARAM, }: SearchParamsKeysType = SearchParamsKeys; -export const DagsFilters = () => { +type DagsFiltersProps = { + readonly onTagsSelectChange: (tags: Array) => void; +}; + +export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { const [searchParams, setSearchParams] = useSearchParams(); const showPaused = searchParams.get(PAUSED_PARAM); @@ -43,6 +48,10 @@ export const DagsFilters = () => { const isFailed = state === "failed"; const isSuccess = state === "success"; + const { data } = useDagServiceGetDagTags({ + orderBy: "name", + }); + const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; @@ -133,7 +142,21 @@ export const DagsFilters = () => { - + "No tags found"} + onChange={(options) => { + onTagsSelectChange(options.map(({ value }) => value)); + }} + options={data?.tags.map((tag) => ({ + label: tag, + value: tag, + }))} + placeholder="Filter by tag" + /> ); }; diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index ad1b08fe87589..88aab74a020a7 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -120,6 +120,7 @@ const cardDef: CardDef = { export const DagsList = () => { const [searchParams, setSearchParams] = useSearchParams(); const [display, setDisplay] = useState<"card" | "table">("card"); + const [selectedTags, setSelectedTags] = useState>([]); const showPaused = searchParams.get(PAUSED_PARAM); const lastDagRunState = searchParams.get( @@ -163,8 +164,16 @@ export const DagsList = () => { onlyActive: true, orderBy, paused: showPaused === null ? undefined : showPaused === "true", + tags: selectedTags, }, - [dagDisplayNamePattern, showPaused, lastDagRunState, pagination, orderBy], + [ + dagDisplayNamePattern, + showPaused, + lastDagRunState, + pagination, + orderBy, + selectedTags, + ], { refetchOnMount: true, refetchOnReconnect: false, @@ -195,7 +204,7 @@ export const DagsList = () => { onChange: handleSearchChange, }} /> - + {pluralize("DAG", data?.total_entries)} From cfc8d334a6ea7c6ea76da6295b8bf23de59daaa0 Mon Sep 17 00:00:00 2001 From: Josix Date: Thu, 24 Oct 2024 00:58:43 +0800 Subject: [PATCH 2/3] Update airflow/ui/src/pages/DagsList/DagsFilters.tsx Co-authored-by: Brent Bovenzi --- airflow/ui/src/pages/DagsList/DagsFilters.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index f0ce4be5dc64c..6fd10bad6d712 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -144,7 +144,12 @@ export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { ({ + ...provided, + minWidth: 64, + }), + }} isClearable isMulti noOptionsMessage={() => "No tags found"} From f572891ac444063954c63385a1e005542170bc6d Mon Sep 17 00:00:00 2001 From: josix Date: Thu, 24 Oct 2024 02:15:53 +0800 Subject: [PATCH 3/3] fixup! feat(pages/DagsList): add tags filter to dags list --- airflow/ui/src/constants/searchParams.ts | 1 + airflow/ui/src/pages/DagsList/DagsFilters.tsx | 34 ++++++++++++++----- airflow/ui/src/pages/DagsList/DagsList.tsx | 5 +-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/airflow/ui/src/constants/searchParams.ts b/airflow/ui/src/constants/searchParams.ts index 893a4461bffe7..8ca5e0b4f19a9 100644 --- a/airflow/ui/src/constants/searchParams.ts +++ b/airflow/ui/src/constants/searchParams.ts @@ -23,6 +23,7 @@ export enum SearchParamsKeys { OFFSET = "offset", PAUSED = "paused", SORT = "sort", + TAGS = "tags", } export type SearchParamsKeysType = Record< diff --git a/airflow/ui/src/pages/DagsList/DagsFilters.tsx b/airflow/ui/src/pages/DagsList/DagsFilters.tsx index 6fd10bad6d712..f2b1baae8610f 100644 --- a/airflow/ui/src/pages/DagsList/DagsFilters.tsx +++ b/airflow/ui/src/pages/DagsList/DagsFilters.tsx @@ -18,6 +18,7 @@ */ import { HStack, Select, Text, Box } from "@chakra-ui/react"; import { Select as ReactSelect } from "chakra-react-select"; +import type { MultiValue } from "chakra-react-select"; import { useCallback } from "react"; import { useSearchParams } from "react-router-dom"; @@ -32,17 +33,15 @@ import { const { LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, PAUSED: PAUSED_PARAM, + TAGS: TAGS_PARAM, }: SearchParamsKeysType = SearchParamsKeys; -type DagsFiltersProps = { - readonly onTagsSelectChange: (tags: Array) => void; -}; - -export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { +export const DagsFilters = () => { const [searchParams, setSearchParams] = useSearchParams(); const showPaused = searchParams.get(PAUSED_PARAM); const state = searchParams.get(LAST_DAG_RUN_STATE_PARAM); + const selectedTags = searchParams.getAll(TAGS_PARAM); const isAll = state === null; const isRunning = state === "running"; const isFailed = state === "failed"; @@ -88,6 +87,21 @@ export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { }, [pagination, searchParams, setSearchParams, setTableURLState, sorting], ); + const handleSelectTagsChange = useCallback( + ( + tags: MultiValue<{ + label: string; + value: string; + }>, + ) => { + searchParams.delete(TAGS_PARAM); + tags.forEach(({ value }) => { + searchParams.append(TAGS_PARAM, value); + }); + setSearchParams(searchParams); + }, + [searchParams, setSearchParams], + ); return ( @@ -143,7 +157,7 @@ export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { ({ ...provided, @@ -153,14 +167,16 @@ export const DagsFilters = ({ onTagsSelectChange }: DagsFiltersProps) => { isClearable isMulti noOptionsMessage={() => "No tags found"} - onChange={(options) => { - onTagsSelectChange(options.map(({ value }) => value)); - }} + onChange={handleSelectTagsChange} options={data?.tags.map((tag) => ({ label: tag, value: tag, }))} placeholder="Filter by tag" + value={selectedTags.map((tag) => ({ + label: tag, + value: tag, + }))} /> ); diff --git a/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow/ui/src/pages/DagsList/DagsList.tsx index 88aab74a020a7..a2763bdac352e 100644 --- a/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -108,6 +108,7 @@ const { LAST_DAG_RUN_STATE: LAST_DAG_RUN_STATE_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM, PAUSED: PAUSED_PARAM, + TAGS: TAGS_PARAM, }: SearchParamsKeysType = SearchParamsKeys; const cardDef: CardDef = { @@ -120,12 +121,12 @@ const cardDef: CardDef = { export const DagsList = () => { const [searchParams, setSearchParams] = useSearchParams(); const [display, setDisplay] = useState<"card" | "table">("card"); - const [selectedTags, setSelectedTags] = useState>([]); const showPaused = searchParams.get(PAUSED_PARAM); const lastDagRunState = searchParams.get( LAST_DAG_RUN_STATE_PARAM, ) as DagRunState; + const selectedTags = searchParams.getAll(TAGS_PARAM); const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; @@ -204,7 +205,7 @@ export const DagsList = () => { onChange: handleSearchChange, }} /> - + {pluralize("DAG", data?.total_entries)}