Skip to content
Open
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 @@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Box } from "@chakra-ui/react";
import { Box, useToken } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { FiStar } from "react-icons/fi";

import { useToggleFavoriteDag } from "src/queries/useToggleFavoriteDag";
import { resolveTokenValue } from "src/theme";

import ActionButton from "../ui/ActionButton";

Expand All @@ -35,17 +36,21 @@ export const FavoriteDagButton = ({ dagId, isFavorite = false, withText = true }

const { isLoading, toggleFavorite } = useToggleFavoriteDag(dagId);

const [brandSolidColor] = useToken("colors", ["brand.solid"])
.map(token => resolveTokenValue(token || "oklch(0.5 0 0)"));

const onToggle = () => toggleFavorite(isFavorite);

return (
<Box>
<ActionButton
actionName={isFavorite ? translate("unfavoriteDag") : translate("favoriteDag")}
colorPalette="brand"
icon={
<FiStar
style={{
fill: isFavorite ? "var(--chakra-colors-brand-solid)" : "none",
stroke: "var(--chakra-colors-brand-solid)",
fill: isFavorite ? brandSolidColor : "none",
stroke: brandSolidColor,
}}
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const DateTimeInput = forwardRef<HTMLInputElement, Props>(({ onChange, va

return (
<Input
_hover={{ borderColor: "colorPalette.emphasized" }}
colorPalette="brand"
onChange={(event) =>
onChange?.({
...event,
Expand Down
15 changes: 8 additions & 7 deletions airflow-core/src/airflow/ui/src/components/DurationChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";

import type { TaskInstanceResponse, GridRunsResponse } from "openapi/requests/types.gen";
import { getComputedCSSVariableValue } from "src/theme";
import { resolveTokenValue } from "src/theme";
import { DEFAULT_DATETIME_FORMAT } from "src/utils/datetimeUtils";

ChartJS.register(
Expand Down Expand Up @@ -68,14 +68,15 @@ export const DurationChart = ({
}) => {
const { t: translate } = useTranslation(["components", "common"]);
const navigate = useNavigate();
const [queuedColorToken] = useToken("colors", ["queued.solid"]);
const [queuedColor] = useToken("colors", ["queued.solid"])
.map(token => resolveTokenValue(token || "oklch(0.5 0 0)"));

// Get states and create color tokens for them
const states = entries?.map((entry) => entry.state).filter(Boolean) ?? [];
const stateColorTokens = useToken(
const stateColors = useToken(
"colors",
states.map((state) => `${state}.solid`),
);
).map(token => resolveTokenValue(token || "oklch(0.5 0 0)"));

if (!entries) {
return undefined;
Expand All @@ -85,8 +86,8 @@ export const DurationChart = ({
const stateColorMap: Record<string, string> = {};

states.forEach((state, index) => {
if (state) {
stateColorMap[state] = getComputedCSSVariableValue(stateColorTokens[index] ?? "oklch(0.5 0 0)");
if (state && stateColors[index]) {
stateColorMap[state] = stateColors[index];
}
});

Expand Down Expand Up @@ -125,7 +126,7 @@ export const DurationChart = ({
data={{
datasets: [
{
backgroundColor: getComputedCSSVariableValue(queuedColorToken ?? "oklch(0.5 0 0)"),
backgroundColor: queuedColor,
data: entries.map((entry: RunResponse) => {
switch (kind) {
case "Dag Run": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const EditableMarkdownButton = ({
<Box display="inline-block" position="relative">
<ActionButton
actionName={placeholder}
colorPalette="brand"
icon={noteIcon}
onClick={() => {
if (!isOpen) {
Expand All @@ -70,7 +71,7 @@ const EditableMarkdownButton = ({
/>
{Boolean(mdContent?.trim()) && (
<Box
bg="brand.500"
bg="editable-markdown-button.indicator.bg"
borderRadius="full"
height={2.5}
position="absolute"
Expand All @@ -89,7 +90,7 @@ const EditableMarkdownButton = ({
unmountOnExit={true}
>
<Dialog.Content backdrop>
<Dialog.Header bg="brand.muted">
<Dialog.Header bg="editable-markdown-button.header.bg">
<Heading size="xl">{header}</Heading>
<Dialog.CloseTrigger closeButtonProps={{ size: "xl" }} />
</Dialog.Header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,10 @@ export const FilterBar = ({
<Menu.Root>
<Menu.Trigger asChild>
<Button
_hover={{ bg: "colorPalette.subtle" }}
bg="gray.muted"
_hover={{ bg: "colorPalette.emphasized" }}
bg="colorPalette.muted"
borderRadius="full"
colorPalette="brand"
variant="outline"
>
<MdAdd />
Expand All @@ -165,7 +166,7 @@ export const FilterBar = ({
</Menu.Root>
)}
{filters.length > 0 && (
<Button borderRadius="full" colorPalette="gray" onClick={resetFilters} size="sm" variant="outline">
<Button borderRadius="full" onClick={resetFilters} size="sm" variant="outline">
<MdClear />
{translate("common:reset")}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ export const FilterPill = ({
<Box
_hover={{ bg: "colorPalette.subtle" }}
as="button"
bg={hasValue ? "blue.muted" : "gray.muted"}
bg="colorPalette.muted"
borderRadius="full"
color="colorPalette.fg"
colorPalette={hasValue ? "blue" : "gray"}
colorPalette={hasValue ? "brand" : "gray"}
cursor="pointer"
display="flex"
fontSize="sm"
Expand All @@ -133,14 +133,13 @@ export const FilterPill = ({

<Box
_hover={{
bg: "gray.100",
color: "gray.600",
bg: "filter-bar.pill.close.bg.hover",
}}
alignItems="center"
aria-label={`Remove ${filter.config.label} filter`}
bg="transparent"
borderRadius="full"
color="gray.400"
color="filter-bar.pill.close.color"
cursor="pointer"
display="flex"
h={6}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,29 @@ export const SelectFilter = ({ filter, onChange, onRemove }: FilterPluginProps)
border="0.5px solid"
borderColor="border"
borderRadius="full"
colorPalette="gray"
display="flex"
h="full"
overflow="hidden"
width="330px"
>
<Text
alignItems="center"
bg="gray.muted"
alignSelf="stretch"
bg="colorPalette.muted"
borderLeftRadius="full"
display="flex"
flexShrink={0}
fontSize="sm"
fontWeight="medium"
h="full"
px={4}
px={3}
py={2}
whiteSpace="nowrap"
>
{filter.config.label}:
</Text>
<Select.Root
border="none"
collection={createListCollection({ items: config.options })}
h="full"
onValueChange={handleValueChange}
size="sm"
value={hasValue ? [String(filter.value)] : []}
>
<Select.Trigger triggerProps={{ border: "none" }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const DownloadButton = ({ name }: { readonly name: string }) => {
return (
<Panel position="bottom-right" style={{ transform: "translateY(-150px)" }}>
<IconButton
_hover={{ bg: "colorPalette.emphasized" }}
aria-label={translate("graph.downloadImage")}
colorPalette="info"
onClick={() => {
Expand Down
7 changes: 6 additions & 1 deletion airflow-core/src/airflow/ui/src/components/JsonEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@
* under the License.
*/
import { json } from "@codemirror/lang-json";
import { useToken } from "@chakra-ui/react";
import { githubLight, githubDark } from "@uiw/codemirror-themes-all";
import CodeMirror, { type ReactCodeMirrorProps, type ReactCodeMirrorRef } from "@uiw/react-codemirror";
import { forwardRef } from "react";

import { useColorMode } from "src/context/colorMode";
import { resolveTokenValue } from "src/theme";

export const JsonEditor = forwardRef<ReactCodeMirrorRef, ReactCodeMirrorProps>((props, ref) => {
const { colorMode } = useColorMode();

const [borderColor] = useToken("colors", ["border.emphasized"])
.map(token => resolveTokenValue(token || "oklch(0.5 0 0)"));

return (
<CodeMirror
basicSetup={{
Expand All @@ -38,7 +43,7 @@ export const JsonEditor = forwardRef<ReactCodeMirrorRef, ReactCodeMirrorProps>((
height="200px"
ref={ref}
style={{
border: "1px solid var(--chakra-colors-border-emphasized)",
border: `1px solid ${borderColor}`,
borderRadius: "8px",
outline: "none",
padding: "2px",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const NeedsReviewButton = ({
return hitlTIsCount > 0 ? (
<Box maxW="250px">
<StatsCard
colorScheme="deferred"
colorPalette="deferred"
count={hitlTIsCount}
icon={<LuUserRoundPen />}
isLoading={isLoading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ type QuickFilterButtonProps = {

export const QuickFilterButton = ({ children, isActive, ...rest }: QuickFilterButtonProps) => (
<Button
_hover={{ bg: "colorPalette.emphasized" }}
_hover={{ bg: "colorPalette.subtle" }}
bg={isActive ? "colorPalette.muted" : undefined}
borderColor="border.emphasized"
borderRadius={20}
borderWidth={1}
color="colorPalette.fg"
color="fg"
fontWeight="normal"
size="sm"
variant={isActive ? "solid" : "outline"}
Expand Down
11 changes: 8 additions & 3 deletions airflow-core/src/airflow/ui/src/components/StatsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type { TaskInstanceState } from "openapi/requests/types.gen";
import { StateBadge } from "src/components/StateBadge";

export const StatsCard = ({
colorScheme,
colorPalette,
count,
icon,
isLoading = false,
Expand All @@ -34,7 +34,7 @@ export const StatsCard = ({
onClick,
state,
}: {
readonly colorScheme: string;
readonly colorPalette: string;
readonly count: number;
readonly icon?: React.ReactNode;
readonly isLoading?: boolean;
Expand All @@ -50,14 +50,19 @@ export const StatsCard = ({

const content = (
<HStack
_hover={{
bg: "colorPalette.subtle",
borderColor: "colorPalette.emphasized",
}}
alignItems="center"
borderRadius="lg"
borderWidth={1}
color="fg.emphasized"
colorPalette={colorPalette}
cursor="pointer"
p={2}
>
<StateBadge colorPalette={colorScheme} mr={2} state={state}>
<StateBadge colorPalette={colorPalette} mr={2} state={state}>
{icon}
{count}
</StateBadge>
Expand Down
46 changes: 13 additions & 33 deletions airflow-core/src/airflow/ui/src/components/TrendCountChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/
import { Box, useToken } from "@chakra-ui/react";
import { resolveTokenValue } from "src/theme";
import {
Chart as ChartJS,
CategoryScale,
Expand All @@ -31,7 +32,6 @@ import dayjs from "dayjs";
import { useMemo, useRef, useEffect } from "react";
import { Line } from "react-chartjs-2";

import { useColorMode } from "src/context/colorMode";

ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Filler, Tooltip);

Expand Down Expand Up @@ -97,46 +97,26 @@ type Props = {
};

export const TrendCountChart = ({ endDate, events, startDate }: Props) => {
const { colorMode } = useColorMode();
const chartRef = useRef<ChartJS<"line">>();

// Get raw color values instead of CSS variables
const [bgLightGreen, bgDarkGreen, lineLightGreen, lineDarkGreen] = useToken("colors", [
"green.100",
"green.800",
"green.500",
"green.400",
]);

const [bgLightRed, bgDarkRed, lineLightRed, lineDarkRed] = useToken("colors", [
"red.100",
"red.800",
"red.500",
"red.400",
]);
const [successBg, successLine, failedBg, failedLine] = useToken("colors", [
"trend-count-chart.success.bg",
"trend-count-chart.success.line",
"trend-count-chart.failed.bg",
"trend-count-chart.failed.line",
]).map(token => resolveTokenValue(token || "oklch(0.5 0 0)"));

const intervalData = useMemo(
() => aggregateEventsIntoIntervals(events, startDate, endDate),
[events, startDate, endDate],
);

const backgroundColor =
colorMode === "light"
? intervalData.some((value) => value > 0)
? bgLightRed
: bgLightGreen
: intervalData.some((value) => value > 0)
? bgDarkRed
: bgDarkGreen;

const lineColor =
colorMode === "light"
? intervalData.some((value) => value > 0)
? lineLightRed
: lineLightGreen
: intervalData.some((value) => value > 0)
? lineDarkRed
: lineDarkGreen;
// TODO: Add a default/neutral state (neither green nor red) when no runs have happened yet.
// Currently shows green (success) when count is 0, but this is misleading when there are
// actually no runs at all (as opposed to runs with no failures).
const hasFailures = intervalData.some((value) => value > 0);
const backgroundColor = hasFailures ? failedBg : successBg;
const lineColor = hasFailures ? failedLine : successLine;

// Cleanup chart instance on unmount
useEffect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const TriggerDAGButton: React.FC<Props> = ({ dagDisplayName, dagId, isPaused, wi
<Box>
<ActionButton
actionName={translate("triggerDag.title")}
colorPalette="brand"
icon={<FiPlay />}
onClick={onOpen}
text={translate("triggerDag.button")}
Expand Down
Loading