hyper-tuner-cloud/src/components/TopBar.tsx

258 lines
7.3 KiB
TypeScript
Raw Normal View History

import {
useCallback,
useEffect,
useMemo,
} from 'react';
2021-03-22 14:29:03 -07:00
import {
matchPath,
useLocation,
useHistory,
} from 'react-router';
2022-01-09 14:33:38 -08:00
import {
Link,
generatePath,
} from 'react-router-dom';
2021-03-22 14:29:03 -07:00
import {
Layout,
Space,
Button,
Row,
Col,
Tooltip,
Grid,
Menu,
Dropdown,
Typography,
Radio,
} from 'antd';
import {
UserOutlined,
CloudUploadOutlined,
CloudDownloadOutlined,
SettingOutlined,
LoginOutlined,
LineChartOutlined,
SlidersOutlined,
FileExcelOutlined,
FileTextOutlined,
FileZipOutlined,
SaveOutlined,
DesktopOutlined,
DownOutlined,
SearchOutlined,
2021-03-22 15:24:39 -07:00
ToolOutlined,
FundOutlined,
2021-12-25 14:32:07 -08:00
UserAddOutlined,
LogoutOutlined,
2022-01-16 09:32:55 -08:00
InfoCircleOutlined,
2021-03-22 14:29:03 -07:00
} from '@ant-design/icons';
import { useKBar } from 'kbar';
2021-03-22 14:29:03 -07:00
import store from '../store';
2022-01-23 10:35:26 -08:00
import {
isMac,
isFirefox,
} from '../utils/env';
2021-03-22 14:29:03 -07:00
import {
isCommand,
isToggleSidebar,
} from '../utils/keyboard/shortcuts';
import { Routes } from '../routes';
2021-12-25 14:32:07 -08:00
import { useAuth } from '../contexts/AuthContext';
import {
logOutFailed,
logOutSuccessful,
2022-01-02 13:25:52 -08:00
} from '../pages/auth/notifications';
2021-03-22 14:29:03 -07:00
const { Header } = Layout;
const { useBreakpoint } = Grid;
const { SubMenu } = Menu;
2022-01-09 14:33:38 -08:00
const TopBar = ({ tuneId }: { tuneId: string | null }) => {
2022-01-02 13:25:52 -08:00
const { sm, lg } = useBreakpoint();
2021-03-22 14:29:03 -07:00
const { pathname } = useLocation();
2021-12-25 14:32:07 -08:00
const { currentUser, logout } = useAuth();
2021-03-22 14:29:03 -07:00
const history = useHistory();
const { query } = useKBar();
2022-01-09 14:33:38 -08:00
const buildTuneUrl = (route: string) => tuneId ? generatePath(route, { tuneId }) : null;
2022-01-16 09:32:55 -08:00
const matchedTuneRootPath = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_ROOT,
}), [pathname]);
2022-01-09 14:33:38 -08:00
const matchedTabPath = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_TAB,
}), [pathname]);
2021-12-26 05:11:15 -08:00
const logoutClick = useCallback(async () => {
try {
await logout();
logOutSuccessful();
} catch (error) {
console.warn(error);
logOutFailed(error as Error);
2021-12-26 05:11:15 -08:00
}
}, [logout]);
2021-03-22 14:29:03 -07:00
const toggleCommandPalette = useCallback(() => query.toggle(), [query]);
const handleGlobalKeyboard = useCallback((e: KeyboardEvent) => {
2021-03-22 14:29:03 -07:00
if (isCommand(e)) {
2022-01-23 10:35:26 -08:00
e.preventDefault();
toggleCommandPalette();
2021-03-22 14:29:03 -07:00
}
if (isToggleSidebar(e)) {
e.preventDefault();
store.dispatch({ type: 'ui/toggleSidebar' });
}
}, [toggleCommandPalette]);
2021-03-22 14:29:03 -07:00
useEffect(() => {
document.addEventListener('keydown', handleGlobalKeyboard);
return () => document.removeEventListener('keydown', handleGlobalKeyboard);
});
2022-01-09 14:33:38 -08:00
const tabs = (
2022-01-16 09:53:36 -08:00
<Col span={14} md={12} sm={16} style={{ textAlign: 'center' }}>
2022-01-09 14:33:38 -08:00
<Radio.Group
key={pathname}
2022-01-16 09:32:55 -08:00
defaultValue={matchedTabPath?.url || matchedTuneRootPath?.url}
2022-01-09 14:33:38 -08:00
optionType="button"
buttonStyle="solid"
onChange={(e) => history.push(e.target.value)}
>
2022-01-16 09:32:55 -08:00
<Radio.Button value={buildTuneUrl(Routes.TUNE_ROOT)}>
<Space>
<InfoCircleOutlined />
{sm && 'Info'}
</Space>
</Radio.Button>
2022-01-09 14:33:38 -08:00
<Radio.Button value={buildTuneUrl(Routes.TUNE_TUNE)}>
<Space>
<ToolOutlined />
{sm && 'Tune'}
</Space>
</Radio.Button>
2022-01-23 12:40:41 -08:00
<Radio.Button value={buildTuneUrl(Routes.TUNE_LOGS)}>
2022-01-09 14:33:38 -08:00
<Space>
<FundOutlined />
2022-01-23 12:40:41 -08:00
{sm && 'Logs'}
2022-01-09 14:33:38 -08:00
</Space>
</Radio.Button>
<Radio.Button value={buildTuneUrl(Routes.TUNE_DIAGNOSE)}>
<Space>
<SettingOutlined />
{sm && 'Diagnose'}
</Space>
</Radio.Button>
</Radio.Group>
</Col>
);
const rightMenuColProps = tuneId ? {
span: 10,
md: 8,
sm: 8,
} : {
span: 14,
md: 10,
sm: 8,
};
2021-03-22 14:29:03 -07:00
return (
<Header className="app-top-bar">
<Row>
2022-01-16 09:53:36 -08:00
<Col span={0} md={4} sm={0} />
2022-01-09 14:33:38 -08:00
{tuneId ? tabs : <Col span={10} md={10} sm={16} />}
<Col {...rightMenuColProps} style={{ textAlign: 'right' }}>
<Space>
{sm && <Tooltip title={
2022-01-23 10:35:26 -08:00
isFirefox ?
(<>
<Typography.Text keyboard>{isMac ? '⌘' : 'CTRL'}</Typography.Text>
<Typography.Text keyboard>K</Typography.Text>
</>)
:
(<>
<Typography.Text keyboard>{isMac ? '⌘' : 'CTRL'}</Typography.Text>
<Typography.Text keyboard>SHIFT</Typography.Text>
<Typography.Text keyboard>P</Typography.Text>
</>)
2021-03-22 14:29:03 -07:00
}>
<Button icon={<SearchOutlined />} onClick={toggleCommandPalette} />
2022-01-16 09:53:36 -08:00
</Tooltip>}
2022-01-02 13:25:52 -08:00
<Link to={Routes.UPLOAD}>
2022-01-09 14:33:38 -08:00
<Button icon={<CloudUploadOutlined />} type={matchedTabPath?.url === Routes.UPLOAD ? 'primary' : 'default'}>
2022-01-02 13:25:52 -08:00
{lg && 'Upload'}
</Button>
</Link>
2021-03-22 14:29:03 -07:00
<Dropdown
2022-01-02 13:25:52 -08:00
overlay={
<Menu disabled>
2022-01-02 13:25:52 -08:00
<SubMenu key="tune-sub" title="Tune" icon={<SlidersOutlined />}>
<Menu.Item key="download" icon={<SaveOutlined />}>
<a href="/tunes/202103.msq" target="__blank" rel="noopener noreferrer">
Download
</a>
</Menu.Item>
<Menu.Item key="open" disabled icon={<DesktopOutlined />}>
Open in app
</Menu.Item>
</SubMenu>
<SubMenu key="logs-sub" title="Logs" icon={<LineChartOutlined />}>
<Menu.Item key="mlg" disabled icon={<FileZipOutlined />}>
MLG
</Menu.Item>
<Menu.Item key="msl" disabled icon={<FileTextOutlined />}>
MSL
</Menu.Item>
<Menu.Item key="csv" disabled icon={<FileExcelOutlined />}>
CSV
</Menu.Item>
</SubMenu>
</Menu>
}
2021-03-22 14:29:03 -07:00
placement="bottomCenter"
2021-03-23 12:36:06 -07:00
trigger={['click']}
2021-03-22 14:29:03 -07:00
>
2022-01-02 13:25:52 -08:00
<Button icon={<CloudDownloadOutlined />}>
{lg && 'Download'}
2022-01-16 09:53:36 -08:00
{sm && <DownOutlined />}
2021-03-22 14:29:03 -07:00
</Button>
</Dropdown>
<Dropdown
2022-01-02 13:25:52 -08:00
overlay={
<Menu>
{currentUser ? (
<Menu.Item key="logout" icon={<LogoutOutlined />} onClick={logoutClick}>
Logout
</Menu.Item>
) : (
<>
<Menu.Item key="login" icon={<LoginOutlined />}>
<Link to={Routes.LOGIN}>Login</Link>
</Menu.Item>
<Menu.Item key="sign-up" icon={<UserAddOutlined />}>
<Link to={Routes.SIGN_UP}>Sign Up</Link>
</Menu.Item>
</>
)}
<Menu.Item key="preferences" disabled icon={<SettingOutlined />}>
Preferences
</Menu.Item>
</Menu>
}
2021-03-22 14:29:03 -07:00
placement="bottomCenter"
2021-03-23 12:36:06 -07:00
trigger={['click']}
2021-03-22 14:29:03 -07:00
>
<Button icon={<UserOutlined />}>
2022-01-16 09:53:36 -08:00
{sm && <DownOutlined />}
2021-03-22 14:29:03 -07:00
</Button>
</Dropdown>
</Space>
</Col>
</Row>
</Header>
);
};
export default TopBar;