Download tune and logs (#857)
This commit is contained in:
parent
2fc6398b1e
commit
49d659f817
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"cSpell.words": [
|
||||
"hypertuner",
|
||||
"kbar",
|
||||
"pocketbase",
|
||||
"prefs",
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
/* eslint-disable jsx-a11y/anchor-is-valid */
|
||||
/* eslint-disable jsx-a11y/anchor-has-content */
|
||||
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import {
|
||||
useLocation,
|
||||
|
@ -31,10 +35,7 @@ import {
|
|||
LoginOutlined,
|
||||
LineChartOutlined,
|
||||
SlidersOutlined,
|
||||
FileExcelOutlined,
|
||||
FileTextOutlined,
|
||||
FileZipOutlined,
|
||||
SaveOutlined,
|
||||
DesktopOutlined,
|
||||
DownOutlined,
|
||||
SearchOutlined,
|
||||
|
@ -44,6 +45,8 @@ import {
|
|||
LogoutOutlined,
|
||||
InfoCircleOutlined,
|
||||
CarOutlined,
|
||||
FileTextOutlined,
|
||||
FileExcelOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { useKBar } from 'kbar';
|
||||
import store from '../store';
|
||||
|
@ -53,10 +56,17 @@ import { Routes } from '../routes';
|
|||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { logOutSuccessful } from '../pages/auth/notifications';
|
||||
import { TuneDataState } from '../types/state';
|
||||
import { removeFilenameSuffix } from '../pocketbase';
|
||||
import useServerStorage from '../hooks/useServerStorage';
|
||||
|
||||
const { Header } = Layout;
|
||||
const { useBreakpoint } = Grid;
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
const logsExtensionsIcons: { [key: string]: any } = {
|
||||
'mlg': <FileZipOutlined />,
|
||||
'msl': <FileTextOutlined />,
|
||||
'csv': <FileExcelOutlined />,
|
||||
};
|
||||
|
||||
const TopBar = ({
|
||||
tuneData,
|
||||
|
@ -77,6 +87,8 @@ const TopBar = ({
|
|||
const tabMatch = useMatch(`${Routes.TUNE_TAB}/*`);
|
||||
const uploadMatch = useMatch(Routes.UPLOAD);
|
||||
const hubMatch = useMatch(Routes.HUB);
|
||||
const { downloadFile } = useServerStorage();
|
||||
const downloadAnchorRef = useRef<HTMLAnchorElement | null>(null);
|
||||
const logoutClick = useCallback(() => {
|
||||
logout();
|
||||
logOutSuccessful();
|
||||
|
@ -92,6 +104,54 @@ const TopBar = ({
|
|||
}
|
||||
}, []);
|
||||
|
||||
const downloadLogsItems = {
|
||||
label: 'Logs',
|
||||
icon: <LineChartOutlined />,
|
||||
key: 'logs',
|
||||
children: (tuneData?.logFiles || []).map((filename) => ({
|
||||
key: filename,
|
||||
label: removeFilenameSuffix(filename),
|
||||
icon: logsExtensionsIcons[filename.slice(-3)],
|
||||
onClick: () => downloadFile(tuneData!.id, filename, downloadAnchorRef.current!),
|
||||
})),
|
||||
};
|
||||
|
||||
const downloadToothLogsItems = {
|
||||
label: 'Tooth logs',
|
||||
icon: <SettingOutlined />,
|
||||
key: 'toothLogs',
|
||||
children: (tuneData?.toothLogFiles || []).map((filename) => ({
|
||||
key: filename,
|
||||
label: removeFilenameSuffix(filename),
|
||||
icon: logsExtensionsIcons[filename.slice(-3)],
|
||||
onClick: () => downloadFile(tuneData!.id, filename, downloadAnchorRef.current!),
|
||||
})),
|
||||
};
|
||||
|
||||
const downloadItems = [
|
||||
{
|
||||
label: 'Tune',
|
||||
icon: <SlidersOutlined />,
|
||||
key: 'tune',
|
||||
children: [
|
||||
{
|
||||
label: 'Download',
|
||||
icon: <FileTextOutlined />,
|
||||
key: 'download',
|
||||
onClick: () => downloadFile(tuneData!.id, tuneData!.tuneFile, downloadAnchorRef.current!),
|
||||
},
|
||||
{
|
||||
label: 'Open in app',
|
||||
icon: <DesktopOutlined />,
|
||||
key: 'open',
|
||||
onClick: () => window.open(`hypertuner://hypertuner.cloud/t/${tuneData!.tuneId}`, '_blank'),
|
||||
},
|
||||
],
|
||||
},
|
||||
(tuneData?.logFiles || []).length > 0 ? { ...downloadLogsItems } : null,
|
||||
(tuneData?.toothLogFiles || []).length > 0 ? { ...downloadToothLogsItems } : null,
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('keydown', handleGlobalKeyboard);
|
||||
|
||||
|
@ -212,31 +272,9 @@ const TopBar = ({
|
|||
{lg && 'Upload'}
|
||||
</Button>
|
||||
</Link>
|
||||
<Dropdown
|
||||
{tuneData?.tuneId && <Dropdown
|
||||
overlay={
|
||||
<Menu disabled>
|
||||
<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>
|
||||
<Menu triggerSubMenuAction="click" items={downloadItems} />
|
||||
}
|
||||
placement="bottom"
|
||||
trigger={['click']}
|
||||
|
@ -244,7 +282,7 @@ const TopBar = ({
|
|||
<Button icon={<CloudDownloadOutlined />}>
|
||||
{downloadButton}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</Dropdown>}
|
||||
<Dropdown
|
||||
overlay={<Menu items={userMenuItems} />}
|
||||
placement="bottomRight"
|
||||
|
@ -254,6 +292,8 @@ const TopBar = ({
|
|||
{sm && <DownOutlined />}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
{/* dummy anchor for file download */}
|
||||
<a ref={downloadAnchorRef} style={{ display: 'none' }} />
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import Pako from 'pako';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { API_URL } from '../pocketbase';
|
||||
import {
|
||||
API_URL,
|
||||
removeFilenameSuffix,
|
||||
} from '../pocketbase';
|
||||
import { Collections } from '../@types/pocketbase-types';
|
||||
import useDb from './useDb';
|
||||
import {
|
||||
fetchWithProgress,
|
||||
OnProgress,
|
||||
} from '../utils/http';
|
||||
import { downloading } from '../pages/auth/notifications';
|
||||
|
||||
const useServerStorage = () => {
|
||||
const { getIni } = useDb();
|
||||
|
@ -43,10 +47,28 @@ const useServerStorage = () => {
|
|||
signal,
|
||||
).then((response) => response);
|
||||
|
||||
const downloadFile = async (recordId: string, filename: string, anchorRef: HTMLAnchorElement) => {
|
||||
downloading();
|
||||
|
||||
const response = await fetch(buildFileUrl(Collections.Tunes, recordId, filename));
|
||||
const data = Pako.inflate(new Uint8Array(await response.arrayBuffer()));
|
||||
const url = window.URL.createObjectURL(new Blob([data]));
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
anchorRef.href = url;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
anchorRef.target = '_blank';
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
anchorRef.download = removeFilenameSuffix(filename);
|
||||
anchorRef.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
return {
|
||||
fetchTuneFile: (recordId: string, filename: string): Promise<ArrayBuffer> => fetchTuneFile(recordId, filename),
|
||||
fetchINIFile: (signature: string): Promise<ArrayBuffer> => fetchINIFile(signature),
|
||||
fetchLogFileWithProgress: (recordId: string, filename: string, onProgress?: OnProgress, signal?: AbortSignal): Promise<ArrayBuffer> => fetchLogFileWithProgress(recordId, filename, onProgress, signal),
|
||||
downloadFile: (recordId: string, filename: string, anchorRef: HTMLAnchorElement): Promise<void> => downloadFile(recordId, filename, anchorRef),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -147,6 +147,12 @@ const signatureNotSupportedWarning = (message: string) => notification.warning({
|
|||
...baseOptions,
|
||||
});
|
||||
|
||||
const downloading = () => notification.success({
|
||||
message: 'Downloading...',
|
||||
...baseOptions,
|
||||
duration: 1,
|
||||
});
|
||||
|
||||
export {
|
||||
error,
|
||||
emailNotVerified,
|
||||
|
@ -172,4 +178,5 @@ export {
|
|||
iniLoadingError,
|
||||
tuneParsingError,
|
||||
signatureNotSupportedWarning,
|
||||
downloading,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue