diff --git a/.gitignore b/.gitignore index e7fb2a5403dff..1528de626bdac 100644 --- a/.gitignore +++ b/.gitignore @@ -171,8 +171,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* -.vscode/* -!.vscode/extensions.json /.vite/ # Exclude the ui .vite dir airflow-core/src/airflow/ui/.vite/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000000..0e6d5fd64e4df --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000..aeae611e1fe46 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,38 @@ +{ + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + } + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + } + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + } + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + } + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, +} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/AdminButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/AdminButton.tsx index ddc01d9db28ee..427d994c55aa7 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/AdminButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/AdminButton.tsx @@ -79,7 +79,7 @@ export const AdminButton = ({ return ( - } title={translate("nav.admin")} /> + {menuItems} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/BrowseButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/BrowseButton.tsx index 170f89a94f5fb..986fa973bbc19 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/BrowseButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/BrowseButton.tsx @@ -70,7 +70,7 @@ export const BrowseButton = ({ return ( - } title={translate("nav.browse")} /> + {menuItems} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/DocsButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/DocsButton.tsx index d73b323b3e122..3af4e7f93a636 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/DocsButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/DocsButton.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Link } from "@chakra-ui/react"; +import { Box, Icon, Link } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiBookOpen, FiExternalLink } from "react-icons/fi"; @@ -61,7 +61,7 @@ export const DocsButton = ({ return ( - } title={translate("nav.docs")} /> + {links @@ -73,17 +73,18 @@ export const DocsButton = ({ href={link.href} rel="noopener noreferrer" target="_blank" + textDecoration="none" > - {translate(`docs.${link.key}`)} - + {translate(`docs.${link.key}`)} + ))} {version === undefined ? undefined : ( - {version} - + {version} + )} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/Nav.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/Nav.tsx index 01185d2df8bae..2203df73880c1 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/Nav.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/Nav.tsx @@ -19,7 +19,7 @@ import { Box, Flex, VStack } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiDatabase, FiHome } from "react-icons/fi"; -import { NavLink } from "react-router-dom"; +import { Link } from "react-router-dom"; import { useAuthLinksServiceGetAuthMenus, @@ -140,14 +140,14 @@ export const Nav = () => { height="100%" justifyContent="space-between" position="fixed" - py={3} + py={1} top={0} - width={20} + width={16} zIndex="docked" > - - - + + + { transition: "transform 0.8s ease-in-out", }, }} - height="35px" - width="35px" + boxSize={8} /> - + - } title={translate("nav.home")} to="/" /> + } + icon={DagIcon} title={translate("nav.dags")} to="dags" /> } + icon={FiDatabase} title={translate("nav.assets")} to="assets" /> @@ -184,7 +183,7 @@ export const Nav = () => { - + > | IconType; readonly isExternal?: boolean; - readonly title?: string; + readonly pluginIcon?: ReactNode; + readonly title: string; readonly to?: string; } & ButtonProps; -export const NavButton = ({ icon, isExternal = false, title, to, ...rest }: NavButtonProps) => - to === undefined ? ( - - ) : isExternal ? ( - - - - ) : ( - - {({ isActive }: { readonly isActive: boolean }) => ( - - )} - + + ); + } + + return ( + ); +}; diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx index c7372703237a5..5d36cf59e1053 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Link, Image, Menu } from "@chakra-ui/react"; +import { Link, Image, Menu, Icon, Box } from "@chakra-ui/react"; import { FiExternalLink } from "react-icons/fi"; import { LuPlug } from "react-icons/lu"; import { RiArchiveStackLine } from "react-icons/ri"; @@ -46,11 +46,11 @@ export const PluginMenuItem = ({ const displayIcon = colorMode === "dark" && typeof iconDarkMode === "string" ? iconDarkMode : icon; const pluginIcon = typeof displayIcon === "string" ? ( - + ) : urlRoute === "legacy-fab-views" ? ( - + ) : ( - + ); const isExternal = urlRoute === undefined || urlRoute === null; @@ -58,9 +58,10 @@ export const PluginMenuItem = ({ if (topLevel) { return ( @@ -80,13 +81,15 @@ export const PluginMenuItem = ({ width="100%" > {pluginIcon} - {name} - + {name} + ) : ( {pluginIcon} - {name} + + {name} + )} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx index 2dfbf58ac3d4e..9ac31f6947fed 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Box } from "@chakra-ui/react"; +import { Box, Icon } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiChevronRight } from "react-icons/fi"; import { LuPlug } from "react-icons/lu"; @@ -53,7 +53,7 @@ export const PluginMenus = ({ navItems }: { readonly navItems: Array= 2 ? ( - } title={translate("nav.plugins")} /> + {buttons.map((navItem) => ( @@ -63,7 +63,7 @@ export const PluginMenus = ({ navItems }: { readonly navItems: Array {key} - + {menuButtons.map((navItem) => ( diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/SecurityButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/SecurityButton.tsx index 6d9fdca68f0e2..2955abce5ee30 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/SecurityButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/SecurityButton.tsx @@ -36,7 +36,7 @@ export const SecurityButton = () => { return ( - } title={translate("nav.security")} /> + {authLinks.extra_menu_items.map(({ text }) => { diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneMenuItem.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneMenuItem.tsx index 596cf79bb1ba1..42508f0316e05 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneMenuItem.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneMenuItem.tsx @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { Box, Icon } from "@chakra-ui/react"; import dayjs from "dayjs"; import timezone from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; @@ -48,8 +49,10 @@ export const TimezoneMenuItem = ({ onOpen }: { readonly onOpen: () => void }) => return ( - - {translate("timezone")}: {dayjs(time).tz(selectedTimezone).format("HH:mm z (Z)")} + + + {translate("timezone")}: {dayjs(time).tz(selectedTimezone).format("HH:mm z (Z)")} + ); }; diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx index 31e2dd0078a60..84d8c385fed87 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { useDisclosure } from "@chakra-ui/react"; +import { Box, Icon, useDisclosure } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiGrid, @@ -55,9 +55,29 @@ type ColorMode = (typeof COLOR_MODES)[keyof typeof COLOR_MODES]; export const UserSettingsButton = ({ externalViews }: { readonly externalViews: Array }) => { const { i18n, t: translate } = useTranslation(); const { selectedTheme, setColorMode } = useColorMode(); + + const colorModeOptions = [ + { + icon: FiSun, + label: translate("appearance.lightMode"), + value: COLOR_MODES.LIGHT, + }, + { + icon: FiMoon, + label: translate("appearance.darkMode"), + value: COLOR_MODES.DARK, + }, + { + icon: FiMonitor, + label: translate("appearance.systemMode"), + value: COLOR_MODES.SYSTEM, + }, + ]; + const { onClose: onCloseTimezone, onOpen: onOpenTimezone, open: isOpenTimezone } = useDisclosure(); const { onClose: onCloseLogout, onOpen: onOpenLogout, open: isOpenLogout } = useDisclosure(); const { onClose: onCloseLanguage, onOpen: onOpenLanguage, open: isOpenLanguage } = useDisclosure(); + const [dagView, setDagView] = useLocalStorage<"graph" | "grid">("default_dag_view", "grid"); const theme = selectedTheme ?? COLOR_MODES.SYSTEM; @@ -65,79 +85,60 @@ export const UserSettingsButton = ({ externalViews }: { readonly externalViews: const isRTL = i18n.dir() === "rtl"; return ( - - - } title={translate("user")} /> - - - - - {translate("selectLanguage")} - - - - - {translate("appearance.appearance")} - {isRTL ? ( - - ) : ( - - )} - - - setColorMode(element.value as ColorMode)} - value={theme} - > - - - {translate("appearance.lightMode")} - - - - - {translate("appearance.darkMode")} - - - - - {translate("appearance.systemMode")} - - - - - - (dagView === "grid" ? setDagView("graph") : setDagView("grid"))} - value={dagView} - > - {dagView === "grid" ? ( - <> - - {translate("defaultToGraphView")} - - ) : ( - <> - - {translate("defaultToGridView")} - - )} - - - {externalViews.map((view) => ( - - ))} - - - {translate("logout")} - - + <> + + + + + + + + {translate("selectLanguage")} + + + + + {translate("appearance.appearance")} + + + + setColorMode(element.value as ColorMode)} + value={theme} + > + {colorModeOptions.map(({ icon, label, value }) => ( + + + {label} + + + ))} + + + + (dagView === "grid" ? setDagView("graph") : setDagView("grid"))} + value={dagView} + > + + + {dagView === "grid" ? translate("defaultToGraphView") : translate("defaultToGridView")} + + + + {externalViews.map((view) => ( + + ))} + + + + {translate("logout")} + + + - + ); };