Skip to content

Commit aa9c918

Browse files
bbovenzisanederchik
authored andcommitted
i18n - Translate Task Instance and Dag Run tables (apache#51222)
* Translate Task Instance and Dag Run tables * Fix error and action accordion
1 parent 3a9da72 commit aa9c918

24 files changed

+405
-220
lines changed

airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
*/
1919
import { Box, Editable, Text, VStack } from "@chakra-ui/react";
2020
import type { ChangeEvent } from "react";
21+
import { useTranslation } from "react-i18next";
2122

2223
import type { DAGRunResponse, TaskInstanceCollectionResponse } from "openapi/requests/types.gen";
2324
import ReactMarkdown from "src/components/ReactMarkdown";
2425
import { Accordion } from "src/components/ui";
2526

2627
import { DataTable } from "../DataTable";
27-
import { columns } from "./columns";
28+
import { getColumns } from "./columns";
2829

2930
type Props = {
3031
readonly affectedTasks?: TaskInstanceCollectionResponse;
@@ -36,6 +37,7 @@ type Props = {
3637
// TODO: Make a front-end only unconnected table component with client side ordering and pagination
3738
const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
3839
const showTaskSection = affectedTasks !== undefined;
40+
const { t: translate } = useTranslation();
3941

4042
return (
4143
<Accordion.Root
@@ -47,15 +49,20 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
4749
{showTaskSection ? (
4850
<Accordion.Item key="tasks" value="tasks">
4951
<Accordion.ItemTrigger>
50-
<Text fontWeight="bold">Affected Tasks: {affectedTasks.total_entries}</Text>
52+
<Text fontWeight="bold">
53+
{translate("dags:runAndTaskActions.clear.dialog.affectedTasks.title", {
54+
count: affectedTasks.total_entries,
55+
})}
56+
</Text>
5157
</Accordion.ItemTrigger>
5258
<Accordion.ItemContent>
5359
<Box maxH="400px" overflowY="scroll">
5460
<DataTable
55-
columns={columns}
61+
columns={getColumns(translate)}
5662
data={affectedTasks.task_instances}
5763
displayMode="table"
58-
modelName="Task Instance"
64+
modelName={translate("common:taskInstance_other")}
65+
noRowsMessage={translate("dags:runAndTaskActions.clear.dialog.affectedTasks.noItemsFound")}
5966
total={affectedTasks.total_entries}
6067
/>
6168
</Box>
@@ -64,7 +71,7 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
6471
) : undefined}
6572
<Accordion.Item key="note" value="note">
6673
<Accordion.ItemTrigger>
67-
<Text fontWeight="bold">Note</Text>
74+
<Text fontWeight="bold">{translate("dags:runAndTaskActions.clear.dialog.note.title")}</Text>
6875
</Accordion.ItemTrigger>
6976
<Accordion.ItemContent>
7077
<Editable.Root
@@ -83,14 +90,16 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
8390
{Boolean(note) ? (
8491
<ReactMarkdown>{note}</ReactMarkdown>
8592
) : (
86-
<Text color="fg.subtle">Add a note...</Text>
93+
<Text color="fg.subtle">
94+
{translate("dags:runAndTaskActions.clear.dialog.note.placeholder")}
95+
</Text>
8796
)}
8897
</Editable.Preview>
8998
<Editable.Textarea
9099
data-testid="notes-input"
91100
height="200px"
92101
overflowY="auto"
93-
placeholder="Add a note..."
102+
placeholder={translate("dags:runAndTaskActions.clear.dialog.note.placeholder")}
94103
resize="none"
95104
/>
96105
</Editable.Root>

airflow-core/src/airflow/ui/src/components/ActionAccordion/columns.tsx

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,50 +16,33 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
import { Link } from "@chakra-ui/react";
20-
import type { ColumnDef } from "@tanstack/react-table";
21-
import { Link as RouterLink } from "react-router-dom";
19+
import type { TFunction } from "i18next";
2220

2321
import type { TaskInstanceResponse } from "openapi/requests/types.gen";
22+
import type { MetaColumn } from "src/components/DataTable/types";
2423
import { StateBadge } from "src/components/StateBadge";
25-
import { Tooltip } from "src/components/ui";
26-
import { getTaskInstanceLink } from "src/utils/links";
27-
import { trimText } from "src/utils/trimTextFn";
2824

29-
export const columns: Array<ColumnDef<TaskInstanceResponse>> = [
25+
export const getColumns = (translate: TFunction): Array<MetaColumn<TaskInstanceResponse>> => [
3026
{
31-
accessorKey: "task_display_name",
32-
cell: ({ row: { original } }) => (
33-
<Tooltip content={original.task_display_name}>
34-
<Link asChild color="fg.info" fontWeight="bold" maxWidth="200px" overflow="hidden">
35-
<RouterLink to={getTaskInstanceLink(original)}>
36-
{trimText(original.task_display_name, 25).trimmedText}
37-
</RouterLink>
38-
</Link>
39-
</Tooltip>
40-
),
41-
enableSorting: false,
42-
header: "Task ID",
27+
accessorKey: "task_id",
28+
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.taskId"),
29+
size: 200,
4330
},
4431
{
4532
accessorKey: "state",
4633
cell: ({
4734
row: {
4835
original: { state },
4936
},
50-
}) => <StateBadge state={state}>{state}</StateBadge>,
51-
enableSorting: false,
52-
header: () => "State",
37+
}) => <StateBadge state={state}>{translate(`common:states.${state}`)}</StateBadge>,
38+
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.state"),
5339
},
5440
{
55-
accessorKey: "rendered_map_index",
56-
enableSorting: false,
57-
header: "Map Index",
41+
accessorKey: "map_index",
42+
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.mapIndex"),
5843
},
59-
6044
{
61-
accessorKey: "dag_run_id",
62-
enableSorting: false,
63-
header: "Run Id",
45+
accessorKey: "run_id",
46+
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.runId"),
6447
},
6548
];

airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunButton.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Box, useDisclosure } from "@chakra-ui/react";
2020
import { useHotkeys } from "react-hotkeys-hook";
21+
import { useTranslation } from "react-i18next";
2122
import { CgRedo } from "react-icons/cg";
2223

2324
import type { DAGRunResponse } from "openapi/requests/types.gen";
@@ -34,6 +35,7 @@ type Props = {
3435

3536
const ClearRunButton = ({ dagRun, isHotkeyEnabled = false, withText = true }: Props) => {
3637
const { onClose, onOpen, open } = useDisclosure();
38+
const { t: translate } = useTranslation();
3739

3840
useHotkeys(
3941
"shift+c",
@@ -44,13 +46,18 @@ const ClearRunButton = ({ dagRun, isHotkeyEnabled = false, withText = true }: Pr
4446
);
4547

4648
return (
47-
<Tooltip closeDelay={100} content="Press shift+c to clear" disabled={!isHotkeyEnabled} openDelay={100}>
49+
<Tooltip
50+
closeDelay={100}
51+
content={translate("dags:runAndTaskActions.clear.buttonTooltip")}
52+
disabled={!isHotkeyEnabled}
53+
openDelay={100}
54+
>
4855
<Box>
4956
<ActionButton
50-
actionName="Clear Dag Run"
57+
actionName={translate("dags:runAndTaskActions.clear.button", { type: "Run" })}
5158
icon={<CgRedo />}
5259
onClick={onOpen}
53-
text="Clear Run"
60+
text={translate("dags:runAndTaskActions.clear.button", { type: "Run" })}
5461
withText={withText}
5562
/>
5663

airflow-core/src/airflow/ui/src/components/Clear/Run/ClearRunDialog.tsx

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Flex, Heading, VStack } from "@chakra-ui/react";
2020
import { useState } from "react";
21+
import { useTranslation } from "react-i18next";
2122
import { CgRedo } from "react-icons/cg";
2223

2324
import type { DAGRunResponse } from "openapi/requests/types.gen";
@@ -35,46 +36,40 @@ type Props = {
3536
};
3637

3738
const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
38-
const [selectedOptions, setSelectedOptions] = useState<Array<string>>([]);
39-
4039
const dagId = dagRun.dag_id;
4140
const dagRunId = dagRun.dag_run_id;
41+
const { t: translate } = useTranslation();
42+
43+
const [note, setNote] = useState<string | null>(dagRun.note);
44+
const [selectedOptions, setSelectedOptions] = useState<Array<string>>(["existingTasks"]);
45+
const onlyFailed = selectedOptions.includes("onlyFailed");
46+
47+
const { data: affectedTasks = { task_instances: [], total_entries: 0 } } = useClearDagRunDryRun({
48+
dagId,
49+
dagRunId,
50+
requestBody: { only_failed: onlyFailed },
51+
});
4252

4353
const { isPending, mutate } = useClearDagRun({
4454
dagId,
4555
dagRunId,
4656
onSuccessConfirm: onClose,
4757
});
4858

49-
const onlyFailed = selectedOptions.includes("onlyFailed");
50-
51-
const [note, setNote] = useState<string | null>(dagRun.note);
52-
const { isPending: isPendingPatchDagRun, mutate: mutatePatchDagRun } = usePatchDagRun({ dagId, dagRunId });
53-
54-
const { data } = useClearDagRunDryRun({
59+
const { isPending: isPendingPatchDagRun, mutate: mutatePatchDagRun } = usePatchDagRun({
5560
dagId,
5661
dagRunId,
57-
options: {
58-
enabled: open,
59-
refetchOnMount: "always",
60-
},
61-
requestBody: {
62-
only_failed: onlyFailed,
63-
},
62+
onSuccess: onClose,
6463
});
6564

66-
const affectedTasks = data ?? {
67-
task_instances: [],
68-
total_entries: 0,
69-
};
70-
7165
return (
7266
<Dialog.Root lazyMount onOpenChange={onClose} open={open} size="xl">
7367
<Dialog.Content backdrop>
7468
<Dialog.Header>
7569
<VStack align="start" gap={4}>
7670
<Heading size="xl">
77-
<strong>Clear DagRun: </strong> {dagRunId}
71+
<strong>{translate("dags:runAndTaskActions.clear.dialog.title", { type: "Run" })}: </strong>{" "}
72+
{dagRunId}
7873
</Heading>
7974
</VStack>
8075
</Dialog.Header>
@@ -87,11 +82,17 @@ const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
8782
defaultValues={["existingTasks"]}
8883
onChange={setSelectedOptions}
8984
options={[
90-
{ label: "Clear existing tasks", value: "existingTasks" },
91-
{ label: "Clear only failed tasks", value: "onlyFailed" },
85+
{
86+
label: translate("dags:runAndTaskActions.clear.dialog.options.existingTasks"),
87+
value: "existingTasks",
88+
},
89+
{
90+
label: translate("dags:runAndTaskActions.clear.dialog.options.onlyFailed"),
91+
value: "onlyFailed",
92+
},
9293
{
9394
disabled: true,
94-
label: "Queue up new tasks",
95+
label: translate("dags:runAndTaskActions.clear.dialog.options.queueNew"),
9596
value: "new_tasks",
9697
},
9798
]}
@@ -118,7 +119,7 @@ const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
118119
}
119120
}}
120121
>
121-
<CgRedo /> Confirm
122+
<CgRedo /> {translate("dags:runAndTaskActions.clear.dialog.confirm")}
122123
</Button>
123124
</Flex>
124125
</Dialog.Body>

airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceButton.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Box, useDisclosure } from "@chakra-ui/react";
2020
import { useHotkeys } from "react-hotkeys-hook";
21+
import { useTranslation } from "react-i18next";
2122
import { CgRedo } from "react-icons/cg";
2223

2324
import type { TaskInstanceResponse } from "openapi/requests/types.gen";
@@ -34,6 +35,7 @@ type Props = {
3435

3536
const ClearTaskInstanceButton = ({ isHotkeyEnabled = false, taskInstance, withText = true }: Props) => {
3637
const { onClose, onOpen, open } = useDisclosure();
38+
const { t: translate } = useTranslation();
3739

3840
useHotkeys(
3941
"shift+c",
@@ -44,13 +46,18 @@ const ClearTaskInstanceButton = ({ isHotkeyEnabled = false, taskInstance, withTe
4446
);
4547

4648
return (
47-
<Tooltip closeDelay={100} content="Press shift+c to clear" disabled={!isHotkeyEnabled} openDelay={100}>
49+
<Tooltip
50+
closeDelay={100}
51+
content={translate("dags:runAndTaskActions.clear.buttonTooltip")}
52+
disabled={!isHotkeyEnabled}
53+
openDelay={100}
54+
>
4855
<Box>
4956
<ActionButton
50-
actionName="Clear Task Instance"
57+
actionName={translate("dags:runAndTaskActions.clear.button", { type: "Task Instance" })}
5158
icon={<CgRedo />}
5259
onClick={onOpen}
53-
text="Clear Task Instance"
60+
text={translate("dags:runAndTaskActions.clear.button", { type: "Task Instance" })}
5461
withText={withText}
5562
/>
5663

airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceDialog.tsx

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Flex, Heading, VStack } from "@chakra-ui/react";
2020
import { useState } from "react";
21+
import { useTranslation } from "react-i18next";
2122
import { CgRedo } from "react-icons/cg";
2223

2324
import type { TaskInstanceResponse } from "openapi/requests/types.gen";
@@ -38,6 +39,7 @@ type Props = {
3839
const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
3940
const taskId = taskInstance.task_id;
4041
const mapIndex = taskInstance.map_index;
42+
const { t: translate } = useTranslation();
4143

4244
const dagId = taskInstance.dag_id;
4345
const dagRunId = taskInstance.dag_run_id;
@@ -92,8 +94,10 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
9294
<Dialog.Header>
9395
<VStack align="start" gap={4}>
9496
<Heading size="xl">
95-
<strong>Clear Task Instance:</strong> {taskInstance.task_display_name}{" "}
96-
<Time datetime={taskInstance.start_date} />
97+
<strong>
98+
{translate("dags:runAndTaskActions.clear.dialog.title", { type: "Task Instance" })}:
99+
</strong>{" "}
100+
{taskInstance.task_display_name} <Time datetime={taskInstance.start_date} />
97101
</Heading>
98102
</VStack>
99103
</Dialog.Header>
@@ -106,11 +110,28 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
106110
multiple
107111
onChange={setSelectedOptions}
108112
options={[
109-
{ disabled: taskInstance.logical_date === null, label: "Past", value: "past" },
110-
{ disabled: taskInstance.logical_date === null, label: "Future", value: "future" },
111-
{ label: "Upstream", value: "upstream" },
112-
{ label: "Downstream", value: "downstream" },
113-
{ label: "Only Failed", value: "onlyFailed" },
113+
{
114+
disabled: taskInstance.logical_date === null,
115+
label: translate("dags:runAndTaskActions.clear.dialog.options.past"),
116+
value: "past",
117+
},
118+
{
119+
disabled: taskInstance.logical_date === null,
120+
label: translate("dags:runAndTaskActions.clear.dialog.options.future"),
121+
value: "future",
122+
},
123+
{
124+
label: translate("dags:runAndTaskActions.clear.dialog.options.upstream"),
125+
value: "upstream",
126+
},
127+
{
128+
label: translate("dags:runAndTaskActions.clear.dialog.options.downstream"),
129+
value: "downstream",
130+
},
131+
{
132+
label: translate("dags:runAndTaskActions.clear.dialog.options.onlyFailed"),
133+
value: "onlyFailed",
134+
},
114135
]}
115136
/>
116137
</Flex>
@@ -145,7 +166,7 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
145166
}
146167
}}
147168
>
148-
<CgRedo /> Confirm
169+
<CgRedo /> {translate("dags:runAndTaskActions.clear.dialog.confirm")}
149170
</Button>
150171
</Flex>
151172
</Dialog.Body>

0 commit comments

Comments
 (0)