import React from 'react'; import {CircleQuestion, Gear, Person} from '@gravity-ui/icons'; import type {AsideHeaderItem} from '@gravity-ui/navigation'; import {AsideHeader, FooterItem} from '@gravity-ui/navigation'; import type {IconData} from '@gravity-ui/uikit'; import {useHistory} from 'react-router-dom'; import {useMultiTabQueryEditorEnabled} from '../../store/reducers/capabilities/hooks'; import {SETTING_KEYS} from '../../store/reducers/settings/constants'; import {cn} from '../../utils/cn'; import {useSetting} from '../../utils/hooks'; import {InformationPopup} from './InformationPopup'; import {SsoUserIcon} from './SsoUserIcon/SsoUserIcon'; import { DEFAULT_HOTKEY_GROUPS, EDITOR_TABS_HOTKEY_GROUP, useHotkeysPanel, } from './hooks/useHotkeysPanel'; import i18n from './i18n'; import userSecret from '../../assets/icons/user-secret.svg'; import ydbLogoIcon from '../../assets/icons/ydb.svg'; import './AsideNavigation.scss'; const b = cn('kv-navigation'); interface YdbUserDropdownProps { isCompact: boolean; user?: { login: string; icon?: IconData; isSso?: boolean; }; popupAnchor: React.RefObject; children: React.ReactNode; } function UserDropdown({isCompact, popupAnchor, user, children}: YdbUserDropdownProps) { const [isUserDropdownVisible, setIsUserDropdownVisible] = React.useState(false); const iconData = user ? (user.icon ?? Person) : userSecret; return ( setIsUserDropdownVisible((v) => !v)} enableTooltip={!isUserDropdownVisible} popupRef={popupAnchor} popupVisible={isUserDropdownVisible} itemWrapper={ user?.isSso ? (params, makeItem) => makeItem({...params, icon: }) : undefined } onOpenChangePopup={(open) => { if (!open) { setIsUserDropdownVisible(false); } }} renderPopupContent={() => (
{children}
)} /> ); } export interface AsideNavigationProps { settings: JSX.Element; ydbInternalUser: JSX.Element; menuItems?: AsideHeaderItem[]; content: React.ReactNode; user?: {login: string; icon?: IconData; isSso?: boolean}; renderFooterItems?: ( defaultFooterItems: React.ReactNode[], ctx: {compact: boolean; asideRef: React.RefObject}, ) => React.ReactNode[]; className?: string; } enum Panel { UserSettings = 'UserSettings', Information = 'Information', Hotkeys = 'Hotkeys', } export function AsideNavigation(props: AsideNavigationProps) { const history = useHistory(); const [visiblePanel, setVisiblePanel] = React.useState(); const [informationPopupVisible, setInformationPopupVisible] = React.useState(false); const [compact, setIsCompact] = useSetting(SETTING_KEYS.ASIDE_HEADER_COMPACT); const toggleInformationPopup = () => setInformationPopupVisible((prev) => !prev); const closeInformationPopup = React.useCallback(() => setInformationPopupVisible(false), []); const openHotkeysPanel = React.useCallback(() => { closeInformationPopup(); setVisiblePanel(Panel.Hotkeys); }, [closeInformationPopup]); const closePanel = React.useCallback(() => { setVisiblePanel(undefined); }, []); const isMultiTabQueryEditorEnabled = useMultiTabQueryEditorEnabled(); const hotkeyGroups = isMultiTabQueryEditorEnabled ? [...DEFAULT_HOTKEY_GROUPS, EDITOR_TABS_HOTKEY_GROUP] : DEFAULT_HOTKEY_GROUPS; const {renderPanel: renderHotkeysPanel} = useHotkeysPanel({ isPanelVisible: visiblePanel === Panel.Hotkeys, closePanel, openPanel: openHotkeysPanel, hotkeyGroups, }); const renderInformationPopup = () => { return ; }; const renderContent = React.useCallback(() => { return
{props.content}
; }, [props.content]); const renderLogo = React.useCallback((node: React.ReactNode) => { if (!React.isValidElement(node)) { return node; } return React.cloneElement(node as React.ReactElement<{'data-qa'?: string}>, { 'data-qa': 'aside-logo', }); }, []); return ( history.push('/'), wrapper: renderLogo, }} menuItems={props.menuItems} compact={compact} onChangeCompact={setIsCompact} multipleTooltip={true} className={b(null, props.className)} renderContent={renderContent} renderFooter={({compact: footerCompact, asideRef}) => { const defaultFooterItems = [ { if (!open) { closeInformationPopup(); } }} renderPopupContent={renderInformationPopup} />, { setVisiblePanel( visiblePanel === Panel.UserSettings ? undefined : Panel.UserSettings, ); }} compact={footerCompact} />, {props.ydbInternalUser} , ]; return ( {props.renderFooterItems ? props.renderFooterItems(defaultFooterItems, { compact: footerCompact, asideRef, }) : defaultFooterItems} ); }} panelItems={[ { id: 'user-settings', open: visiblePanel === Panel.UserSettings, size: 'auto', children: props.settings, }, { id: 'information', open: visiblePanel === Panel.Information, }, { id: 'hotkeys', open: visiblePanel === Panel.Hotkeys, keepMounted: true, children: renderHotkeysPanel(), }, ]} onClosePanel={closePanel} /> ); }