This commit is contained in:
Josh Stewart 2022-10-30 20:31:20 +11:00
commit b463809aa6
16 changed files with 5146 additions and 129 deletions

5
.env
View File

@ -1,6 +1,11 @@
NPM_GITHUB_TOKEN=
VITE_ENVIRONMENT=development
VITE_WEB_URL=http://localhost:5173
VITE_SENTRY_DSN=
VITE_GTM_ID=
VITE_POCKETBASE_API_URL="https://api.hypertuner.cloud"
VITE_META_TITLE="HyperTuner Cloud"
VITE_META_DESCRIPTION="The best way to share your Speeduino and rusEFI tunes and logs"
VITE_META_THEME_COLOR="#191C1E"

View File

@ -6,7 +6,7 @@
<div align="center">
<p><a href="https://hypertuner.cloud"><strong>hypertuner.cloud</strong></a></p>
<p><sub>The best way to share your tunes and logs</sub></p>
<p><sub>The best way to share your tunes and logs.</sub></p>
</div>
<br/>
@ -22,8 +22,6 @@
</p>
</div>
<div align="center"><p>🚧 Work in progress 🚧</p></div>
<br/>
![Screenshot VE Table](/public/img/screen1.png)
@ -32,6 +30,10 @@
![Screenshot Logs](/public/img/screen2.png)
<br/>
![Screenshot Tooth](/public/img/screen3.png)
## Supported ECUs
### Speeduino
@ -39,6 +41,18 @@
- Source code: [noisymime/speeduino](https://github.com/noisymime/speeduino)
- Documentation: [wiki.speeduino.com](https://wiki.speeduino.com/)
## Support this project
[GitHub Sponsors](https://github.com/sponsors/karniv00l)
## Discord server
[![HyperTuner Discord server](https://dcbadge.vercel.app/api/server/HdxznPUA)](https://discord.gg/HdxznPUA)
## Development
Before you begin please see [Development guide](https://github.com/hyper-tuner/hyper-tuner-cloud/blob/master/DEVELOPMENT.md).
## License
[MIT](https://github.com/hyper-tuner/hyper-tuner-cloud/blob/master/LICENSE)

4985
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,8 @@
"pocketbase-typegen": "^1.0.11",
"prettier": "^2.7.1",
"rollup-plugin-visualizer": "^5.8.3",
"typescript": "^4.8.4"
"typescript": "^4.8.4",
"vite-plugin-html": "^3.2.0",
"vite-plugin-pwa": "^0.13.1"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 140 KiB

BIN
public/img/screen3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -1,37 +0,0 @@
{
"short_name": "HyperTuner Cloud",
"name": "HyperTuner Cloud",
"description": "The best way to share your Speeduino and rusEFI tunes and logs",
"icons": [
{
"src": "/icons/icon.ico",
"type": "image/x-icon",
"sizes": "256x256"
},
{
"src": "/icons/icon.png",
"type": "image/png",
"sizes": "512x512"
}
],
"screenshots" : [
{
"src": "/img/screen2.png",
"sizes": "1920x1194",
"type": "image/png",
"platform": "wide",
"label": "Log viewer"
},
{
"src": "/img/screen1.png",
"sizes": "1920x1194",
"type": "image/png",
"platform": "wide",
"label": "VE Table with command palette"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#191C1E",
"background_color": "#191C1E"
}

View File

@ -62,6 +62,7 @@ const ResetPassword = lazy(() => import('./pages/auth/ResetPassword'));
const ResetPasswordConfirmation = lazy(() => import('./pages/auth/ResetPasswordConfirmation'));
const EmailVerification = lazy(() => import('./pages/auth/EmailVerification'));
const OauthCallback = lazy(() => import('./pages/auth/OauthCallback'));
const About = lazy(() => import('./pages/About'));
const { Content } = Layout;
@ -200,6 +201,7 @@ const App = ({ ui, tuneData }: { ui: UIState, tuneData: TuneDataState }) => {
<Route path={Routes.SIGN_UP} element={<ContentFor element={<Login formRole={FormRoles.SING_UP} />} />} />
<Route path={Routes.PROFILE} element={<ContentFor element={<Profile />} />} />
<Route path={Routes.RESET_PASSWORD} element={<ContentFor element={<ResetPassword />} />} />
<Route path={Routes.ABOUT} element={<ContentFor element={<About />} />} />
<Route path={Routes.EMAIL_VERIFICATION} element={<ContentFor element={<EmailVerification />} />} />
<Route path={Routes.RESET_PASSWORD_CONFIRMATION} element={<ContentFor element={<ResetPasswordConfirmation />} />} />

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -2,6 +2,7 @@ import {
useEffect,
useState,
} from 'react';
import { Link } from 'react-router-dom';
import {
Layout,
Space,
@ -18,6 +19,7 @@ import {
AppState,
TuneState,
} from '../types/state';
import { Routes } from '../routes';
const { Footer } = Layout;
@ -55,16 +57,12 @@ const StatusBar = ({ tune }: { tune: TuneState }) => (
{tune?.details?.author && <Firmware tune={tune} />}
</Col>
<Col span={4} style={{ textAlign: 'right' }}>
<a
href="https://github.com/hyper-tuner/hyper-tuner-cloud"
target="__blank"
rel="noopener noreferrer"
>
<Space className="github-link">
<Link to={Routes.ABOUT}>
<Space>
<GithubOutlined />
GitHub
</Space>
</a>
</Link>
</Col>
</Row>
</Footer>

View File

@ -226,7 +226,7 @@ const TopBar = ({
return list.length ? list : null;
}, [lg, sm]);
const userMenuItems = useMemo(() => currentUser ? [{
const userAuthMenuItems = useMemo(() => currentUser ? [{
key: 'profile',
icon: <UserOutlined />,
label: 'Profile',
@ -248,6 +248,20 @@ const TopBar = ({
onClick: () => navigate(Routes.SIGN_UP),
}], [currentUser, logoutClick, navigate]);
const userMenuItems = [
...userAuthMenuItems,
{
key: 'divider',
type: 'divider',
},
{
key: 'about',
icon: <InfoCircleOutlined />,
label: 'About',
onClick: () => navigate(Routes.ABOUT),
},
];
return (
<Header className="app-top-bar" style={xs ? { padding: '0 5px' } : {}}>
<Row>

View File

@ -8,6 +8,7 @@
body {
overflow: hidden;
background-color: @main-dark;
}
html, body {
@ -46,10 +47,6 @@ html, body {
a:hover {
text-decoration: underline;
}
.github-link {
animation: wiggle 2s linear 2;
}
}
.app-sidebar {
@ -194,3 +191,7 @@ select:-webkit-autofill:focus {
resize: none;
}
}
.sponsor-button {
animation: wiggle 2s linear 1;
}

49
src/pages/About.tsx Normal file
View File

@ -0,0 +1,49 @@
import {
Button,
Result,
} from 'antd';
import {
HeartOutlined,
GithubOutlined,
} from '@ant-design/icons';
import hyperIcon from '../assets/img/hyper-tuner-logo.png';
const About = () => (
<div className="large-container">
<Result
status="success"
icon={<img src={hyperIcon} alt="HyperTuner" style={{ maxWidth: 100 }} />}
title={
<>
Powered by <a href="https://github.com/hyper-tuner" target="_blank" rel="noreferrer">HyperTuner</a>
</>
}
subTitle={
<>
Created with <HeartOutlined /> by <a href="https://github.com/karniv00l" target="_blank" rel="noreferrer">Piotr Rogowski</a>,
licensed under <a href="https://github.com/hyper-tuner/hyper-tuner-cloud/blob/master/LICENSE" target="_blank" rel="noreferrer">MIT</a>.
</>
}
extra={[
<Button
type="primary"
key="sponsor"
className="sponsor-button"
icon={<HeartOutlined />}
onClick={() => window.open('https://github.com/sponsors/karniv00l', '_blank')}
>
Sponsor
</Button>,
<Button
key="source"
icon={<GithubOutlined />}
onClick={() => window.open('https://github.com/hyper-tuner/hyper-tuner-cloud', '_blank')}
>
Source
</Button>,
]}
/>
</div>
);
export default About;

View File

@ -25,5 +25,7 @@ export enum Routes {
EMAIL_VERIFICATION = '/auth/email-verification/:token',
OAUTH_CALLBACK = '/auth/oauth-callback/:provider',
ABOUT = '/about',
REDIRECT_PAGE_OAUTH_CALLBACK = 'oauth',
}

View File

@ -1,40 +1,108 @@
import { defineConfig } from 'vite';
import {
defineConfig,
loadEnv,
} from 'vite';
import react from '@vitejs/plugin-react';
import { visualizer } from 'rollup-plugin-visualizer';
import { createHtmlPlugin } from 'vite-plugin-html';
import { VitePWA } from 'vite-plugin-pwa';
// https://vitejs.dev/config/
export default defineConfig({
build: {
outDir: 'build',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
react: ['react', 'react-dom'],
antdResult: ['antd/es/result'],
antdTable: ['antd/es/table'],
antdIcons: ['@ant-design/icons'],
uplot: ['uplot'],
sentry: ['@sentry/react', '@sentry/browser', '@sentry/tracing'],
kbar: ['kbar'],
perfectScrollbar: ['perfect-scrollbar'],
pako: ['pako'],
mlgConverter: ['mlg-converter'],
export default ({ mode }) => {
const env = loadEnv(mode, process.cwd());
return defineConfig({
build: {
outDir: 'build',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
react: ['react', 'react-dom'],
antdResult: ['antd/es/result'],
antdTable: ['antd/es/table'],
antdIcons: ['@ant-design/icons'],
uplot: ['uplot'],
sentry: ['@sentry/react', '@sentry/browser', '@sentry/tracing'],
kbar: ['kbar'],
perfectScrollbar: ['perfect-scrollbar'],
pako: ['pako'],
mlgConverter: ['mlg-converter'],
},
},
},
},
},
server: {
open: true,
host: '0.0.0.0',
},
css: {
preprocessorOptions: {
less: { javascriptEnabled: true },
server: {
open: true,
host: '0.0.0.0',
},
},
plugins: [
react(),
visualizer(),
],
});
css: {
preprocessorOptions: {
less: { javascriptEnabled: true },
},
},
plugins: [
react(),
visualizer(),
createHtmlPlugin({
template: '/index.html',
inject: {
data: {
metaTitle: env.VITE_META_TITLE,
metaDescription: env.VITE_META_DESCRIPTION,
metaImage: `${env.VITE_WEB_URL}/img/screen2.png`,
metaUrl: env.VITE_WEB_URL,
metaThemeColor: env.VITE_META_THEME_COLOR,
},
},
}),
VitePWA({
registerType: null,
devOptions: { enabled: true },
manifest: {
name: env.VITE_META_TITLE,
short_name: env.VITE_META_TITLE,
description: env.VITE_META_DESCRIPTION,
start_url: '.',
display: 'standalone',
theme_color: env.VITE_META_THEME_COLOR,
background_color: env.VITE_META_THEME_COLOR,
icons: [
{
src: '/icons/icon.ico',
type: 'image/x-icon',
sizes: '256x256',
},
{
src: '/icons/icon.png',
type: 'image/png',
sizes: '512x512',
},
],
screenshots: [
{
src: '/img/screen1.png',
sizes: '3008x2050',
type: 'image/png',
platform: 'wide',
label: 'Tune view',
},
{
src: '/img/screen2.png',
sizes: '3008x2050',
type: 'image/png',
platform: 'wide',
label: 'Log viewer',
},
{
src: '/img/screen3.png',
sizes: '3008x2050',
type: 'image/png',
platform: 'wide',
label: 'Tooth log viewer',
},
],
},
}),
],
});
};