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
3 changes: 2 additions & 1 deletion airflow-core/src/airflow/api_fastapi/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ class MenuItem(Enum):
"""Define all menu items defined in the menu."""

ASSETS = "Assets"
AUDIT_LOG = "Audit log"
AUDIT_LOG = "Audit Log"
CONFIG = "Config"
CONNECTIONS = "Connections"
DAGS = "Dags"
DOCS = "Docs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10200,7 +10200,8 @@ components:
type: string
enum:
- Assets
- Audit log
- Audit Log
- Config
- Connections
- Dags
- Docs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4296,7 +4296,8 @@ export const $MenuItem = {
type: "string",
enum: [
"Assets",
"Audit log",
"Audit Log",
"Config",
"Connections",
"Dags",
"Docs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,8 @@ export type JobResponse = {
*/
export type MenuItem =
| "Assets"
| "Audit log"
| "Audit Log"
| "Config"
| "Connections"
| "Dags"
| "Docs"
Expand Down
41 changes: 25 additions & 16 deletions airflow-core/src/airflow/ui/src/layouts/Nav/AdminButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import { FiSettings } from "react-icons/fi";
import { Link } from "react-router-dom";

import type { MenuItem } from "openapi/requests/types.gen";
import { Menu } from "src/components/ui";

import { NavButton } from "./NavButton";
Expand Down Expand Up @@ -50,19 +51,27 @@ const links = [
},
];

export const AdminButton = () => (
<Menu.Root positioning={{ placement: "right" }}>
<Menu.Trigger asChild>
<NavButton icon={<FiSettings size="1.75rem" />} title="Admin" />
</Menu.Trigger>
<Menu.Content>
{links.map((link) => (
<Menu.Item asChild key={link.title} value={link.title}>
<Link aria-label={link.title} to={link.href}>
{link.title}
</Link>
</Menu.Item>
))}
</Menu.Content>
</Menu.Root>
);
export const AdminButton = ({ authorizedMenuItems }: { readonly authorizedMenuItems: Array<MenuItem> }) => {
const menuItems = links
.filter(({ title }) => authorizedMenuItems.includes(title as MenuItem))
.map((link) => (
<Menu.Item asChild key={link.title} value={link.title}>
<Link aria-label={link.title} to={link.href}>
{link.title}
</Link>
</Menu.Item>
));

if (!menuItems.length) {
return undefined;
}

return (
<Menu.Root positioning={{ placement: "right" }}>
<Menu.Trigger asChild>
<NavButton icon={<FiSettings size="1.75rem" />} title="Admin" />
</Menu.Trigger>
<Menu.Content>{menuItems}</Menu.Content>
</Menu.Root>
);
};
43 changes: 26 additions & 17 deletions airflow-core/src/airflow/ui/src/layouts/Nav/BrowseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,43 @@
import { FiGlobe } from "react-icons/fi";
import { Link } from "react-router-dom";

import type { MenuItem } from "openapi/requests/types.gen";
import { Menu } from "src/components/ui";

import { NavButton } from "./NavButton";

const links = [
{
href: "/events",
title: "Events",
title: "Audit Log",
},
{
href: "/xcoms",
title: "XComs",
},
];

export const BrowseButton = () => (
<Menu.Root positioning={{ placement: "right" }}>
<Menu.Trigger asChild>
<NavButton icon={<FiGlobe size="1.75rem" />} title="Browse" />
</Menu.Trigger>
<Menu.Content>
{links.map((link) => (
<Menu.Item asChild key={link.title} value={link.title}>
<Link aria-label={link.title} to={link.href}>
{link.title}
</Link>
</Menu.Item>
))}
</Menu.Content>
</Menu.Root>
);
export const BrowseButton = ({ authorizedMenuItems }: { readonly authorizedMenuItems: Array<MenuItem> }) => {
const menuItems = links
.filter(({ title }) => authorizedMenuItems.includes(title as MenuItem))
.map((link) => (
<Menu.Item asChild key={link.title} value={link.title}>
<Link aria-label={link.title} to={link.href}>
{link.title}
</Link>
</Menu.Item>
));

if (!menuItems.length) {
return undefined;
}

return (
<Menu.Root positioning={{ placement: "right" }}>
<Menu.Trigger asChild>
<NavButton icon={<FiGlobe size="1.75rem" />} title="Browse" />
</Menu.Trigger>
<Menu.Content>{menuItems}</Menu.Content>
</Menu.Root>
);
};
19 changes: 17 additions & 2 deletions airflow-core/src/airflow/ui/src/layouts/Nav/DocsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@ const links = [
},
];

export const DocsButton = () => {
const showAPIDocs = Boolean(useConfig("enable_swagger_ui"));
export const DocsButton = ({
showAPI,
version,
}: {
readonly showAPI?: boolean;
readonly version?: string;
}) => {
const showAPIDocs = Boolean(useConfig("enable_swagger_ui")) && showAPI;

const versionLink = `https://airflow.apache.org/docs/apache-airflow/${version}/index.html`;

return (
<Menu.Root positioning={{ placement: "right" }}>
Expand All @@ -59,6 +67,13 @@ export const DocsButton = () => {
</Link>
</Menu.Item>
))}
{version === undefined ? undefined : (
<Menu.Item asChild key={version} value={version}>
<Link aria-label={version} href={versionLink} rel="noopener noreferrer" target="_blank">
{version}
</Link>
</Menu.Item>
)}
</Menu.Content>
</Menu.Root>
);
Expand Down
34 changes: 18 additions & 16 deletions airflow-core/src/airflow/ui/src/layouts/Nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Box, Flex, VStack, Link } from "@chakra-ui/react";
import { Box, Flex, VStack } from "@chakra-ui/react";
import { FiDatabase, FiHome } from "react-icons/fi";

import { useVersionServiceGetVersion } from "openapi/queries";
import { useAuthLinksServiceGetAuthMenus, useVersionServiceGetVersion } from "openapi/queries";
import { AirflowPin } from "src/assets/AirflowPin";
import { DagIcon } from "src/assets/DagIcon";

Expand All @@ -33,6 +33,7 @@ import { UserSettingsButton } from "./UserSettingsButton";

export const Nav = () => {
const { data } = useVersionServiceGetVersion();
const { data: authLinks } = useAuthLinksServiceGetAuthMenus();

return (
<VStack
Expand All @@ -52,25 +53,26 @@ export const Nav = () => {
<AirflowPin height="35px" width="35px" />
</Box>
<NavButton icon={<FiHome size="1.75rem" />} title="Home" to="/" />
<NavButton icon={<DagIcon height="1.75rem" width="1.75rem" />} title="Dags" to="dags" />
<NavButton icon={<FiDatabase size="1.75rem" />} title="Assets" to="assets" />
<BrowseButton />
<AdminButton />
<NavButton
disabled={!authLinks?.authorized_menu_items.includes("Dags")}
icon={<DagIcon height="1.75rem" width="1.75rem" />}
title="Dags"
to="dags"
/>
<NavButton
disabled={!authLinks?.authorized_menu_items.includes("Assets")}
icon={<FiDatabase size="1.75rem" />}
title="Assets"
to="assets"
/>
<BrowseButton authorizedMenuItems={authLinks?.authorized_menu_items ?? []} />
<AdminButton authorizedMenuItems={authLinks?.authorized_menu_items ?? []} />
<SecurityButton />
<PluginMenus />
</Flex>
<Flex flexDir="column">
<DocsButton />
<DocsButton showAPI={authLinks?.authorized_menu_items.includes("Docs")} version={data?.version} />
<UserSettingsButton />
<Link
aria-label={data?.version}
color="fg.info"
href={`https://airflow.apache.org/docs/apache-airflow/${data?.version}/index.html`}
rel="noopener noreferrer"
target="_blank"
>
{data?.version}
</Link>
</Flex>
</VStack>
);
Expand Down