Add profile page, refactor code (#421)
This commit is contained in:
parent
b4e7046aac
commit
f658c229f4
|
@ -34,7 +34,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@craco/craco": "^7.0.0-alpha.0",
|
"@craco/craco": "^7.0.0-alpha.0",
|
||||||
"@speedy-tuner/eslint-config": "^0.1.3",
|
"@speedy-tuner/eslint-config": "^0.1.3",
|
||||||
"@types/node": "^17.0.16",
|
"@types/node": "^17.0.17",
|
||||||
"@types/pako": "^1.0.3",
|
"@types/pako": "^1.0.3",
|
||||||
"@types/react": "^17.0.39",
|
"@types/react": "^17.0.39",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
@ -5093,9 +5093,9 @@
|
||||||
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
|
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "17.0.16",
|
"version": "17.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz",
|
||||||
"integrity": "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA=="
|
"integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/pako": {
|
"node_modules/@types/pako": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
@ -24138,9 +24138,9 @@
|
||||||
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
|
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "17.0.16",
|
"version": "17.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz",
|
||||||
"integrity": "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA=="
|
"integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw=="
|
||||||
},
|
},
|
||||||
"@types/pako": {
|
"@types/pako": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@craco/craco": "^7.0.0-alpha.0",
|
"@craco/craco": "^7.0.0-alpha.0",
|
||||||
"@speedy-tuner/eslint-config": "^0.1.3",
|
"@speedy-tuner/eslint-config": "^0.1.3",
|
||||||
"@types/node": "^17.0.16",
|
"@types/node": "^17.0.17",
|
||||||
"@types/pako": "^1.0.3",
|
"@types/pako": "^1.0.3",
|
||||||
"@types/react": "^17.0.39",
|
"@types/react": "^17.0.39",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
|
14
src/App.less
14
src/App.less
|
@ -64,6 +64,20 @@ html, body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.small-container,
|
||||||
|
.large-container {
|
||||||
|
padding: 20px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-container {
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-container {
|
||||||
|
max-width: 1400px;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-tabs-tabpane {
|
.ant-tabs-tabpane {
|
||||||
height: calc(100vh - @layout-header-height - @layout-footer-height - @layout-trigger-height - @tabs-nav-height);
|
height: calc(100vh - @layout-header-height - @layout-footer-height - @layout-trigger-height - @tabs-nav-height);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
81
src/App.tsx
81
src/App.tsx
|
@ -6,7 +6,6 @@ import {
|
||||||
import {
|
import {
|
||||||
Layout,
|
Layout,
|
||||||
Result,
|
Result,
|
||||||
Skeleton,
|
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
|
@ -22,7 +21,7 @@ import { Routes } from './routes';
|
||||||
import { loadTune } from './utils/api';
|
import { loadTune } from './utils/api';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
import Logs from './pages/Logs';
|
import Logs from './pages/Logs';
|
||||||
import './App.less';
|
import Loader from './components/Loader';
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
|
@ -33,6 +32,7 @@ import Info from './pages/Info';
|
||||||
import Hub from './pages/Hub';
|
import Hub from './pages/Hub';
|
||||||
|
|
||||||
import 'react-perfect-scrollbar/dist/css/styles.css';
|
import 'react-perfect-scrollbar/dist/css/styles.css';
|
||||||
|
import './App.less';
|
||||||
|
|
||||||
// TODO: fix this
|
// TODO: fix this
|
||||||
// lazy loading this component causes a weird Curve canvas scaling
|
// lazy loading this component causes a weird Curve canvas scaling
|
||||||
|
@ -41,6 +41,7 @@ import 'react-perfect-scrollbar/dist/css/styles.css';
|
||||||
const Tune = lazy(() => import('./pages/Tune'));
|
const Tune = lazy(() => import('./pages/Tune'));
|
||||||
const Diagnose = lazy(() => import('./pages/Diagnose'));
|
const Diagnose = lazy(() => import('./pages/Diagnose'));
|
||||||
const Login = lazy(() => import('./pages/auth/Login'));
|
const Login = lazy(() => import('./pages/auth/Login'));
|
||||||
|
const Profile = lazy(() => import('./pages/auth/Profile'));
|
||||||
const SignUp = lazy(() => import('./pages/auth/SignUp'));
|
const SignUp = lazy(() => import('./pages/auth/SignUp'));
|
||||||
const ResetPassword = lazy(() => import('./pages/auth/ResetPassword'));
|
const ResetPassword = lazy(() => import('./pages/auth/ResetPassword'));
|
||||||
const Upload = lazy(() => import('./pages/Upload'));
|
const Upload = lazy(() => import('./pages/Upload'));
|
||||||
|
@ -84,22 +85,15 @@ const App = ({ ui, navigation }: { ui: UIState, navigation: NavigationState }) =
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [tuneId]);
|
}, [tuneId]);
|
||||||
|
|
||||||
const ContentFor = useCallback((props: { children: ReactNode, marginLeft?: number }) => {
|
const ContentFor = useCallback((props: { element: ReactNode, marginLeft?: number }) => {
|
||||||
const { children, marginLeft } = props;
|
const { element, marginLeft } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout style={{ marginLeft }}>
|
<Layout style={{ marginLeft }}>
|
||||||
<Layout className="app-content">
|
<Layout className="app-content">
|
||||||
<Content>
|
<Content>
|
||||||
<Suspense fallback={<Skeleton
|
<Suspense fallback={<Loader />}>
|
||||||
active
|
{element}
|
||||||
style={{
|
|
||||||
maxWidth: 600,
|
|
||||||
margin: '0 auto',
|
|
||||||
padding: 20,
|
|
||||||
}}
|
|
||||||
/>}>
|
|
||||||
{children}
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -112,57 +106,18 @@ const App = ({ ui, navigation }: { ui: UIState, navigation: NavigationState }) =
|
||||||
<Layout>
|
<Layout>
|
||||||
<TopBar tuneId={navigation.tuneId} />
|
<TopBar tuneId={navigation.tuneId} />
|
||||||
<ReactRoutes>
|
<ReactRoutes>
|
||||||
<Route path={Routes.ROOT} element={
|
<Route path={Routes.HUB} element={<ContentFor element={<Hub />} />} />
|
||||||
<ContentFor>
|
<Route path={Routes.TUNE_ROOT} element={<ContentFor element={<Info />} />} />
|
||||||
<Hub />
|
<Route path={`${Routes.TUNE_TUNE}/*`} element={<ContentFor marginLeft={margin} element={<Tune />} />} />
|
||||||
</ContentFor>
|
<Route path={Routes.TUNE_LOGS} element={<ContentFor marginLeft={margin} element={<Logs />} />} />
|
||||||
} />
|
<Route path={Routes.TUNE_DIAGNOSE} element={<ContentFor marginLeft={margin} element={<Diagnose />} />} />
|
||||||
<Route path={Routes.TUNE_ROOT} element={
|
<Route path={Routes.LOGIN} element={<ContentFor element={<Login />} />} />
|
||||||
<ContentFor>
|
<Route path={Routes.PROFILE} element={<ContentFor element={<Profile />} />} />
|
||||||
<Info />
|
<Route path={Routes.SIGN_UP} element={<ContentFor element={<SignUp />} />} />
|
||||||
</ContentFor>
|
<Route path={Routes.RESET_PASSWORD} element={<ContentFor element={<ResetPassword />} />} />
|
||||||
} />
|
<Route path={Routes.UPLOAD} element={<ContentFor element={<Upload />} />} />
|
||||||
<Route path={`${Routes.TUNE_TUNE}/*`} element={
|
|
||||||
<ContentFor marginLeft={margin}>
|
|
||||||
<Tune />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.TUNE_LOGS} element={
|
|
||||||
<ContentFor marginLeft={margin}>
|
|
||||||
<Logs />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.TUNE_DIAGNOSE} element={
|
|
||||||
<ContentFor marginLeft={margin}>
|
|
||||||
<Diagnose />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.LOGIN} element={
|
|
||||||
<ContentFor>
|
|
||||||
<Login />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.SIGN_UP} element={
|
|
||||||
<ContentFor>
|
|
||||||
<SignUp />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.RESET_PASSWORD} element={
|
|
||||||
<ContentFor>
|
|
||||||
<ResetPassword />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
<Route path={Routes.UPLOAD} element={
|
|
||||||
<ContentFor>
|
|
||||||
<Upload />
|
|
||||||
</ContentFor>
|
|
||||||
} />
|
|
||||||
</ReactRoutes>
|
</ReactRoutes>
|
||||||
<Result
|
<Result status="warning" title="Page not found" style={{ marginTop: 50 }} />
|
||||||
status="warning"
|
|
||||||
title="Page not found"
|
|
||||||
style={{ marginTop: 50 }}
|
|
||||||
/>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -322,7 +322,7 @@ const CommandPalette = (props: CommandPaletteProps) => {
|
||||||
name: 'Hub',
|
name: 'Hub',
|
||||||
subtitle: 'Public tunes and logs.',
|
subtitle: 'Public tunes and logs.',
|
||||||
icon: <CarOutlined />,
|
icon: <CarOutlined />,
|
||||||
perform: () => navigate(Routes.ROOT),
|
perform: () => navigate(Routes.HUB),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ToggleSidebar',
|
id: 'ToggleSidebar',
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Skeleton } from 'antd';
|
||||||
|
|
||||||
|
const Loader = () => (
|
||||||
|
<div className="small-container">
|
||||||
|
<Skeleton active />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Loader;
|
|
@ -17,9 +17,9 @@ import {
|
||||||
import LandscapeNotice from '../Tune/Dialog/LandscapeNotice';
|
import LandscapeNotice from '../Tune/Dialog/LandscapeNotice';
|
||||||
import { Colors } from '../../utils/colors';
|
import { Colors } from '../../utils/colors';
|
||||||
import touchZoomPlugin from '../../utils/uPlot/touchZoomPlugin';
|
import touchZoomPlugin from '../../utils/uPlot/touchZoomPlugin';
|
||||||
|
import { isNumber } from '../../utils/tune/expression';
|
||||||
|
|
||||||
import 'uplot/dist/uPlot.min.css';
|
import 'uplot/dist/uPlot.min.css';
|
||||||
import { isNumber } from '../../utils/tune/expression';
|
|
||||||
|
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
|
|
|
@ -73,20 +73,22 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { query } = useKBar();
|
const { query } = useKBar();
|
||||||
const buildTuneUrl = useCallback((route: string) => tuneId ? generatePath(route, { tuneId }) : null, [tuneId]);
|
const buildTuneUrl = useCallback((route: string) => tuneId ? generatePath(route, { tuneId }) : null, [tuneId]);
|
||||||
const rootPathMatch = useMatch(Routes.ROOT);
|
const hubPathMatch = useMatch(Routes.HUB);
|
||||||
const tuneRootMatch = useMatch(`${Routes.TUNE_ROOT}/*`);
|
const tuneRootMatch = useMatch(`${Routes.TUNE_ROOT}/*`);
|
||||||
const tuneTuneMatch = useMatch(`${Routes.TUNE_TUNE}/*`);
|
const tuneTuneMatch = useMatch(`${Routes.TUNE_TUNE}/*`);
|
||||||
const tabMatch = useMatch(`${Routes.TUNE_TAB}/*`);
|
const tabMatch = useMatch(`${Routes.TUNE_TAB}/*`);
|
||||||
const uploadMatch = useMatch(Routes.UPLOAD);
|
const uploadMatch = useMatch(Routes.UPLOAD);
|
||||||
|
const hubMatch = useMatch(Routes.HUB);
|
||||||
const logoutClick = useCallback(async () => {
|
const logoutClick = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
await logout();
|
navigate(Routes.HUB);
|
||||||
|
logout();
|
||||||
logOutSuccessful();
|
logOutSuccessful();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
logOutFailed(error as Error);
|
logOutFailed(error as Error);
|
||||||
}
|
}
|
||||||
}, [logout]);
|
}, [logout, navigate]);
|
||||||
|
|
||||||
const toggleCommandPalette = useCallback(() => query.toggle(), [query]);
|
const toggleCommandPalette = useCallback(() => query.toggle(), [query]);
|
||||||
|
|
||||||
|
@ -109,15 +111,15 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs = useMemo(() => (
|
const tabs = useMemo(() => (
|
||||||
<Col span={16} md={12} sm={16} style={{ textAlign: 'center' }}>
|
<Col span={16} md={16} sm={16}>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
key={pathname}
|
key={pathname}
|
||||||
defaultValue={tuneTuneMatch?.pathnameBase || tabMatch?.pathname || tuneRootMatch?.pathname || rootPathMatch?.pathname}
|
defaultValue={tuneTuneMatch?.pathnameBase || tabMatch?.pathname || tuneRootMatch?.pathname || hubPathMatch?.pathname}
|
||||||
optionType="button"
|
optionType="button"
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
onChange={(e) => navigate(e.target.value)}
|
onChange={(e) => navigate(e.target.value)}
|
||||||
>
|
>
|
||||||
<Radio.Button value={buildTuneUrl(Routes.ROOT)}>
|
<Radio.Button value={buildTuneUrl(Routes.HUB)}>
|
||||||
<Space>
|
<Space>
|
||||||
<CarOutlined />
|
<CarOutlined />
|
||||||
{lg && 'Hub'}
|
{lg && 'Hub'}
|
||||||
|
@ -149,7 +151,7 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Col>
|
</Col>
|
||||||
), [buildTuneUrl, lg, navigate, pathname, rootPathMatch?.pathname, tabMatch?.pathname, tuneRootMatch?.pathname, tuneTuneMatch?.pathnameBase]);
|
), [buildTuneUrl, lg, navigate, pathname, hubPathMatch?.pathname, tabMatch?.pathname, tuneRootMatch?.pathname, tuneTuneMatch?.pathnameBase]);
|
||||||
|
|
||||||
const rightMenuColProps = tuneId ? {
|
const rightMenuColProps = tuneId ? {
|
||||||
span: 8,
|
span: 8,
|
||||||
|
@ -178,8 +180,13 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
return (
|
return (
|
||||||
<Header className="app-top-bar">
|
<Header className="app-top-bar">
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={0} md={4} sm={0} />
|
{tuneId ? tabs : (
|
||||||
{tuneId ? tabs : <Col span={10} md={10} sm={16} />}
|
<Col span={10} md={14} sm={16}>
|
||||||
|
<Link to={Routes.HUB}>
|
||||||
|
<Button icon={<CarOutlined />} type={hubMatch ? 'primary' : 'default'}>Hub</Button>
|
||||||
|
</Link>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
<Col {...rightMenuColProps} style={{ textAlign: 'right' }}>
|
<Col {...rightMenuColProps} style={{ textAlign: 'right' }}>
|
||||||
<Space>
|
<Space>
|
||||||
{sm && <Tooltip title={
|
{sm && <Tooltip title={
|
||||||
|
@ -239,9 +246,14 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
overlay={
|
overlay={
|
||||||
<Menu>
|
<Menu>
|
||||||
{currentUser ? (
|
{currentUser ? (
|
||||||
|
<>
|
||||||
|
<Menu.Item key="profile" icon={<UserOutlined />}>
|
||||||
|
<Link to={Routes.PROFILE}>Profile</Link>
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item key="logout" icon={<LogoutOutlined />} onClick={logoutClick}>
|
<Menu.Item key="logout" icon={<LogoutOutlined />} onClick={logoutClick}>
|
||||||
Logout
|
Logout
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Menu.Item key="login" icon={<LoginOutlined />}>
|
<Menu.Item key="login" icon={<LoginOutlined />}>
|
||||||
|
@ -252,9 +264,6 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Menu.Item key="preferences" disabled icon={<SettingOutlined />}>
|
|
||||||
Preferences
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
placement="bottomCenter"
|
placement="bottomCenter"
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
Skeleton,
|
|
||||||
Divider,
|
Divider,
|
||||||
Col,
|
Col,
|
||||||
Row,
|
Row,
|
||||||
|
@ -43,6 +42,7 @@ import Map from './Dialog/Map';
|
||||||
import { evaluateExpression } from '../../utils/tune/expression';
|
import { evaluateExpression } from '../../utils/tune/expression';
|
||||||
import useBrowserStorage from '../../hooks/useBrowserStorage';
|
import useBrowserStorage from '../../hooks/useBrowserStorage';
|
||||||
import useConfig from '../../hooks/useConfig';
|
import useConfig from '../../hooks/useConfig';
|
||||||
|
import Loader from '../Loader';
|
||||||
|
|
||||||
interface DialogsAndCurves {
|
interface DialogsAndCurves {
|
||||||
[name: string]: DialogType | CurveType | TableType,
|
[name: string]: DialogType | CurveType | TableType,
|
||||||
|
@ -82,18 +82,6 @@ const mapStateToProps = (state: AppState) => ({
|
||||||
ui: state.ui,
|
ui: state.ui,
|
||||||
});
|
});
|
||||||
|
|
||||||
const containerStyle = {
|
|
||||||
padding: 20,
|
|
||||||
maxWidth: 1400,
|
|
||||||
width: '100%',
|
|
||||||
margin: '0 auto',
|
|
||||||
};
|
|
||||||
|
|
||||||
const skeleton = (<div style={containerStyle}>
|
|
||||||
<Skeleton active />
|
|
||||||
<Skeleton active />
|
|
||||||
</div>);
|
|
||||||
|
|
||||||
// TODO: refactor this
|
// TODO: refactor this
|
||||||
const Dialog = ({
|
const Dialog = ({
|
||||||
ui,
|
ui,
|
||||||
|
@ -364,7 +352,7 @@ const Dialog = ({
|
||||||
}, [isDataReady, url, ui.sidebarCollapsed]);
|
}, [isDataReady, url, ui.sidebarCollapsed]);
|
||||||
|
|
||||||
if (!isDataReady) {
|
if (!isDataReady) {
|
||||||
return skeleton;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialogConfig = config.dialogs[name];
|
const dialogConfig = config.dialogs[name];
|
||||||
|
@ -375,7 +363,7 @@ const Dialog = ({
|
||||||
if (!dialogConfig) {
|
if (!dialogConfig) {
|
||||||
if (curveConfig) {
|
if (curveConfig) {
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef} style={containerStyle}>
|
<div ref={containerRef} className="large-container">
|
||||||
<Divider>{curveConfig.title}</Divider>
|
<Divider>{curveConfig.title}</Divider>
|
||||||
{renderCurve(curveConfig)}
|
{renderCurve(curveConfig)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -384,7 +372,7 @@ const Dialog = ({
|
||||||
|
|
||||||
if (tableConfig) {
|
if (tableConfig) {
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef} style={containerStyle}>
|
<div ref={containerRef} className="large-container">
|
||||||
{renderHelp(tableConfig.help)}
|
{renderHelp(tableConfig.help)}
|
||||||
<Divider>{tableConfig.title}</Divider>
|
<Divider>{tableConfig.title}</Divider>
|
||||||
{renderTable(tableConfig)}
|
{renderTable(tableConfig)}
|
||||||
|
@ -402,7 +390,7 @@ const Dialog = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef} style={containerStyle}>
|
<div ref={containerRef} className="large-container">
|
||||||
{renderHelp(dialogConfig?.help)}
|
{renderHelp(dialogConfig?.help)}
|
||||||
<Form
|
<Form
|
||||||
labelCol={{ span: 10 }}
|
labelCol={{ span: 10 }}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
Layout,
|
Layout,
|
||||||
Menu,
|
Menu,
|
||||||
Skeleton,
|
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
|
@ -23,7 +22,6 @@ import {
|
||||||
import store from '../../store';
|
import store from '../../store';
|
||||||
import Icon from '../SideBar/Icon';
|
import Icon from '../SideBar/Icon';
|
||||||
import { Routes } from '../../routes';
|
import { Routes } from '../../routes';
|
||||||
import useConfig from '../../hooks/useConfig';
|
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
|
@ -77,7 +75,6 @@ const SideBar = ({ config, tune, ui, navigation, matchedPath }: SideBarProps) =>
|
||||||
collapsed: ui.sidebarCollapsed,
|
collapsed: ui.sidebarCollapsed,
|
||||||
onCollapse: (collapsed: boolean) => store.dispatch({ type: 'ui/sidebarCollapsed', payload: collapsed }),
|
onCollapse: (collapsed: boolean) => store.dispatch({ type: 'ui/sidebarCollapsed', payload: collapsed }),
|
||||||
} as any;
|
} as any;
|
||||||
const { isConfigReady } = useConfig(config);
|
|
||||||
const [menus, setMenus] = useState<any[]>([]);
|
const [menus, setMenus] = useState<any[]>([]);
|
||||||
|
|
||||||
const menusList = useCallback((types: MenusType) => (
|
const menusList = useCallback((types: MenusType) => (
|
||||||
|
@ -123,20 +120,6 @@ const SideBar = ({ config, tune, ui, navigation, matchedPath }: SideBarProps) =>
|
||||||
}
|
}
|
||||||
}, [config.menus, menusList, tune.constants]);
|
}, [config.menus, menusList, tune.constants]);
|
||||||
|
|
||||||
if (!isConfigReady) {
|
|
||||||
return (
|
|
||||||
<Sider {...siderProps} className="app-sidebar" >
|
|
||||||
<div style={{ paddingLeft: 10 }}>
|
|
||||||
<Skeleton active />
|
|
||||||
<Skeleton active />
|
|
||||||
<Skeleton active />
|
|
||||||
<Skeleton active />
|
|
||||||
<Skeleton active />
|
|
||||||
</div>
|
|
||||||
</Sider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider {...siderProps} className="app-sidebar">
|
<Sider {...siderProps} className="app-sidebar">
|
||||||
<PerfectScrollbar options={{ suppressScrollX: true }}>
|
<PerfectScrollbar options={{ suppressScrollX: true }}>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
import {
|
import {
|
||||||
Layout,
|
Layout,
|
||||||
Tabs,
|
Tabs,
|
||||||
Skeleton,
|
|
||||||
Progress,
|
Progress,
|
||||||
Steps,
|
Steps,
|
||||||
Space,
|
Space,
|
||||||
|
@ -44,6 +43,7 @@ import TriggerLogsParser, {
|
||||||
ToothLogEntry,
|
ToothLogEntry,
|
||||||
} from '../utils/logs/TriggerLogsParser';
|
} from '../utils/logs/TriggerLogsParser';
|
||||||
import ToothCanvas from '../components/TriggerLogs/ToothCanvas';
|
import ToothCanvas from '../components/TriggerLogs/ToothCanvas';
|
||||||
|
import Loader from '../components/Loader';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
|
@ -144,7 +144,7 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
|
||||||
<>
|
<>
|
||||||
<Sider {...(siderProps as any)} className="app-sidebar">
|
<Sider {...(siderProps as any)} className="app-sidebar">
|
||||||
{!logs && !loadedLogs.length ?
|
{!logs && !loadedLogs.length ?
|
||||||
<div style={{ padding: 20 }}><Skeleton active /></div>
|
<Loader />
|
||||||
:
|
:
|
||||||
!ui.sidebarCollapsed &&
|
!ui.sidebarCollapsed &&
|
||||||
<Tabs defaultActiveKey="files" style={{ marginLeft: 20 }}>
|
<Tabs defaultActiveKey="files" style={{ marginLeft: 20 }}>
|
||||||
|
|
|
@ -31,12 +31,6 @@ import { TuneDbData } from '../types/dbData';
|
||||||
import { Routes } from '../routes';
|
import { Routes } from '../routes';
|
||||||
import { generateShareUrl } from '../utils/url';
|
import { generateShareUrl } from '../utils/url';
|
||||||
|
|
||||||
const containerStyle = {
|
|
||||||
padding: 20,
|
|
||||||
maxWidth: 1200,
|
|
||||||
margin: '0 auto',
|
|
||||||
};
|
|
||||||
|
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
const loadingCards = (
|
const loadingCards = (
|
||||||
|
@ -60,6 +54,7 @@ const Hub = () => {
|
||||||
const [tunes, setTunes] = useState<TuneDbData[]>([]);
|
const [tunes, setTunes] = useState<TuneDbData[]>([]);
|
||||||
const [dataSource, setDataSource] = useState<any[]>([]);
|
const [dataSource, setDataSource] = useState<any[]>([]);
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const goToTune = (tuneId: string) => navigate(generatePath(Routes.TUNE_ROOT, { tuneId }));
|
const goToTune = (tuneId: string) => navigate(generatePath(Routes.TUNE_ROOT, { tuneId }));
|
||||||
|
|
||||||
|
@ -90,6 +85,7 @@ const Hub = () => {
|
||||||
publishedAt: new Date((tune.createdAt as Timestamp).seconds * 1000).toLocaleString(),
|
publishedAt: new Date((tune.createdAt as Timestamp).seconds * 1000).toLocaleString(),
|
||||||
stars: 0,
|
stars: 0,
|
||||||
})));
|
})));
|
||||||
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, [listTunes]);
|
}, [listTunes]);
|
||||||
|
|
||||||
|
@ -144,14 +140,14 @@ const Hub = () => {
|
||||||
}, []); // TODO: fix this
|
}, []); // TODO: fix this
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="large-container">
|
||||||
<Typography.Title>Hub</Typography.Title>
|
<Typography.Title>Hub</Typography.Title>
|
||||||
<Input style={{ marginBottom: 10, height: 50 }} placeholder="Search..." />
|
<Input style={{ marginBottom: 10, height: 40 }} placeholder="Search..." />
|
||||||
{md ?
|
{md ?
|
||||||
<Table dataSource={dataSource} columns={columns} />
|
<Table dataSource={dataSource} columns={columns} loading={isLoading} />
|
||||||
:
|
:
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{tunes.length === 0 ? loadingCards : (
|
{isLoading ? loadingCards : (
|
||||||
tunes.map((tune) => (
|
tunes.map((tune) => (
|
||||||
<Col span={16} sm={8} key={tune.tuneFile}>
|
<Col span={16} sm={8} key={tune.tuneFile}>
|
||||||
<Card
|
<Card
|
||||||
|
|
|
@ -7,19 +7,14 @@ import {
|
||||||
Input,
|
Input,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
TuneDataState,
|
TuneDataState,
|
||||||
} from '../types/state';
|
} from '../types/state';
|
||||||
|
import Loader from '../components/Loader';
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
const containerStyle = {
|
|
||||||
padding: 20,
|
|
||||||
maxWidth: 600,
|
|
||||||
margin: '0 auto',
|
|
||||||
};
|
|
||||||
const rowProps = { gutter: 10 };
|
const rowProps = { gutter: 10 };
|
||||||
const colProps = { span: 24, sm: 12 };
|
const colProps = { span: 24, sm: 12 };
|
||||||
|
|
||||||
|
@ -29,15 +24,11 @@ const mapStateToProps = (state: AppState) => ({
|
||||||
|
|
||||||
const Info = ({ tuneData }: { tuneData: TuneDataState }) => {
|
const Info = ({ tuneData }: { tuneData: TuneDataState }) => {
|
||||||
if (!tuneData.details) {
|
if (!tuneData.details) {
|
||||||
return (
|
return <Loader />;
|
||||||
<div style={containerStyle}>
|
|
||||||
<Skeleton active />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
<Divider>Details</Divider>
|
<Divider>Details</Divider>
|
||||||
<Form>
|
<Form>
|
||||||
<Row {...rowProps}>
|
<Row {...rowProps}>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
Tabs,
|
Tabs,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Row,
|
Row,
|
||||||
Skeleton,
|
|
||||||
Progress,
|
Progress,
|
||||||
Steps,
|
Steps,
|
||||||
Space,
|
Space,
|
||||||
|
@ -52,6 +51,7 @@ import {
|
||||||
AppState,
|
AppState,
|
||||||
UIState,
|
UIState,
|
||||||
} from '../types/state';
|
} from '../types/state';
|
||||||
|
import Loader from '../components/Loader';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
|
@ -220,7 +220,7 @@ const Logs = ({
|
||||||
<>
|
<>
|
||||||
<Sider {...(siderProps as any)} className="app-sidebar">
|
<Sider {...(siderProps as any)} className="app-sidebar">
|
||||||
{!logs && !loadedLogs.length ?
|
{!logs && !loadedLogs.length ?
|
||||||
<div style={{ padding: 20 }}><Skeleton active /></div>
|
<Loader />
|
||||||
:
|
:
|
||||||
!ui.sidebarCollapsed &&
|
!ui.sidebarCollapsed &&
|
||||||
<Tabs defaultActiveKey="fields" style={{ marginLeft: 20 }}>
|
<Tabs defaultActiveKey="fields" style={{ marginLeft: 20 }}>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { Skeleton } from 'antd';
|
|
||||||
import {
|
import {
|
||||||
generatePath,
|
generatePath,
|
||||||
useMatch,
|
useMatch,
|
||||||
|
@ -18,6 +17,7 @@ import {
|
||||||
AppState,
|
AppState,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
} from '../types/state';
|
} from '../types/state';
|
||||||
|
import Loader from '../components/Loader';
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState) => ({
|
const mapStateToProps = (state: AppState) => ({
|
||||||
navigation: state.navigation,
|
navigation: state.navigation,
|
||||||
|
@ -54,13 +54,8 @@ const Tune = ({ navigation, config }: { navigation: NavigationState, config: Con
|
||||||
}
|
}
|
||||||
}, [firstDialogPath, navigate, tuneRootMatch, isConfigReady]);
|
}, [firstDialogPath, navigate, tuneRootMatch, isConfigReady]);
|
||||||
|
|
||||||
// TODO: unify loading indicators across the app
|
|
||||||
if (!isConfigReady || !dialogMatch) {
|
if (!isConfigReady || !dialogMatch) {
|
||||||
return (
|
return <Loader />;
|
||||||
<div>
|
|
||||||
<Skeleton active />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
notification,
|
notification,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
|
||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Tabs,
|
Tabs,
|
||||||
|
@ -56,6 +55,7 @@ import LogParser from '../utils/logs/LogParser';
|
||||||
import useDb from '../hooks/useDb';
|
import useDb from '../hooks/useDb';
|
||||||
import useServerStorage from '../hooks/useServerStorage';
|
import useServerStorage from '../hooks/useServerStorage';
|
||||||
import { generateShareUrl } from '../utils/url';
|
import { generateShareUrl } from '../utils/url';
|
||||||
|
import Loader from '../components/Loader';
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
|
|
||||||
|
@ -83,11 +83,6 @@ interface ValidationResult {
|
||||||
|
|
||||||
type ValidateFile = (file: File) => Promise<ValidationResult>;
|
type ValidateFile = (file: File) => Promise<ValidationResult>;
|
||||||
|
|
||||||
const containerStyle = {
|
|
||||||
padding: 20,
|
|
||||||
maxWidth: 600,
|
|
||||||
margin: '0 auto',
|
|
||||||
};
|
|
||||||
const rowProps = { gutter: 10 };
|
const rowProps = { gutter: 10 };
|
||||||
const colProps = { span: 24, sm: 12 };
|
const colProps = { span: 24, sm: 12 };
|
||||||
|
|
||||||
|
@ -666,23 +661,19 @@ const UploadPage = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isUserAuthorized) {
|
if (!isUserAuthorized) {
|
||||||
return (
|
return <Loader />;
|
||||||
<div style={containerStyle}>
|
|
||||||
<Skeleton active />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPublished) {
|
if (isPublished) {
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
{shareSection}
|
{shareSection}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
<Form
|
<Form
|
||||||
onFinish={publish}
|
onFinish={publish}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
|
|
|
@ -27,7 +27,6 @@ import {
|
||||||
logInFailed,
|
logInFailed,
|
||||||
logInSuccessful,
|
logInSuccessful,
|
||||||
} from './notifications';
|
} from './notifications';
|
||||||
import { containerStyle } from './common';
|
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ const Login = () => {
|
||||||
const { login, googleAuth, githubAuth } = useAuth();
|
const { login, googleAuth, githubAuth } = useAuth();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isAnythingLoading = isEmailLoading || isGoogleLoading || isGithubLoading;
|
const isAnythingLoading = isEmailLoading || isGoogleLoading || isGithubLoading;
|
||||||
const redirectAfterLogin = useCallback(() => navigate(Routes.UPLOAD), [navigate]);
|
const redirectAfterLogin = useCallback(() => navigate(Routes.HUB), [navigate]);
|
||||||
|
|
||||||
const googleLogin = useCallback(async () => {
|
const googleLogin = useCallback(async () => {
|
||||||
setIsGoogleLoading(true);
|
setIsGoogleLoading(true);
|
||||||
|
@ -85,10 +84,9 @@ const Login = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
<Divider>Log In using email</Divider>
|
<Divider>Log In using email</Divider>
|
||||||
<Form
|
<Form
|
||||||
initialValues={{ remember: true }}
|
|
||||||
onFinish={emailLogin}
|
onFinish={emailLogin}
|
||||||
validateMessages={validateMessages}
|
validateMessages={validateMessages}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
|
} from 'antd';
|
||||||
|
import { UserOutlined } from '@ant-design/icons';
|
||||||
|
import validateMessages from './validateMessages';
|
||||||
|
import { useAuth } from '../../contexts/AuthContext';
|
||||||
|
import { restrictedPage } from './notifications';
|
||||||
|
import { Routes } from '../../routes';
|
||||||
|
|
||||||
|
const { Item } = Form;
|
||||||
|
|
||||||
|
const Profile = () => {
|
||||||
|
const { currentUser } = useAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!currentUser) {
|
||||||
|
restrictedPage();
|
||||||
|
navigate(Routes.LOGIN);
|
||||||
|
}
|
||||||
|
}, [currentUser, navigate]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="small-container">
|
||||||
|
<Divider>Your Profile</Divider>
|
||||||
|
<Form
|
||||||
|
validateMessages={validateMessages}
|
||||||
|
form={form}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Item
|
||||||
|
name="username"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
hasFeedback
|
||||||
|
>
|
||||||
|
<Input prefix={<UserOutlined />} placeholder="Username" />
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Profile;
|
|
@ -17,7 +17,6 @@ import {
|
||||||
resetFailed,
|
resetFailed,
|
||||||
resetSuccessful,
|
resetSuccessful,
|
||||||
} from './notifications';
|
} from './notifications';
|
||||||
import { containerStyle } from './common';
|
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ const ResetPassword = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
<Divider>Reset password</Divider>
|
<Divider>Reset password</Divider>
|
||||||
<Form
|
<Form
|
||||||
initialValues={{ remember: true }}
|
initialValues={{ remember: true }}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import {
|
||||||
signUpFailed,
|
signUpFailed,
|
||||||
signUpSuccessful,
|
signUpSuccessful,
|
||||||
} from './notifications';
|
} from './notifications';
|
||||||
import { containerStyle } from './common';
|
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ const SignUp = () => {
|
||||||
await signUp(email, password);
|
await signUp(email, password);
|
||||||
signUpSuccessful();
|
signUpSuccessful();
|
||||||
emailNotVerified();
|
emailNotVerified();
|
||||||
navigate(Routes.ROOT);
|
navigate(Routes.HUB);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
|
@ -49,10 +48,9 @@ const SignUp = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div className="small-container">
|
||||||
<Divider>Sign Up</Divider>
|
<Divider>Sign Up</Divider>
|
||||||
<Form
|
<Form
|
||||||
initialValues={{ remember: true }}
|
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
validateMessages={validateMessages}
|
validateMessages={validateMessages}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
const containerStyle = {
|
|
||||||
padding: 20,
|
|
||||||
maxWidth: 370,
|
|
||||||
margin: '0 auto',
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
containerStyle,
|
|
||||||
};
|
|
|
@ -1,6 +1,7 @@
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export enum Routes {
|
export enum Routes {
|
||||||
ROOT = '/',
|
ROOT = '/',
|
||||||
|
HUB = '/',
|
||||||
|
|
||||||
TUNE_ROOT = '/t/:tuneId',
|
TUNE_ROOT = '/t/:tuneId',
|
||||||
TUNE_TAB = '/t/:tuneId/:tab',
|
TUNE_TAB = '/t/:tuneId/:tab',
|
||||||
|
@ -11,6 +12,7 @@ export enum Routes {
|
||||||
|
|
||||||
LOGIN = '/auth/login',
|
LOGIN = '/auth/login',
|
||||||
LOGOUT = '/auth/logout',
|
LOGOUT = '/auth/logout',
|
||||||
|
PROFILE = '/auth/profile',
|
||||||
SIGN_UP = '/auth/sign-up',
|
SIGN_UP = '/auth/sign-up',
|
||||||
FORGOT_PASSWORD = '/auth/forgot-password',
|
FORGOT_PASSWORD = '/auth/forgot-password',
|
||||||
RESET_PASSWORD = '/auth/reset-password',
|
RESET_PASSWORD = '/auth/reset-password',
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
@border-radius-base: 6px;
|
@border-radius-base: 6px;
|
||||||
|
|
||||||
@layout-header-padding: 0 15px;
|
@layout-header-padding: 0 15px;
|
||||||
@layout-header-height: 45px;
|
@layout-header-height: 50px;
|
||||||
|
|
||||||
@layout-footer-padding: 2px 10px;
|
@layout-footer-padding: 2px 10px;
|
||||||
@layout-footer-height: 28px;
|
@layout-footer-height: 28px;
|
||||||
|
|
Loading…
Reference in New Issue