App.tsx 3.9 KB
Newer Older
1 2 3 4 5
import React, {FunctionComponent, Suspense, useEffect, useMemo, useState} from 'react';
import {Redirect, Route, BrowserRouter as Router, Switch, useLocation} from 'react-router-dom';
import {headerHeight, position, size} from '~/utils/style';

import BodyLoading from '~/components/BodyLoading';
P
Peter Pan 已提交
6 7
import ErrorBoundary from '~/components/ErrorBoundary';
import ErrorPage from '~/pages/error';
8 9 10 11
import {Helmet} from 'react-helmet';
import NProgress from 'nprogress';
import Navbar from '~/components/Navbar';
import {SWRConfig} from 'swr';
P
Peter Pan 已提交
12
import {ToastContainer} from 'react-toastify';
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
import {fetcher} from '~/utils/fetch';
import init from '@visualdl/wasm';
import routes from '~/routes';
import styled from 'styled-components';
import {useTranslation} from 'react-i18next';

const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH;

const Main = styled.main`
    padding-top: ${headerHeight};
`;

const Header = styled.header`
    z-index: 10000;

    ${size(headerHeight, '100%')}
    ${position('fixed', 0, 0, null, 0)}
`;

const defaultRoute = routes.find(route => route.default);
const routers = routes.reduce<Omit<typeof routes[number], 'children'>[]>((m, route) => {
    if (route.children) {
        m.push(...route.children);
    } else {
        m.push(route);
    }
    return m;
}, []);

const Progress: FunctionComponent = () => {
    useEffect(() => {
        NProgress.start();
        return () => {
            NProgress.done();
        };
    }, []);

    return null;
};

const Telemetry: FunctionComponent = () => {
    const location = useLocation();
    useEffect(() => {
        globalThis._hmt.push(['_trackPageview', PUBLIC_PATH + location.pathname]);
    }, [location.pathname]);
    return null;
};

const App: FunctionComponent = () => {
P
Peter Pan 已提交
62
    const {t, i18n} = useTranslation('errors');
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

    const dir = useMemo(() => (i18n.language ? i18n.dir(i18n.language) : ''), [i18n]);

    const [inited, setInited] = useState(false);
    useEffect(() => {
        (async () => {
            if (!inited) {
                await init(`${PUBLIC_PATH}/wasm/visualdl.wasm`);
                setInited(true);
            }
        })();
    }, [inited]);

    return (
        <div className="app">
            <Helmet defaultTitle="VisualDL" titleTemplate="%s - VisualDL">
                <html lang={i18n.language} dir={dir} />
            </Helmet>
            <SWRConfig
                value={{
                    fetcher,
                    revalidateOnFocus: false,
                    revalidateOnReconnect: false
                }}
            >
                {!inited ? (
                    <BodyLoading />
                ) : (
                    <Main>
                        <Router basename={PUBLIC_PATH || '/'}>
                            <Telemetry />
                            <Header>
                                <Navbar />
                            </Header>
P
Peter Pan 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109
                            <ErrorBoundary fallback={<ErrorPage />}>
                                <Suspense fallback={<Progress />}>
                                    <Switch>
                                        <Redirect exact from="/" to={defaultRoute?.path ?? '/index'} />
                                        {routers.map(route => (
                                            <Route key={route.id} path={route.path} component={route.component} />
                                        ))}
                                        <Route path="*">
                                            <ErrorPage title={t('errors:page-not-found')} />
                                        </Route>
                                    </Switch>
                                </Suspense>
                            </ErrorBoundary>
110 111 112
                        </Router>
                    </Main>
                )}
P
Peter Pan 已提交
113
                <ToastContainer />
114 115 116 117 118 119
            </SWRConfig>
        </div>
    );
};

export default App;