Skip to content

i18n - Translate Task Instance and Dag Run tables #51222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
*/
import { Box, Editable, Text, VStack } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
import { useTranslation } from "react-i18next";

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

import { DataTable } from "../DataTable";
import { columns } from "./columns";
import { getColumns } from "./columns";

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

return (
<Accordion.Root
Expand All @@ -47,15 +49,20 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
{showTaskSection ? (
<Accordion.Item key="tasks" value="tasks">
<Accordion.ItemTrigger>
<Text fontWeight="bold">Affected Tasks: {affectedTasks.total_entries}</Text>
<Text fontWeight="bold">
{translate("dags:runAndTaskActions.clear.dialog.affectedTasks.title", {
count: affectedTasks.total_entries,
})}
</Text>
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Box maxH="400px" overflowY="scroll">
<DataTable
columns={columns}
columns={getColumns(translate)}
data={affectedTasks.task_instances}
displayMode="table"
modelName="Task Instance"
modelName={translate("common:taskInstance_other")}
noRowsMessage={translate("dags:runAndTaskActions.clear.dialog.affectedTasks.noItemsFound")}
total={affectedTasks.total_entries}
/>
</Box>
Expand All @@ -64,7 +71,7 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
) : undefined}
<Accordion.Item key="note" value="note">
<Accordion.ItemTrigger>
<Text fontWeight="bold">Note</Text>
<Text fontWeight="bold">{translate("dags:runAndTaskActions.clear.dialog.note.title")}</Text>
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Editable.Root
Expand All @@ -83,14 +90,16 @@ const ActionAccordion = ({ affectedTasks, note, setNote }: Props) => {
{Boolean(note) ? (
<ReactMarkdown>{note}</ReactMarkdown>
) : (
<Text color="fg.subtle">Add a note...</Text>
<Text color="fg.subtle">
{translate("dags:runAndTaskActions.clear.dialog.note.placeholder")}
</Text>
)}
</Editable.Preview>
<Editable.Textarea
data-testid="notes-input"
height="200px"
overflowY="auto"
placeholder="Add a note..."
placeholder={translate("dags:runAndTaskActions.clear.dialog.note.placeholder")}
resize="none"
/>
</Editable.Root>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,33 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Link } from "@chakra-ui/react";
import type { ColumnDef } from "@tanstack/react-table";
import { Link as RouterLink } from "react-router-dom";
import type { TFunction } from "i18next";

import type { TaskInstanceResponse } from "openapi/requests/types.gen";
import type { MetaColumn } from "src/components/DataTable/types";
import { StateBadge } from "src/components/StateBadge";
import { Tooltip } from "src/components/ui";
import { getTaskInstanceLink } from "src/utils/links";
import { trimText } from "src/utils/trimTextFn";

export const columns: Array<ColumnDef<TaskInstanceResponse>> = [
export const getColumns = (translate: TFunction): Array<MetaColumn<TaskInstanceResponse>> => [
{
accessorKey: "task_display_name",
cell: ({ row: { original } }) => (
<Tooltip content={original.task_display_name}>
<Link asChild color="fg.info" fontWeight="bold" maxWidth="200px" overflow="hidden">
<RouterLink to={getTaskInstanceLink(original)}>
{trimText(original.task_display_name, 25).trimmedText}
</RouterLink>
</Link>
</Tooltip>
),
enableSorting: false,
header: "Task ID",
accessorKey: "task_id",
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.taskId"),
size: 200,
},
{
accessorKey: "state",
cell: ({
row: {
original: { state },
},
}) => <StateBadge state={state}>{state}</StateBadge>,
enableSorting: false,
header: () => "State",
}) => <StateBadge state={state}>{translate(`common:states.${state}`)}</StateBadge>,
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.state"),
},
{
accessorKey: "rendered_map_index",
enableSorting: false,
header: "Map Index",
accessorKey: "map_index",
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.mapIndex"),
},

{
accessorKey: "dag_run_id",
enableSorting: false,
header: "Run Id",
accessorKey: "run_id",
header: translate("dags:runAndTaskActions.clear.dialog.affectedTasks.columns.runId"),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { Box, useDisclosure } from "@chakra-ui/react";
import { useHotkeys } from "react-hotkeys-hook";
import { useTranslation } from "react-i18next";
import { CgRedo } from "react-icons/cg";

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

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

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

return (
<Tooltip closeDelay={100} content="Press shift+c to clear" disabled={!isHotkeyEnabled} openDelay={100}>
<Tooltip
closeDelay={100}
content={translate("dags:runAndTaskActions.clear.buttonTooltip")}
disabled={!isHotkeyEnabled}
openDelay={100}
>
<Box>
<ActionButton
actionName="Clear Dag Run"
actionName={translate("dags:runAndTaskActions.clear.button", { type: "Run" })}
icon={<CgRedo />}
onClick={onOpen}
text="Clear Run"
text={translate("dags:runAndTaskActions.clear.button", { type: "Run" })}
withText={withText}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { Flex, Heading, VStack } from "@chakra-ui/react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { CgRedo } from "react-icons/cg";

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

const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
const [selectedOptions, setSelectedOptions] = useState<Array<string>>([]);

const dagId = dagRun.dag_id;
const dagRunId = dagRun.dag_run_id;
const { t: translate } = useTranslation();

const [note, setNote] = useState<string | null>(dagRun.note);
const [selectedOptions, setSelectedOptions] = useState<Array<string>>(["existingTasks"]);
const onlyFailed = selectedOptions.includes("onlyFailed");

const { data: affectedTasks = { task_instances: [], total_entries: 0 } } = useClearDagRunDryRun({
dagId,
dagRunId,
requestBody: { only_failed: onlyFailed },
});

const { isPending, mutate } = useClearDagRun({
dagId,
dagRunId,
onSuccessConfirm: onClose,
});

const onlyFailed = selectedOptions.includes("onlyFailed");

const [note, setNote] = useState<string | null>(dagRun.note);
const { isPending: isPendingPatchDagRun, mutate: mutatePatchDagRun } = usePatchDagRun({ dagId, dagRunId });

const { data } = useClearDagRunDryRun({
const { isPending: isPendingPatchDagRun, mutate: mutatePatchDagRun } = usePatchDagRun({
dagId,
dagRunId,
options: {
enabled: open,
refetchOnMount: "always",
},
requestBody: {
only_failed: onlyFailed,
},
onSuccess: onClose,
});

const affectedTasks = data ?? {
task_instances: [],
total_entries: 0,
};

return (
<Dialog.Root lazyMount onOpenChange={onClose} open={open} size="xl">
<Dialog.Content backdrop>
<Dialog.Header>
<VStack align="start" gap={4}>
<Heading size="xl">
<strong>Clear DagRun: </strong> {dagRunId}
<strong>{translate("dags:runAndTaskActions.clear.dialog.title", { type: "Run" })}: </strong>{" "}
{dagRunId}
</Heading>
</VStack>
</Dialog.Header>
Expand All @@ -87,11 +82,17 @@ const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
defaultValues={["existingTasks"]}
onChange={setSelectedOptions}
options={[
{ label: "Clear existing tasks", value: "existingTasks" },
{ label: "Clear only failed tasks", value: "onlyFailed" },
{
label: translate("dags:runAndTaskActions.clear.dialog.options.existingTasks"),
value: "existingTasks",
},
{
label: translate("dags:runAndTaskActions.clear.dialog.options.onlyFailed"),
value: "onlyFailed",
},
{
disabled: true,
label: "Queue up new tasks",
label: translate("dags:runAndTaskActions.clear.dialog.options.queueNew"),
value: "new_tasks",
},
]}
Expand All @@ -118,7 +119,7 @@ const ClearRunDialog = ({ dagRun, onClose, open }: Props) => {
}
}}
>
<CgRedo /> Confirm
<CgRedo /> {translate("dags:runAndTaskActions.clear.dialog.confirm")}
</Button>
</Flex>
</Dialog.Body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { Box, useDisclosure } from "@chakra-ui/react";
import { useHotkeys } from "react-hotkeys-hook";
import { useTranslation } from "react-i18next";
import { CgRedo } from "react-icons/cg";

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

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

useHotkeys(
"shift+c",
Expand All @@ -44,13 +46,18 @@ const ClearTaskInstanceButton = ({ isHotkeyEnabled = false, taskInstance, withTe
);

return (
<Tooltip closeDelay={100} content="Press shift+c to clear" disabled={!isHotkeyEnabled} openDelay={100}>
<Tooltip
closeDelay={100}
content={translate("dags:runAndTaskActions.clear.buttonTooltip")}
disabled={!isHotkeyEnabled}
openDelay={100}
>
<Box>
<ActionButton
actionName="Clear Task Instance"
actionName={translate("dags:runAndTaskActions.clear.button", { type: "Task Instance" })}
icon={<CgRedo />}
onClick={onOpen}
text="Clear Task Instance"
text={translate("dags:runAndTaskActions.clear.button", { type: "Task Instance" })}
withText={withText}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { Flex, Heading, VStack } from "@chakra-ui/react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { CgRedo } from "react-icons/cg";

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

const dagId = taskInstance.dag_id;
const dagRunId = taskInstance.dag_run_id;
Expand Down Expand Up @@ -92,8 +94,10 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
<Dialog.Header>
<VStack align="start" gap={4}>
<Heading size="xl">
<strong>Clear Task Instance:</strong> {taskInstance.task_display_name}{" "}
<Time datetime={taskInstance.start_date} />
<strong>
{translate("dags:runAndTaskActions.clear.dialog.title", { type: "Task Instance" })}:
</strong>{" "}
{taskInstance.task_display_name} <Time datetime={taskInstance.start_date} />
</Heading>
</VStack>
</Dialog.Header>
Expand All @@ -106,11 +110,28 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
multiple
onChange={setSelectedOptions}
options={[
{ disabled: taskInstance.logical_date === null, label: "Past", value: "past" },
{ disabled: taskInstance.logical_date === null, label: "Future", value: "future" },
{ label: "Upstream", value: "upstream" },
{ label: "Downstream", value: "downstream" },
{ label: "Only Failed", value: "onlyFailed" },
{
disabled: taskInstance.logical_date === null,
label: translate("dags:runAndTaskActions.clear.dialog.options.past"),
value: "past",
},
{
disabled: taskInstance.logical_date === null,
label: translate("dags:runAndTaskActions.clear.dialog.options.future"),
value: "future",
},
{
label: translate("dags:runAndTaskActions.clear.dialog.options.upstream"),
value: "upstream",
},
{
label: translate("dags:runAndTaskActions.clear.dialog.options.downstream"),
value: "downstream",
},
{
label: translate("dags:runAndTaskActions.clear.dialog.options.onlyFailed"),
value: "onlyFailed",
},
]}
/>
</Flex>
Expand Down Expand Up @@ -145,7 +166,7 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => {
}
}}
>
<CgRedo /> Confirm
<CgRedo /> {translate("dags:runAndTaskActions.clear.dialog.confirm")}
</Button>
</Flex>
</Dialog.Body>
Expand Down
Loading