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
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,6 @@
"placeholder": "Add a note...",
"taskInstance": "Task Instance Note"
},
"pools": {
"deferred": "Deferred",
"open": "Open",
"pools_one": "pool",
"pools_other": "pools",
"queued": "Queued",
"running": "Running",
"scheduled": "Scheduled"
},
"reset": "Reset",
"runId": "Run ID",
"runTypes": {
Expand Down Expand Up @@ -207,6 +198,7 @@
"failed": "Failed",
"no_status": "No Status",
"none": "No Status",
"open": "Open",
"planned": "Planned",
"queued": "Queued",
"removed": "Removed",
Expand Down
126 changes: 81 additions & 45 deletions airflow-core/src/airflow/ui/src/components/PoolBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Flex, Link, Box } from "@chakra-ui/react";
import { Box, Flex, Text, VStack, Link, HStack } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { Link as RouterLink } from "react-router-dom";

import type { PoolResponse } from "openapi/requests/types.gen";
import type { PoolResponse, TaskInstanceState } from "openapi/requests/types.gen";
import { StateIcon } from "src/components/StateIcon";
import { Tooltip } from "src/components/ui";
import { SearchParamsKeys } from "src/constants/searchParams";
import { type Slots, slotConfigs } from "src/utils/slots";
Expand All @@ -36,52 +37,87 @@ export const PoolBar = ({
}) => {
const { t: translate } = useTranslation("common");

const isDashboard = Boolean(poolsWithSlotType);
const includeDeferredInBar = "include_deferred" in pool && pool.include_deferred;
const barSlots = ["running", "queued", "open"];

if (isDashboard || includeDeferredInBar) {
barSlots.push("deferred");
}
const infoSlots = ["scheduled"];

if (!isDashboard && !includeDeferredInBar) {
infoSlots.push("deferred");
}

const preparedSlots = slotConfigs.map((config) => {
const slotType = config.key.replace("_slots", "") as TaskInstanceState;

return {
...config,
label: translate(`common:states.${slotType}`),
slotType,
slotValue: (pool[config.key] as number | undefined) ?? 0,
};
});

return (
<>
{slotConfigs.map(({ color, icon, key }) => {
const slotValue = pool[key];
const flexValue = slotValue / totalSlots || 0;
<VStack align="stretch" gap={1} w="100%">
<Flex bg="bg.muted" borderRadius="md" h="20px" overflow="hidden" w="100%">
{preparedSlots
.filter((slot) => barSlots.includes(slot.slotType) && slot.slotValue > 0)
.map((slot) => {
const flexValue = slot.slotValue / totalSlots || 0;

if (flexValue === 0) {
return undefined;
}
const poolContent = (
<Tooltip content={slot.label} key={slot.key} showArrow={true}>
<Flex
alignItems="center"
bg={`${slot.color}.solid`}
color={`${slot.color}.contrast`}
gap={1}
h="100%"
justifyContent="center"
overflow="hidden"
px={1}
w="100%"
>
{slot.icon}
<Text fontSize="xs" fontWeight="bold" truncate>
{slot.slotValue}
</Text>
</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 })})`;
const poolContent = (
<Tooltip content={tooltipContent} key={key}>
<Flex
alignItems="center"
bg={`${color}.solid`}
color={`${color}.contrast`}
gap={1}
h="100%"
justifyContent="center"
px={1}
textAlign="center"
w="100%"
>
{icon}
{slotValue}
</Flex>
</Tooltip>
);
return slot.color !== "success" && "name" in pool ? (
<Link asChild flex={flexValue} key={slot.key}>
<RouterLink
to={`/task_instances?${SearchParamsKeys.STATE}=${slot.color}&${SearchParamsKeys.POOL}=${pool.name}`}
>
{poolContent}
</RouterLink>
</Link>
) : (
<Box flex={flexValue} key={slot.key}>
{poolContent}
</Box>
);
})}
</Flex>

return color !== "success" && "name" in pool ? (
<Link asChild display="flex" flex={flexValue} key={key}>
<RouterLink
to={`/task_instances?${SearchParamsKeys.STATE}=${color}&${SearchParamsKeys.POOL}=${pool.name}`}
>
{poolContent}
</RouterLink>
</Link>
) : (
<Box display="flex" flex={flexValue} key={key}>
{poolContent}
</Box>
);
})}
</>
<HStack gap={4} wrap="wrap">
{preparedSlots
.filter((slot) => infoSlots.includes(slot.slotType) && slot.slotValue > 0)
.map((slot) => (
<HStack gap={1} key={slot.key}>
<StateIcon size={12} state={slot.slotType} />
<Text color="fg.muted" fontSize="xs" fontWeight="medium">
{slot.label}: {slot.slotValue}
</Text>
</HStack>
))}
</HStack>
</VStack>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ export const PoolSummary = () => {
{isLoading ? (
<Skeleton borderRadius="full" h={8} w="100%" />
) : (
<Flex bg="bg" borderRadius="full" display="flex" overflow="hidden" w="100%">
<PoolBar pool={aggregatePool} poolsWithSlotType={poolsWithSlotType} totalSlots={totalSlots} />
</Flex>
<PoolBar pool={aggregatePool} poolsWithSlotType={poolsWithSlotType} totalSlots={totalSlots} />
)}
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ const PoolBarCard = ({ pool }: PoolBarCardProps) => {
)}
</VStack>
</Flex>

<Box margin={4}>
<Flex bg="bg.muted" borderRadius="md" h="20px" overflow="hidden" w="100%">
<PoolBar pool={pool} totalSlots={pool.slots} />
</Flex>
<PoolBar pool={pool} totalSlots={pool.slots} />
</Box>
</Box>
);
Expand Down
Loading