Skip to content
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
1 change: 1 addition & 0 deletions airflow-core/src/airflow/ui/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
*.yaml
coverage/*
.pnpm-store
src/i18n/locales/*
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const AssetEvents = ({
title,
...rest
}: AssetEventProps & BoxProps) => {
const { t: translate } = useTranslation("dashboard");
const { t: translate } = useTranslation(["dashboard", "common"]);
const assetSortOptions = createListCollection({
items: [
{ label: translate("sortBy.newestFirst"), value: "-timestamp" },
Expand All @@ -74,7 +74,7 @@ export const AssetEvents = ({
{data?.total_entries ?? " "}
</StateBadge>
<Heading marginEnd="auto" size="md">
{translate("assetEvent", { count: data?.total_entries ?? 0 })}
{translate("common:assetEvent", { count: data?.total_entries ?? 0 })}
</Heading>
</HStack>
{setOrderBy === undefined ? undefined : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
* under the License.
*/
import { Flex, Link, Text } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { Link as RouterLink } from "react-router-dom";

import type { DagRunAssetReference, DagRunState } from "openapi/requests/types.gen";
import { Button, Popover } from "src/components/ui";
import { pluralize } from "src/utils";

import { StateBadge } from "../StateBadge";

Expand All @@ -30,13 +30,15 @@ type Props = {
};

