This is an automated email from the ASF dual-hosted git repository.
choo121600 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 22afa85809d Remove most accordions from forms (#74422)
22afa85809d is described below
commit 22afa85809d40664471a017a35a067cba49c934e
Author: Brent Bovenzi <[email protected]>
AuthorDate: Thu Oct 8 02:21:32 2026 -0400
Remove most accordions from forms (#74422)
---
.../ui/public/i18n/locales/ar/components.json | 1 -
.../ui/public/i18n/locales/ca/components.json | 1 -
.../ui/public/i18n/locales/de/components.json | 1 -
.../ui/public/i18n/locales/el/components.json | 1 -
.../ui/public/i18n/locales/en/components.json | 1 -
.../ui/public/i18n/locales/es/components.json | 1 -
.../ui/public/i18n/locales/fr/components.json | 1 -
.../ui/public/i18n/locales/he/components.json | 1 -
.../ui/public/i18n/locales/hi/components.json | 1 -
.../ui/public/i18n/locales/hu/components.json | 1 -
.../ui/public/i18n/locales/it/components.json | 1 -
.../ui/public/i18n/locales/ja/components.json | 1 -
.../ui/public/i18n/locales/ko/components.json | 1 -
.../ui/public/i18n/locales/nl/components.json | 1 -
.../ui/public/i18n/locales/pl/components.json | 1 -
.../ui/public/i18n/locales/pt/components.json | 1 -
.../ui/public/i18n/locales/ru/components.json | 1 -
.../ui/public/i18n/locales/th/components.json | 1 -
.../ui/public/i18n/locales/tr/components.json | 1 -
.../ui/public/i18n/locales/zh-CN/components.json | 1 -
.../ui/public/i18n/locales/zh-TW/components.json | 1 -
.../components/ActionAccordion/ActionAccordion.tsx | 140 +++++++-----------
.../src/airflow/ui/src/components/ConfigForm.tsx | 71 +++++----
.../src/components/FlexibleForm/FlexibleForm.tsx | 163 +++++----------------
.../TriggerDag/TriggerDAGAdvancedOptions.tsx | 12 +-
.../components/TriggerDag/TriggerDAGForm.test.tsx | 14 +-
.../src/pages/Connections/ConnectionForm.test.tsx | 16 +-
.../ui/src/pages/Connections/ConnectionForm.tsx | 84 +++++------
.../pages/Connections/ConnectionStandardFields.tsx | 2 +-
.../pages/HITLTaskInstances/HITLResponseForm.tsx | 1 -
30 files changed, 181 insertions(+), 343 deletions(-)
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
index 824f5522217..a8ae01cff8b 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
@@ -52,7 +52,6 @@
},
"close": "إغلاق",
"configForm": {
- "advancedOptions": "خيارات متقدمة",
"configJson": "تكوين JSON",
"invalidJson": "تنسيق JSON غير صالح: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ca/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/ca/components.json
index ad29c45cf63..41830dab059 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ca/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ca/components.json
@@ -52,7 +52,6 @@
},
"close": "Tancar",
"configForm": {
- "advancedOptions": "Opcions avançades",
"configJson": "Configuració JSON",
"invalidJson": "Format JSON no vàlid: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json
index 1d16a2e92d1..d7cd7a3d9c2 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json
@@ -52,7 +52,6 @@
},
"close": "Schließen",
"configForm": {
- "advancedOptions": "Erweiterte Optionen",
"configJson": "JSON der Konfiguration",
"invalidJson": "Ungültiges JSON Format: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/el/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/el/components.json
index 8e460d27ec1..fcbb839d761 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/el/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/el/components.json
@@ -41,7 +41,6 @@
},
"close": "Κλείσιμο",
"configForm": {
- "advancedOptions": "Προχωρημένες Επιλογές",
"configJson": "Ρυθμίσεις JSON",
"invalidJson": "Μη έγκυρη μορφή JSON: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/en/components.json
index 53fa5e0b261..166cb001e99 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/en/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/components.json
@@ -52,7 +52,6 @@
},
"close": "Close",
"configForm": {
- "advancedOptions": "Advanced Options",
"configJson": "Configuration JSON",
"invalidJson": "Invalid JSON format: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
index 3719117068d..10dc6289bb4 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
@@ -52,7 +52,6 @@
},
"close": "Cerrar",
"configForm": {
- "advancedOptions": "Opciones Avanzadas",
"configJson": "Configuración JSON",
"invalidJson": "Formato JSON inválido: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json
index 3f225bb4426..24735e62c66 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json
@@ -54,7 +54,6 @@
},
"close": "Fermer",
"configForm": {
- "advancedOptions": "Options avancées",
"configJson": "Configuration JSON",
"invalidJson": "Format JSON invalide : {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
index 3557c62b95e..8c6512f7dee 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
@@ -42,7 +42,6 @@
},
"close": "סגור",
"configForm": {
- "advancedOptions": "אפשרויות מתקדמות",
"configJson": "הגדרות JSON",
"invalidJson": "מבנה ה-JSON אינו תקין: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
index 6bf4842b87d..7dcc757cbb1 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
@@ -41,7 +41,6 @@
},
"close": "बंद करें",
"configForm": {
- "advancedOptions": "उन्नत विकल्प",
"configJson": "विन्यास JSON",
"invalidJson": "अमान्य JSON प्रारूप: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
index 37492be488c..a94e63c0c9d 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
@@ -41,7 +41,6 @@
},
"close": "Bezárás",
"configForm": {
- "advancedOptions": "Speciális beállítások",
"configJson": "Konfiguráció JSON",
"invalidJson": "Érvénytelen JSON formátum: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
index 1b502a0243b..3bca1603286 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
@@ -39,7 +39,6 @@
},
"close": "Chiudi",
"configForm": {
- "advancedOptions": "Opzioni Avanzate",
"configJson": "Configurazione JSON",
"invalidJson": "Formato JSON non valido: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ja/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/ja/components.json
index db075c8704f..202a3513395 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ja/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ja/components.json
@@ -37,7 +37,6 @@
},
"close": "閉じる",
"configForm": {
- "advancedOptions": "詳細設定",
"configJson": "JSON の設定",
"invalidJson": "無効な JSON 形式: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json
index a3bf26e53e2..fd033ffa0e4 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json
@@ -52,7 +52,6 @@
},
"close": "닫기",
"configForm": {
- "advancedOptions": "고급 옵션",
"configJson": "구성 JSON",
"invalidJson": "잘못된 JSON 형식: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
index db5b5f9b10e..7f8d3320a84 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
@@ -41,7 +41,6 @@
},
"close": "Sluiten",
"configForm": {
- "advancedOptions": "Geavanceerde opties",
"configJson": "Configuratie JSON",
"invalidJson": "Ongeldig JSON formaat: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json
index 35bbf943f4f..c2bd078a7d1 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json
@@ -56,7 +56,6 @@
},
"close": "Zamknij",
"configForm": {
- "advancedOptions": "Zaawansowane opcje",
"configJson": "Konfiguracja JSON",
"invalidJson": "Nieprawidłowy format JSON: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
index e952b5a62de..da5cf1e7985 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
@@ -40,7 +40,6 @@
},
"close": "Fechar",
"configForm": {
- "advancedOptions": "Opções Avançadas",
"configJson": "Configuração JSON",
"invalidJson": "Formato JSON inválido: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ru/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/ru/components.json
index c53b27bc723..2bdc71f6ebf 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ru/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ru/components.json
@@ -43,7 +43,6 @@
},
"close": "Закрыть",
"configForm": {
- "advancedOptions": "Расширенные параметры",
"configJson": "Конфигурация JSON",
"invalidJson": "Некорректный формат JSON: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/th/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/th/components.json
index d5c04cda8ba..a595296d152 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/th/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/th/components.json
@@ -37,7 +37,6 @@
},
"close": "ปิด",
"configForm": {
- "advancedOptions": "ตัวเลือกขั้นสูง",
"configJson": "การตั้งค่า JSON",
"invalidJson": "รูปแบบ JSON ไม่ถูกต้อง: {{errorMessage}}"
},
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
index d2db8b1736b..c92f6f7a4dd 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
@@ -41,7 +41,6 @@
},
"close": "Kapat",
"configForm": {
- "advancedOptions": "Gelişmiş Seçenekler",
"configJson": "Yapılandırma JSON",
"invalidJson": "Geçersiz JSON formatı: {{errorMessage}}"
},
diff --git
a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
index e87b2f58988..b42fbb9bfbd 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
@@ -52,7 +52,6 @@
},
"close": "关闭",
"configForm": {
- "advancedOptions": "高级选项",
"configJson": "配置 JSON",
"invalidJson": "无效的 JSON 格式:{{errorMessage}}"
},
diff --git
a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json
index 2f554e05e8e..68081b0bc55 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json
@@ -52,7 +52,6 @@
},
"close": "關閉",
"configForm": {
- "advancedOptions": "進階選項",
"configJson": "設定 JSON",
"invalidJson": "無效的 JSON 格式: {{errorMessage}}"
},
diff --git
a/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
b/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
index 768b148325f..0e4010b7d69 100644
---
a/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
+++
b/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
@@ -16,9 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import type { ChangeEvent } from "react";
-
-import { Box, Editable, Text, VStack } from "@chakra-ui/react";
+import { Box, Field, Heading, Stack, Text, VStack } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import type {
@@ -29,7 +27,7 @@ import type {
import { Accordion } from "src/system-components";
-import ReactMarkdown from "src/components/ReactMarkdown";
+import EditableMarkdown from "src/components/TriggerDag/EditableMarkdown";
import { formatNumber } from "src/utils";
@@ -97,91 +95,61 @@ const ActionAccordion = ({ affectedTasks, groupByRunId =
false, note, selection,
const shouldGroup = groupByRunId && runGroups !== undefined &&
runGroups.size > 1;
return (
- <Accordion.Root
- collapsible
- defaultValue={showTaskSection ? ["tasks"] : ["note"]}
- multiple={false}
- variant="enclosed"
- >
+ <VStack align="stretch" gap={4}>
{showTaskSection ? (
- <Accordion.Item key="tasks" value="tasks">
- <Accordion.ItemTrigger>
- <Text fontWeight="bold">
- {translate("dags:runAndTaskActions.affectedTasks.title", {
- count: affectedTasks.total_entries ?? 0,
- })}
- </Text>
- </Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <Box maxH="400px" overflowY="scroll">
- {shouldGroup ? (
- <Accordion.Root collapsible multiple variant="plain">
- {[...runGroups.entries()].map(([runId, tis]) => (
- <Accordion.Item key={runId} value={runId}>
- <Accordion.ItemTrigger px={2} py={1}>
- <Text fontSize="sm" fontWeight="semibold">
- {translate("runId")}: {runId}{" "}
- <Text as="span" color="fg.subtle"
fontWeight="normal">
- ({formatNumber(tis.length, i18n.language)})
- </Text>
+ <Box>
+ <Heading mb={2} size="lg">
+ {translate("dags:runAndTaskActions.affectedTasks.title", {
+ count: affectedTasks.total_entries ?? 0,
+ })}
+ </Heading>
+ <Box borderRadius="md" borderWidth={1} maxH="400px" overflowY="auto">
+ {shouldGroup ? (
+ <Accordion.Root collapsible defaultValue={[...runGroups.keys()]}
multiple variant="plain">
+ {[...runGroups.entries()].map(([runId, tis]) => (
+ <Accordion.Item key={runId} value={runId}>
+ <Accordion.ItemTrigger px={2} py={1}>
+ <Text fontSize="sm" fontWeight="semibold">
+ {translate("runId")}: {runId}{" "}
+ <Text as="span" color="fg.subtle" fontWeight="normal">
+ ({formatNumber(tis.length, i18n.language)})
</Text>
- </Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <TasksTable
-
noRowsMessage={translate("dags:runAndTaskActions.affectedTasks.noItemsFound")}
- selection={selection}
- tasks={tis}
- />
- </Accordion.ItemContent>
- </Accordion.Item>
- ))}
- </Accordion.Root>
- ) : (
- <TasksTable
-
noRowsMessage={translate("dags:runAndTaskActions.affectedTasks.noItemsFound")}
- selection={selection}
- tasks={affectedTasks.task_instances}
- />
- )}
- </Box>
- </Accordion.ItemContent>
- </Accordion.Item>
+ </Text>
+ </Accordion.ItemTrigger>
+ <Accordion.ItemContent>
+ <TasksTable
+
noRowsMessage={translate("dags:runAndTaskActions.affectedTasks.noItemsFound")}
+ selection={selection}
+ tasks={tis}
+ />
+ </Accordion.ItemContent>
+ </Accordion.Item>
+ ))}
+ </Accordion.Root>
+ ) : (
+ <TasksTable
+
noRowsMessage={translate("dags:runAndTaskActions.affectedTasks.noItemsFound")}
+ selection={selection}
+ tasks={affectedTasks.task_instances}
+ />
+ )}
+ </Box>
+ </Box>
) : undefined}
- <Accordion.Item key="note" value="note">
- <Accordion.ItemTrigger>
- <Text fontWeight="bold">{translate("note.label")}</Text>
- </Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <Editable.Root
- onChange={(event: ChangeEvent<HTMLInputElement>) =>
setNote(event.target.value)}
- value={note ?? ""}
- >
- <Editable.Preview
- _hover={{ backgroundColor: "transparent" }}
- alignItems="flex-start"
- as={VStack}
- gap="0"
- height="200px"
- overflowY="auto"
- width="100%"
- >
- {Boolean(note) ? (
- <ReactMarkdown>{note}</ReactMarkdown>
- ) : (
- <Text color="fg.subtle">{translate("note.placeholder")}</Text>
- )}
- </Editable.Preview>
- <Editable.Textarea
- data-testid="notes-input"
- height="200px"
- overflowY="auto"
- placeholder={translate("note.placeholder")}
- resize="none"
- />
- </Editable.Root>
- </Accordion.ItemContent>
- </Accordion.Item>
- </Accordion.Root>
+ <Field.Root orientation="horizontal">
+ <Stack>
+ <Field.Label fontSize="md" style={{ flexBasis: "30%" }}>
+ {translate("note.label")}
+ </Field.Label>
+ </Stack>
+ <Stack css={{ flexBasis: "70%" }}>
+ <EditableMarkdown
+ field={{ onChange: setNote, value: note ?? "" }}
+ placeholder={translate("note.placeholder")}
+ />
+ </Stack>
+ </Field.Root>
+ </VStack>
);
};
diff --git a/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx
b/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx
index 1d92a01e3cc..753cea8f369 100644
--- a/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx
+++ b/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx
@@ -18,7 +18,7 @@
*/
import type { ReactNode, Dispatch, SetStateAction } from "react";
-import { Box, Field } from "@chakra-ui/react";
+import { Field, Stack, Text } from "@chakra-ui/react";
import { type Control, type FieldValues, type Path, Controller } from
"react-hook-form";
import { useTranslation } from "react-i18next";
@@ -84,48 +84,43 @@ const ConfigForm = <T extends FieldValues = FieldValues>({
};
return (
- <Accordion.Root
- collapsible
- data-testid="config-form"
- defaultValue={[flexibleFormDefaultSection]}
- mb={4}
- overflow="visible"
- size="lg"
- variant="enclosed"
- >
+ <Stack data-testid="config-form" gap={4} mb={4}>
<FlexibleForm
flexibleFormDefaultSection={flexibleFormDefaultSection}
initialParamsDict={initialParamsDict}
setError={setFormError}
/>
- <Accordion.Item key="advancedOptions" value="advancedOptions">
- <Accordion.ItemTrigger cursor="button">
- {translate("configForm.advancedOptions")}
- </Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <Box p={4}>
- {children}
- <Controller
- control={control}
- name={"conf" as Path<T>}
- render={({ field }) => (
- <Field.Root invalid={Boolean(errors.conf)} mt={6}>
- <Field.Label
fontSize="md">{translate("configForm.configJson")}</Field.Label>
- <JsonEditor
- onBlur={() => {
- field.onChange(validateAndPrettifyJson(field.value));
- }}
- onChange={field.onChange}
- value={field.value}
- />
- {Boolean(errors.conf) ?
<Field.ErrorText>{errors.conf}</Field.ErrorText> : undefined}
- </Field.Root>
- )}
- />
- </Box>
- </Accordion.ItemContent>
- </Accordion.Item>
- </Accordion.Root>
+ <Stack gap={4}>
+ {children}
+ <Accordion.Root collapsible overflow="visible" size="lg"
variant="enclosed">
+ <Accordion.Item value="configJson">
+ <Accordion.ItemTrigger cursor="button">
+ <Text color={Boolean(errors.conf) ? "fg.error" : undefined}>
+ {translate("configForm.configJson")}
+ </Text>
+ </Accordion.ItemTrigger>
+ <Accordion.ItemContent>
+ <Controller
+ control={control}
+ name={"conf" as Path<T>}
+ render={({ field }) => (
+ <Field.Root invalid={Boolean(errors.conf)}>
+ <JsonEditor
+ onBlur={() => {
+ field.onChange(validateAndPrettifyJson(field.value));
+ }}
+ onChange={field.onChange}
+ value={field.value}
+ />
+ {Boolean(errors.conf) ?
<Field.ErrorText>{errors.conf}</Field.ErrorText> : undefined}
+ </Field.Root>
+ )}
+ />
+ </Accordion.ItemContent>
+ </Accordion.Item>
+ </Accordion.Root>
+ </Stack>
+ </Stack>
);
};
diff --git
a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FlexibleForm.tsx
b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FlexibleForm.tsx
index dcfab434ab4..e9c197445fe 100644
--- a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FlexibleForm.tsx
+++ b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FlexibleForm.tsx
@@ -18,11 +18,9 @@
*/
import { useEffect, useState, type ReactNode } from "react";
-import { Icon, Stack, StackSeparator, Text } from "@chakra-ui/react";
+import { Heading, Icon, Stack, StackSeparator, Text } from "@chakra-ui/react";
import { MdError } from "react-icons/md";
-import { Accordion } from "src/system-components";
-
import type { ParamsSpec, ParamSpec } from "src/queries/useDagParams";
import { useParamStore } from "src/queries/useParamStore";
@@ -40,14 +38,14 @@ const FlatSection = ({
readonly title: string;
}) => (
<Stack gap={2}>
- <Text color={hasError ? "fg.error" : undefined} fontWeight="medium">
+ <Heading color={hasError ? "fg.error" : undefined} size="lg">
{title}
{hasError ? (
<Icon color="fg.error" margin="-1" ml={1}>
<MdError />
</Icon>
) : undefined}
- </Text>
+ </Heading>
{children}
</Stack>
);
@@ -78,7 +76,6 @@ export type FlexibleFormProps = {
readonly isHITL?: boolean;
readonly key?: string;
readonly namespace?: string;
- readonly noAccordion?: boolean;
readonly setError: (error: boolean) => void;
readonly subHeader?: string;
};
@@ -90,7 +87,6 @@ export const FlexibleForm = ({
initialParamsDict,
isHITL,
namespace = "default",
- noAccordion,
setError,
subHeader,
}: FlexibleFormProps) => {
@@ -137,132 +133,51 @@ export const FlexibleForm = ({
setError(Boolean(error) || newSectionError.size > 0);
};
- if (noAccordion) {
- return Object.keys(params).length > 0 ? (
- <>
- {Object.entries(params).map(([, secParam]) => {
- const currentSection = secParam.schema.section ??
flexibleFormDefaultSection;
-
- if (processedSections.has(currentSection)) {
- return undefined;
- }
- processedSections.set(currentSection, true);
-
- return (
- <FlatSection
- hasError={Boolean(sectionError.get(currentSection))}
- key={currentSection}
- title={currentSection}
- >
- {Boolean(subHeader) ? (
- <Text color="fg.muted" fontSize="xs">
- {subHeader}
- </Text>
- ) : undefined}
- <Stack separator={<StackSeparator py={2} />}>
- {Boolean(flexFormDescription) ? (
- <ReactMarkdown>{flexFormDescription}</ReactMarkdown>
- ) : undefined}
- {Object.entries(params)
- .filter(
- ([, param]) =>
- param.schema.section === currentSection ||
- (currentSection === flexibleFormDefaultSection &&
!Boolean(param.schema.section)),
- )
- .map(([name]) => (
- <Row key={name} name={name} namespace={namespace}
onUpdate={onUpdate} />
- ))}
- </Stack>
- </FlatSection>
- );
- })}
- </>
- ) : isHITL ? (
- <FlatSection
- hasError={Boolean(sectionError.get(flexibleFormDefaultSection))}
- title={flexibleFormDefaultSection}
- >
- {Boolean(flexFormDescription) ?
<ReactMarkdown>{flexFormDescription}</ReactMarkdown> : undefined}
- </FlatSection>
- ) : undefined;
- }
-
return Object.keys(params).length > 0 ? (
- Object.entries(params).map(([, secParam]) => {
- const currentSection = secParam.schema.section ??
flexibleFormDefaultSection;
+ <>
+ {Object.entries(params).map(([, secParam]) => {
+ const currentSection = secParam.schema.section ??
flexibleFormDefaultSection;
- if (processedSections.has(currentSection)) {
- return undefined;
- } else {
+ if (processedSections.has(currentSection)) {
+ return undefined;
+ }
processedSections.set(currentSection, true);
return (
- <Accordion.Item
- // We need to make the item content overflow visible for dropdowns
to work, but directly applying the style does not work
- css={{
- "& > div:nth-of-type(1)": {
- overflow: "visible",
- },
- }}
+ <FlatSection
+ hasError={Boolean(sectionError.get(currentSection))}
key={currentSection}
- value={currentSection}
+ title={currentSection}
>
- <Accordion.ItemTrigger cursor="button">
- <Text color={sectionError.get(currentSection) ? "fg.error" :
undefined}>{currentSection}</Text>
- {sectionError.get(currentSection) ? (
- <Icon color="fg.error" margin="-1">
- <MdError />
- </Icon>
+ {Boolean(subHeader) ? (
+ <Text color="fg.muted" fontSize="xs">
+ {subHeader}
+ </Text>
+ ) : undefined}
+ <Stack separator={<StackSeparator py={2} />}>
+ {Boolean(flexFormDescription) ? (
+ <ReactMarkdown>{flexFormDescription}</ReactMarkdown>
) : undefined}
- </Accordion.ItemTrigger>
-
- <Accordion.ItemContent pt={0}>
- <Accordion.ItemBody>
- {Boolean(subHeader) ? (
- <Text color="fg.muted" fontSize="xs" mb={2}>
- {subHeader}
- </Text>
- ) : undefined}
- <Stack separator={<StackSeparator py={2} />}>
- {Boolean(flexFormDescription) ? (
- <ReactMarkdown>{flexFormDescription}</ReactMarkdown>
- ) : undefined}
- {Object.entries(params)
- .filter(
- ([, param]) =>
- param.schema.section === currentSection ||
- (currentSection === flexibleFormDefaultSection &&
!Boolean(param.schema.section)),
- )
- .map(([name]) => (
- <Row key={name} name={name} namespace={namespace}
onUpdate={onUpdate} />
- ))}
- </Stack>
- </Accordion.ItemBody>
- </Accordion.ItemContent>
- </Accordion.Item>
+ {Object.entries(params)
+ .filter(
+ ([, param]) =>
+ param.schema.section === currentSection ||
+ (currentSection === flexibleFormDefaultSection &&
!Boolean(param.schema.section)),
+ )
+ .map(([name]) => (
+ <Row key={name} name={name} namespace={namespace}
onUpdate={onUpdate} />
+ ))}
+ </Stack>
+ </FlatSection>
);
- }
- })
+ })}
+ </>
) : isHITL ? (
- <Accordion.Item key={flexibleFormDefaultSection}
value={flexibleFormDefaultSection}>
- <Accordion.ItemTrigger cursor="button">
- <Text color={sectionError.get(flexibleFormDefaultSection) ? "fg.error"
: undefined}>
- {flexibleFormDefaultSection}
- </Text>
- {sectionError.get(flexibleFormDefaultSection) ? (
- <Icon color="fg.error" margin="-1">
- <MdError />
- </Icon>
- ) : undefined}
- </Accordion.ItemTrigger>
-
- <Accordion.ItemContent pt={0}>
- <Accordion.ItemBody>
- <Stack separator={<StackSeparator py={2} />}>
- {Boolean(flexFormDescription) ?
<ReactMarkdown>{flexFormDescription}</ReactMarkdown> : undefined}
- </Stack>
- </Accordion.ItemBody>
- </Accordion.ItemContent>
- </Accordion.Item>
+ <FlatSection
+ hasError={Boolean(sectionError.get(flexibleFormDefaultSection))}
+ title={flexibleFormDefaultSection}
+ >
+ {Boolean(flexFormDescription) ?
<ReactMarkdown>{flexFormDescription}</ReactMarkdown> : undefined}
+ </FlatSection>
) : undefined;
};
diff --git
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx
index d5512579093..d7eaa9e5bea 100644
---
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx
+++
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx
@@ -75,9 +75,15 @@ const TriggerDAGAdvancedOptions = ({ control, isPartitioned
}: TriggerDAGAdvance
control={control}
name="note"
render={({ field }) => (
- <Field.Root mt={6}>
- <Field.Label fontSize="md">{translate("note.dagRun")}</Field.Label>
- <EditableMarkdown field={field}
placeholder={translate("note.placeholder")} />
+ <Field.Root mt={6} orientation="horizontal">
+ <Stack>
+ <Field.Label fontSize="md" style={{ flexBasis: "30%" }}>
+ {translate("note.dagRun")}
+ </Field.Label>
+ </Stack>
+ <Stack css={{ flexBasis: "70%" }}>
+ <EditableMarkdown field={field}
placeholder={translate("note.placeholder")} />
+ </Stack>
</Field.Root>
)}
/>
diff --git
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
index ef2ad533a04..326fa529ca2 100644
---
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
+++
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
@@ -43,10 +43,7 @@ vi.mock("react-i18next", () => ({
useTranslation: () => ({
i18n: { language: "en" },
// eslint-disable-next-line id-length
- t: (translationKey: string) =>
- ({
- "configForm.advancedOptions": "Advanced Options",
- })[translationKey] ?? translationKey,
+ t: (translationKey: string) => translationKey,
}),
}));
@@ -184,8 +181,6 @@ describe("TriggerDAGForm", () => {
{ wrapper: Wrapper },
);
- fireEvent.click(screen.getByText("Advanced Options"));
-
await waitFor(() => {
const configJson = screen.getByLabelText("Configuration JSON");
@@ -197,7 +192,7 @@ describe("TriggerDAGForm", () => {
});
});
- it("syncs Advanced Options JSON after Run Parameters edits in prefilled
re-trigger mode", async () => {
+ it("syncs the Configuration JSON after Run Parameters edits in prefilled
re-trigger mode", async () => {
const { container } = render(
<TriggerDAGForm
dagId="example_params_trigger_ui"
@@ -229,7 +224,6 @@ describe("TriggerDAGForm", () => {
}
fireEvent.change(messageField, { target: { value: "Updated message" } });
- fireEvent.click(screen.getByText("Advanced Options"));
await waitFor(() => {
const configJson = screen.getByLabelText("Configuration JSON");
@@ -257,8 +251,6 @@ describe("TriggerDAGForm", () => {
{ wrapper: Wrapper },
);
- fireEvent.click(screen.getByText("Advanced Options"));
-
await waitFor(() => expect(screen.getByText("runId")).toBeInTheDocument());
expect(screen.queryByText("dagRun.partitionKey")).not.toBeInTheDocument();
});
@@ -278,8 +270,6 @@ describe("TriggerDAGForm", () => {
{ wrapper: Wrapper },
);
- fireEvent.click(screen.getByText("Advanced Options"));
-
await waitFor(() =>
expect(screen.getByText("dagRun.partitionKey")).toBeInTheDocument());
expect(screen.getByText("components:triggerDag.partitionKeyHelp")).toBeInTheDocument();
});
diff --git
a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.test.tsx
b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.test.tsx
index 7efdb4f370f..331ea443b35 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.test.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.test.tsx
@@ -93,29 +93,23 @@ describe("ConnectionForm", () => {
i18n.addResourceBundle("en", "admin", adminLocale, true, true);
});
- it("titles the provider fields section after the connection type and opens
it by default", () => {
+ it("titles the provider fields section after the connection type", () => {
mockUseConnectionTypeMeta.mockReturnValue(loadedMeta);
render(renderForm(), { wrapper: Wrapper });
- expect(screen.getByRole("button", { name: "Pydantic AI Fields"
})).toHaveAttribute(
- "aria-expanded",
- "true",
- );
- expect(screen.getByRole("button", { name: "Standard Fields"
})).toHaveAttribute("aria-expanded", "true");
+ expect(screen.getByRole("heading", { name: "Pydantic AI Fields"
})).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "Standard Fields"
})).toBeInTheDocument();
});
- it("keeps the saved extra and opens the section when hook metadata loads
after the form mounts", () => {
+ it("keeps the saved extra and shows the section when hook metadata loads
after the form mounts", () => {
mockUseConnectionTypeMeta.mockReturnValue(pendingMeta);
const { rerender } = render(renderForm(), { wrapper: Wrapper });
mockUseConnectionTypeMeta.mockReturnValue(loadedMeta);
rerender(renderForm());
- expect(screen.getByRole("button", { name: "Pydantic AI Fields"
})).toHaveAttribute(
- "aria-expanded",
- "true",
- );
+ expect(screen.getByRole("heading", { name: "Pydantic AI Fields"
})).toBeInTheDocument();
expect(document.querySelector<HTMLInputElement>("#element_model")).toHaveValue("openai:gpt-5");
});
});
diff --git
a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
index d1ad9354bac..54dc6be1dbb 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
@@ -18,7 +18,7 @@
*/
import { useEffect, useState } from "react";
-import { Input, Button, Box, Spacer, HStack, Field, Stack, VStack, Spinner }
from "@chakra-ui/react";
+import { Input, Button, Box, Spacer, HStack, Field, Heading, Stack, VStack,
Spinner } from "@chakra-ui/react";
import { Select } from "chakra-react-select";
import { useForm, Controller } from "react-hook-form";
import { useTranslation } from "react-i18next";
@@ -210,57 +210,49 @@ const ConnectionForm = ({
/>
{selectedConnType && !isMetaPending ? (
- <Accordion.Root
- collapsible
- defaultValue={["standardFields", connectionTypeFieldsSection]}
- key={selectedConnType}
- mb={4}
- mt={4}
- size="lg"
- variant="enclosed"
- >
- <Accordion.Item key="standardFields" value="standardFields">
-
<Accordion.ItemTrigger>{translate("connections.form.standardFields")}</Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <StandardFields control={control}
standardFields={standardFields} />
- </Accordion.ItemContent>
- </Accordion.Item>
+ <Stack gap={6} key={selectedConnType} mb={4} mt={4} width="100%">
+ <Stack gap={2}>
+ <Heading
size="lg">{translate("connections.form.standardFields")}</Heading>
+ <StandardFields control={control}
standardFields={standardFields} />
+ </Stack>
<FlexibleForm
flexibleFormDefaultSection={connectionTypeFieldsSection}
initialParamsDict={paramsDic}
setError={setFormErrors}
subHeader={isEditMode ?
translate("connections.form.helperTextForRedactedFields") : undefined}
/>
- <Accordion.Item key="extraJson" value="extraJson">
- <Accordion.ItemTrigger cursor="button">
- {translate("connections.form.extraFieldsJson")}
- </Accordion.ItemTrigger>
- <Accordion.ItemContent>
- <Controller
- control={control}
- name="extra"
- render={({ field }) => (
- <Field.Root invalid={Boolean(errors.conf)}>
- <JsonEditor
- onBlur={() => {
- field.onChange(validateAndPrettifyJson(field.value));
- field.onBlur();
- }}
- onChange={field.onChange}
- value={field.value}
- />
- {Boolean(errors.conf) ?
<Field.ErrorText>{errors.conf}</Field.ErrorText> : undefined}
- {isEditMode ? (
- <Field.HelperText>
-
{translate("connections.form.helperTextForRedactedFields")}
- </Field.HelperText>
- ) : undefined}
- </Field.Root>
- )}
- />
- </Accordion.ItemContent>
- </Accordion.Item>
- </Accordion.Root>
+ <Accordion.Root collapsible overflow="visible" size="lg"
variant="enclosed">
+ <Accordion.Item key="extraJson" value="extraJson">
+ <Accordion.ItemTrigger cursor="button">
+ {translate("connections.form.extraFieldsJson")}
+ </Accordion.ItemTrigger>
+ <Accordion.ItemContent>
+ <Controller
+ control={control}
+ name="extra"
+ render={({ field }) => (
+ <Field.Root invalid={Boolean(errors.conf)}>
+ <JsonEditor
+ onBlur={() => {
+
field.onChange(validateAndPrettifyJson(field.value));
+ field.onBlur();
+ }}
+ onChange={field.onChange}
+ value={field.value}
+ />
+ {Boolean(errors.conf) ?
<Field.ErrorText>{errors.conf}</Field.ErrorText> : undefined}
+ {isEditMode ? (
+ <Field.HelperText>
+
{translate("connections.form.helperTextForRedactedFields")}
+ </Field.HelperText>
+ ) : undefined}
+ </Field.Root>
+ )}
+ />
+ </Accordion.ItemContent>
+ </Accordion.Item>
+ </Accordion.Root>
+ </Stack>
) : undefined}
{multiTeamEnabled ? <TeamSelector control={control} /> : undefined}
diff --git
a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionStandardFields.tsx
b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionStandardFields.tsx
index f4408cdc149..313269a36f0 100644
---
a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionStandardFields.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionStandardFields.tsx
@@ -36,7 +36,7 @@ const StandardFields = ({ control, standardFields }:
StandardFieldsProps) => {
const [showPassword, setShowPassword] = useState(false);
return (
- <Stack pb={3} pl={3} pr={3}>
+ <Stack>
{Object.entries(standardFields).map(([key, fields]) => {
if (Boolean(fields.hidden)) {
return undefined;
diff --git
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
index bae3b02eba5..1e896b0955b 100644
---
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
@@ -125,7 +125,6 @@ export const HITLResponseForm = ({ hitlDetail, namespace =
"hitl", onResponded }
isHITL
key={hitlDetail.subject}
namespace={namespace}
- noAccordion
setError={setErrors}
/>
</Box>