forked from sombochea/verdaccio-ui
fix: routes - Replaced class by func. comp (#159)
* refactor: updated routes * fix: fixed conflicts issues * fix: rollback port
This commit is contained in:
parent
8c66dbc4d7
commit
5c06ace14a
@ -4,7 +4,8 @@ import { mount, ReactWrapper } from 'enzyme';
|
|||||||
import storage from '../utils/storage';
|
import storage from '../utils/storage';
|
||||||
import { generateTokenWithTimeRange } from '../../jest/unit/components/__mocks__/token';
|
import { generateTokenWithTimeRange } from '../../jest/unit/components/__mocks__/token';
|
||||||
|
|
||||||
import App, { AppStateInterface } from './App';
|
import App from './App';
|
||||||
|
import { AppProps } from './AppContext';
|
||||||
|
|
||||||
jest.mock('../utils/storage', () => {
|
jest.mock('../utils/storage', () => {
|
||||||
class LocalStorageMock {
|
class LocalStorageMock {
|
||||||
@ -33,7 +34,7 @@ jest.mock('../utils/api', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe('App', () => {
|
describe('App', () => {
|
||||||
let wrapper: ReactWrapper<{}, AppStateInterface, App>;
|
let wrapper: ReactWrapper<{}, AppProps, App>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = mount(<App />);
|
wrapper = mount(<App />);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { Component, ReactElement } from 'react';
|
import React, { Component, ReactElement } from 'react';
|
||||||
import isNil from 'lodash/isNil';
|
import isNil from 'lodash/isNil';
|
||||||
|
import 'normalize.css';
|
||||||
|
import 'typeface-roboto/index.css';
|
||||||
|
|
||||||
import storage from '../utils/storage';
|
import storage from '../utils/storage';
|
||||||
import { makeLogin, isTokenExpire } from '../utils/login';
|
import { makeLogin, isTokenExpire } from '../utils/login';
|
||||||
@ -7,41 +9,15 @@ import Loading from '../components/Loading';
|
|||||||
import LoginModal from '../components/Login';
|
import LoginModal from '../components/Login';
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
import { Container, Content } from '../components/Layout';
|
import { Container, Content } from '../components/Layout';
|
||||||
import RouterApp from '../router';
|
|
||||||
import API from '../utils/api';
|
import API from '../utils/api';
|
||||||
import 'typeface-roboto/index.css';
|
|
||||||
import '../utils/styles/global';
|
import '../utils/styles/global';
|
||||||
import 'normalize.css';
|
|
||||||
import Footer from '../components/Footer';
|
import Footer from '../components/Footer';
|
||||||
import { FormError } from '../components/Login/Login';
|
|
||||||
import { PackageInterface } from '../components/Package/Package';
|
|
||||||
|
|
||||||
interface AppContextData {
|
import AppRoute from './AppRoute';
|
||||||
logoUrl: string;
|
import { AppProps, AppContextProvider } from './AppContext';
|
||||||
scope: string;
|
|
||||||
isUserLoggedIn: boolean;
|
|
||||||
packages: PackageInterface[];
|
|
||||||
user: {
|
|
||||||
username?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export const AppContext = React.createContext<AppContextData>({
|
|
||||||
logoUrl: window.VERDACCIO_LOGO,
|
|
||||||
user: {},
|
|
||||||
scope: window.VERDACCIO_SCOPE || '',
|
|
||||||
isUserLoggedIn: false,
|
|
||||||
packages: [],
|
|
||||||
});
|
|
||||||
const AppContextProvider = AppContext.Provider;
|
|
||||||
export const AppContextConsumer = AppContext.Consumer;
|
|
||||||
|
|
||||||
export interface AppStateInterface extends AppContextData {
|
export default class App extends Component<{}, AppProps> {
|
||||||
error?: FormError;
|
public state: AppProps = {
|
||||||
showLoginModal: boolean;
|
|
||||||
isLoading: boolean;
|
|
||||||
}
|
|
||||||
export default class App extends Component<{}, AppStateInterface> {
|
|
||||||
public state: AppStateInterface = {
|
|
||||||
logoUrl: window.VERDACCIO_LOGO,
|
logoUrl: window.VERDACCIO_LOGO,
|
||||||
user: {},
|
user: {},
|
||||||
scope: window.VERDACCIO_SCOPE || '',
|
scope: window.VERDACCIO_SCOPE || '',
|
||||||
@ -57,7 +33,7 @@ export default class App extends Component<{}, AppStateInterface> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
public componentDidUpdate(_: AppStateInterface, prevState: AppStateInterface): void {
|
public componentDidUpdate(_: AppProps, prevState: AppProps): void {
|
||||||
const { isUserLoggedIn } = this.state;
|
const { isUserLoggedIn } = this.state;
|
||||||
if (prevState.isUserLoggedIn !== isUserLoggedIn) {
|
if (prevState.isUserLoggedIn !== isUserLoggedIn) {
|
||||||
this.loadOnHandler();
|
this.loadOnHandler();
|
||||||
@ -94,6 +70,7 @@ export default class App extends Component<{}, AppStateInterface> {
|
|||||||
public loadOnHandler = async () => {
|
public loadOnHandler = async () => {
|
||||||
try {
|
try {
|
||||||
const packages = await API.request<any[]>('packages', 'GET');
|
const packages = await API.request<any[]>('packages', 'GET');
|
||||||
|
// @ts-ignore: FIX THIS TYPE: Type 'any[]' is not assignable to type '[]'
|
||||||
this.setState({
|
this.setState({
|
||||||
packages,
|
packages,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -176,9 +153,7 @@ export default class App extends Component<{}, AppStateInterface> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Content>
|
<Content>
|
||||||
<RouterApp onLogout={this.handleLogout} onToggleLoginModal={this.handleToggleLoginModal}>
|
<AppRoute>{this.renderHeader()}</AppRoute>
|
||||||
{this.renderHeader()}
|
|
||||||
</RouterApp>
|
|
||||||
</Content>
|
</Content>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
20
src/App/AppContext.tsx
Normal file
20
src/App/AppContext.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
import { FormError } from '../components/Login/Login';
|
||||||
|
|
||||||
|
export interface AppProps {
|
||||||
|
error?: FormError;
|
||||||
|
logoUrl: string;
|
||||||
|
user: {
|
||||||
|
username?: string;
|
||||||
|
};
|
||||||
|
scope: string;
|
||||||
|
showLoginModal: boolean;
|
||||||
|
isUserLoggedIn: boolean;
|
||||||
|
packages: [];
|
||||||
|
isLoading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppContext = createContext<Partial<AppProps>>({});
|
||||||
|
export const AppContextProvider = AppContext.Provider;
|
||||||
|
export const AppContextConsumer = AppContext.Consumer;
|
68
src/App/AppRoute.tsx
Normal file
68
src/App/AppRoute.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React, { lazy, useContext, Suspense } from 'react';
|
||||||
|
import { Route as ReactRouterDomRoute, Switch, Router } from 'react-router-dom';
|
||||||
|
import { createBrowserHistory } from 'history';
|
||||||
|
|
||||||
|
import Loading from '../components/Loading';
|
||||||
|
|
||||||
|
import { AppContext } from './AppContext';
|
||||||
|
|
||||||
|
const NotFound = lazy(() => import('../components/NotFound'));
|
||||||
|
const VersionContextProvider = lazy(() => import('../pages/Version/VersionContextProvider'));
|
||||||
|
const VersionPage = lazy(() => import('../pages/Version'));
|
||||||
|
const HomePage = lazy(() => import('../pages/home'));
|
||||||
|
|
||||||
|
enum Route {
|
||||||
|
ROOT = '/',
|
||||||
|
SCOPE_PACKAGE = '/-/web/detail/@:scope/:package',
|
||||||
|
SCOPE_PACKAGE_VERSION = '/-/web/detail/@:scope/:package/v/:version',
|
||||||
|
PACKAGE = '/-/web/detail/:package',
|
||||||
|
PACKAGE_VERSION = '/-/web/detail/:package/v/:version',
|
||||||
|
}
|
||||||
|
|
||||||
|
const history = createBrowserHistory({
|
||||||
|
basename: window.__VERDACCIO_BASENAME_UI_OPTIONS && window.__VERDACCIO_BASENAME_UI_OPTIONS.url_prefix,
|
||||||
|
});
|
||||||
|
|
||||||
|
/* eslint react/jsx-max-depth: 0 */
|
||||||
|
const AppRoute: React.FC = ({ children }) => {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const { isUserLoggedIn, packages } = appContext;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Router history={history}>
|
||||||
|
<Suspense fallback={<Loading />}>
|
||||||
|
{children}
|
||||||
|
<Switch>
|
||||||
|
<ReactRouterDomRoute exact={true} path={Route.ROOT}>
|
||||||
|
<HomePage isUserLoggedIn={!!isUserLoggedIn} packages={packages || []} />
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
<ReactRouterDomRoute exact={true} path={Route.PACKAGE}>
|
||||||
|
<VersionContextProvider>
|
||||||
|
<VersionPage />
|
||||||
|
</VersionContextProvider>
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
<ReactRouterDomRoute exact={true} path={Route.PACKAGE_VERSION}>
|
||||||
|
<VersionContextProvider>
|
||||||
|
<VersionPage />
|
||||||
|
</VersionContextProvider>
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
<ReactRouterDomRoute exact={true} path={Route.SCOPE_PACKAGE_VERSION}>
|
||||||
|
<VersionContextProvider>
|
||||||
|
<VersionPage />
|
||||||
|
</VersionContextProvider>
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
<ReactRouterDomRoute exact={true} path={Route.SCOPE_PACKAGE}>
|
||||||
|
<VersionContextProvider>
|
||||||
|
<VersionPage />
|
||||||
|
</VersionContextProvider>
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
<ReactRouterDomRoute>
|
||||||
|
<NotFound />
|
||||||
|
</ReactRouterDomRoute>
|
||||||
|
</Switch>
|
||||||
|
</Suspense>
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppRoute;
|
@ -1,74 +0,0 @@
|
|||||||
/* eslint react/jsx-max-depth:0 */
|
|
||||||
|
|
||||||
import React, { Component, ReactElement } from 'react';
|
|
||||||
import { Router, Route, Switch } from 'react-router-dom';
|
|
||||||
import { createBrowserHistory } from 'history';
|
|
||||||
|
|
||||||
import { AppContextConsumer } from './App/App';
|
|
||||||
import Header from './components/Header';
|
|
||||||
|
|
||||||
const history = createBrowserHistory({
|
|
||||||
basename: window.__VERDACCIO_BASENAME_UI_OPTIONS && window.__VERDACCIO_BASENAME_UI_OPTIONS.url_prefix,
|
|
||||||
});
|
|
||||||
|
|
||||||
const NotFound = React.lazy(() => import('./components/NotFound'));
|
|
||||||
const VersionContextProvider = React.lazy(() => import('./pages/Version/VersionContextProvider'));
|
|
||||||
const VersionPackage = React.lazy(() => import('./pages/Version'));
|
|
||||||
const HomePage = React.lazy(() => import('./pages/home'));
|
|
||||||
|
|
||||||
interface RouterAppProps {
|
|
||||||
onLogout: () => void;
|
|
||||||
onToggleLoginModal: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
class RouterApp extends Component<RouterAppProps> {
|
|
||||||
public render(): ReactElement<HTMLDivElement> {
|
|
||||||
return (
|
|
||||||
<Router history={history}>
|
|
||||||
<React.Suspense fallback={null}>
|
|
||||||
{this.renderHeader()}
|
|
||||||
<Switch>
|
|
||||||
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
|
||||||
<Route exact={true} path={'/-/web/detail/@:scope/:package'} render={this.renderVersionPage} />
|
|
||||||
<Route exact={true} path={'/-/web/detail/:package'} render={this.renderVersionPage} />
|
|
||||||
<Route exact={true} path={'/-/web/detail/:package/v/:version'} render={this.renderVersionPage} />
|
|
||||||
<Route exact={true} path={'/-/web/detail/@:scope/:package/v/:version'} render={this.renderVersionPage} />
|
|
||||||
<Route component={NotFound} />
|
|
||||||
</Switch>
|
|
||||||
</React.Suspense>
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public renderHeader = (): ReactElement<HTMLDivElement> => {
|
|
||||||
const { onLogout, onToggleLoginModal } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppContextConsumer>
|
|
||||||
{function renderConsumerVersionPage({ logoUrl, scope = '', user }) {
|
|
||||||
return <Header logo={logoUrl} onLogout={onLogout} onToggleLoginModal={onToggleLoginModal} scope={scope} username={user && user.username} />;
|
|
||||||
}}
|
|
||||||
</AppContextConsumer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
public renderHomePage = (): ReactElement<HTMLDivElement> => {
|
|
||||||
return (
|
|
||||||
<AppContextConsumer>
|
|
||||||
{function renderConsumerVersionPage({ isUserLoggedIn, packages }) {
|
|
||||||
return <HomePage isUserLoggedIn={isUserLoggedIn} packages={packages} />;
|
|
||||||
}}
|
|
||||||
</AppContextConsumer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
public renderVersionPage = (): ReactElement<HTMLDivElement> => {
|
|
||||||
return (
|
|
||||||
<VersionContextProvider>
|
|
||||||
<VersionPackage />
|
|
||||||
</VersionContextProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RouterApp;
|
|
@ -59,10 +59,6 @@ export function formatDateDistance(lastUpdate: Date | string | number): string {
|
|||||||
return distanceInWordsToNow(new Date(lastUpdate));
|
return distanceInWordsToNow(new Date(lastUpdate));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildScopePackage(scope: string, packageName: string): string {
|
|
||||||
return `@${scope}/${packageName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For <LastSync /> component
|
* For <LastSync /> component
|
||||||
* @param {array} uplinks
|
* @param {array} uplinks
|
||||||
|
Loading…
Reference in New Issue
Block a user