export const TriggeredRuns = ({ dagRuns }: Props) => {
const { t: translate } = useTranslation("common");

if (dagRuns === undefined || dagRuns.length === 0) {
return undefined;
}

return dagRuns.length === 1 ? (
<Flex gap={1}>
<Text>Triggered Dag Run: </Text>
<Text>{`${translate("triggered")} ${translate("dagRun_one")}`}: </Text>
<StateBadge state={dagRuns[0]?.state as DagRunState} />
<Link asChild color="fg.info">
<RouterLink to={`/dags/${dagRuns[0]?.dag_id}/runs/${dagRuns[0]?.run_id}`}>
Expand All @@ -49,7 +51,7 @@ export const TriggeredRuns = ({ dagRuns }: Props) => {
<Popover.Root autoFocus={false} lazyMount unmountOnExit>
<Popover.Trigger asChild>
<Button size="sm" variant="outline">
{pluralize("Triggered Dag Run", dagRuns.length)}
{`${dagRuns.length} ${translate("triggered")} ${translate("dagRun_other", { count: dagRuns.length })}`}
</Button>
</Popover.Trigger>
<Popover.Content css={{ "--popover-bg": "colors.bg.emphasized" }} width="fit-content">
Expand Down
72 changes: 38 additions & 34 deletions airflow-core/src/airflow/ui/src/components/PoolBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
* under the License.
*/
import { Flex } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";

import { Tooltip } from "src/components/ui";
import { capitalize } from "src/utils";
import { type Slots, slotConfigs } from "src/utils/slots";

export const PoolBar = ({
Expand All @@ -30,39 +30,43 @@ export const PoolBar = ({
readonly pool: Slots;
readonly poolsWithSlotType?: Slots;
readonly totalSlots: number;
}) => (
<>
{slotConfigs.map(({ color, icon, key }) => {
const slotValue = pool[key];
const flexValue = slotValue / totalSlots || 0;
}) => {
const { t: translate } = useTranslation("common");

if (flexValue === 0) {
return undefined;
}
return (
<>
{slotConfigs.map(({ color, icon, key }) => {
const slotValue = pool[key];
const flexValue = slotValue / totalSlots || 0;

const tooltipContent = `${capitalize(key.replace("_", " "))}: ${slotValue}${
poolsWithSlotType ? ` (${poolsWithSlotType[key]} pools)` : ""
}`;
if (flexValue === 0) {
return undefined;
}

return (
<Tooltip content={tooltipContent} key={key}>
<Flex
alignItems="center"
bg={`${color}.solid`}
color="white"
flex={flexValue}
gap={1}
h="100%"
justifyContent="center"
px={1}
py={0.5}
textAlign="center"
>
{icon}
{slotValue}
</Flex>
</Tooltip>
);
})}
</>
);
const slotType = key.replace("_slots", "");
const poolCount = poolsWithSlotType ? poolsWithSlotType[key] : 0;
const tooltipContent = `${translate(`pools.${slotType}`)}: ${slotValue} (${poolCount} ${translate("pools.pools", { count: poolCount })})`;

return (
<Tooltip content={tooltipContent} key={key}>
<Flex
alignItems="center"
bg={`${color}.solid`}
color="white"
flex={flexValue}
gap={1}
h="100%"
justifyContent="center"
px={1}
py={0.5}
textAlign="center"
>
{icon}
{slotValue}
</Flex>
</Tooltip>
);
})}
</>
);
};
31 changes: 31 additions & 0 deletions airflow-core/src/airflow/ui/src/i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,36 @@
"documentation": "Documentation",
"githubRepo": "GitHub Repo",
"restApiReference": "REST API Reference"
},
"states": {
"queued": "Queued",
"running": "Running",
"success": "Success",
"failed": "Failed",
"skipped": "Skipped",
"removed": "Removed",
"scheduled": "Scheduled",
"restarting": "Restarting",
"up_for_retry": "Up For Retry",
"up_for_reschedule": "Up For Reschedule",
"upstream_failed": "Upstream Failed",
"deferred": "Deferred",
"no_status": "No Status"
},
"dagRun_one": "Dag Run",
"dagRun_other": "Dag Runs",
"taskInstance_one": "Task Instance",
"taskInstance_other": "Task Instances",
"assetEvent_one": "Asset Event",
"assetEvent_other": "Asset Events",
"triggered": "Triggered",
"pools": {
"open": "Open",
"running": "Running",
"queued": "Queued",
"scheduled": "Scheduled",
"deferred": "Deferred",
"pools_one": "pool",
"pools_other": "pools"
}
}
37 changes: 13 additions & 24 deletions airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,27 @@
"metaDatabase": "MetaDatabase",
"scheduler": "Scheduler",
"triggerer": "Triggerer",
"dagProcessor": "Dag Processor"
"dagProcessor": "Dag Processor",
"status": "Status",
"lastHeartbeat": "Last Heartbeat",
"healthy": "Healthy",
"unhealthy": "Unhealthy"
},
"importErrors": {
"searchByFile": "Search by file",
"dagImportError_one": "Dag Import Error",
"dagImportError_other": "Dag Import Errors",
"timestamp": "Timestamp"
},
"poolSlots": "Pool Slots",
"managePools": "Manage Pools",
"history": "History",
"dagRun_one": "Dag Run",
"dagRun_other": "Dag Runs",
"taskInstance_one": "Task Instance",
"taskInstance_other": "Task Instances",
"assetEvent_one": "Asset Event",
"assetEvent_other": "Asset Events",
"states": {
"queued": "Queued",
"running": "Running",
"success": "Success",
"failed": "Failed",
"skipped": "Skipped",
"removed": "Removed",
"scheduled": "Scheduled",
"restarting": "Restarting",
"up_for_retry": "Up For Retry",
"up_for_reschedule": "Up For Reschedule",
"upstream_failed": "Upstream Failed",
"deferred": "Deferred",
"no_status": "No Status"
},
"noAssetEvents": "No Asset Events found.",
"sortBy": {
"newestFirst": "Newest First",
"oldestFirst": "Oldest First"
},
"source": "Source",
"group": "Group",
"uri": "Uri"
"uri": "Uri",
"noAssetEvents": "No Asset Events found."
}
25 changes: 23 additions & 2 deletions airflow-core/src/airflow/ui/src/i18n/locales/zh_TW/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"browse": {
"auditLog": "審計日誌",
"xcoms": "Xcoms"
"xcoms": "XComs"
},
"admin": {
"Variables": "變數",
Expand All @@ -42,5 +42,26 @@
"documentation": "文件",
"githubRepo": "GitHub 倉庫",
"restApiReference": "REST API 參考"
}
},
"states": {
"queued": "排隊中",
"running": "執行中",
"success": "成功",
"failed": "失敗",
"skipped": "已跳過",
"removed": "已移除",
"scheduled": "已排程",
"restarting": "重啟中",
"up_for_retry": "等待重試",
"up_for_reschedule": "等待重新排程",
"upstream_failed": "上游任務失敗",
"deferred": "已延後",
"no_status": "無狀態"
},
"dagRun_one": "Dag 執行",
"dagRun_other": "Dag 執行",
"taskInstance_one": "任務實例",
"taskInstance_other": "任務實例",
"assetEvent_one": "資源事件",
"assetEvent_other": "資源事件"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,12 @@
"poolSlots": "資源池配額",
"managePools": "管理資源池",
"history": "歷史記錄",
"dagRun_one": "Dag 執行",
"dagRun_other": "Dag 執行",
"taskInstance_one": "任務實例",
"taskInstance_other": "任務實例",
"assetEvent_one": "資源事件",
"assetEvent_other": "資源事件",
"states": {
"queued": "排隊中",
"running": "執行中",
"success": "成功",
"failed": "失敗",
"skipped": "已跳過",
"removed": "已移除",
"scheduled": "已排程",
"restarting": "重啟中",
"up_for_retry": "等待重試",
"up_for_reschedule": "等待重新排程",
"upstream_failed": "上游任務失敗",
"deferred": "已延後",
"no_status": "無狀態"
},
"noAssetEvents": "未找到資源事件",
"sortBy": {
"newestFirst": "由新到舊",
"oldestFirst": "由舊到新"
},
"source": "來源",
"group": "群組",
"uri": "Uri"
"uri": "Uri",
"noAssetEvents": "未找到資源事件"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
* under the License.
*/
import { Skeleton, Text } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";

import { StateBadge } from "src/components/StateBadge";
import Time from "src/components/Time";
import { Tooltip } from "src/components/ui";
import { capitalize } from "src/utils";

export const HealthBadge = ({
isLoading,
Expand All @@ -34,6 +34,8 @@ export const HealthBadge = ({
readonly status?: string | null;
readonly title: string;
}) => {
const { t: translate } = useTranslation("dashboard");

if (isLoading) {
return <Skeleton borderRadius="full" height={8} width={24} />;
}
Expand All @@ -44,9 +46,15 @@ export const HealthBadge = ({
<Tooltip
content={
<div>
<Text>Status: {capitalize(status)}</Text>
<Text>
Last Heartbeat: <Time datetime={latestHeartbeat} />
{translate("health.status")}
{": "}
{translate(`health.${status}`)}
</Text>
<Text>
{translate("health.lastHeartbeat")}
{": "}
<Time datetime={latestHeartbeat} />
</Text>
</div>
}
Expand Down
Loading