fix: routes - Replaced class by func. comp (#159)

* refactor: updated routes

* fix: fixed conflicts issues

* fix: rollback port
This commit is contained in:
Priscila Oliveira 2019-10-19 10:49:04 +02:00 committed by Juan Picado @jotadeveloper
parent 8c66dbc4d7
commit 5c06ace14a
6 changed files with 100 additions and 114 deletions

View File

@ -4,7 +4,8 @@ import { mount, ReactWrapper } from 'enzyme';
import storage from '../utils/storage';
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', () => {
class LocalStorageMock {
@ -33,7 +34,7 @@ jest.mock('../utils/api', () => ({
}));
describe('App', () => {
let wrapper: ReactWrapper<{}, AppStateInterface, App>;
let wrapper: ReactWrapper<{}, AppProps, App>;
beforeEach(() => {
wrapper = mount(<App />);

View File

@ -1,5 +1,7 @@
import React, { Component, ReactElement } from 'react';
import isNil from 'lodash/isNil';
import 'normalize.css';
import 'typeface-roboto/index.css';
import storage from '../utils/storage';
import { makeLogin, isTokenExpire } from '../utils/login';
@ -7,41 +9,15 @@ import Loading from '../components/Loading';
import LoginModal from '../components/Login';
import Header from '../components/Header';
import { Container, Content } from '../components/Layout';
import RouterApp from '../router';
import API from '../utils/api';
import 'typeface-roboto/index.css';
import '../utils/styles/global';
import 'normalize.css';
import Footer from '../components/Footer';
import { FormError } from '../components/Login/Login';
import { PackageInterface } from '../components/Package/Package';
interface AppContextData {
logoUrl: string;
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;
import AppRoute from './AppRoute';
import { AppProps, AppContextProvider } from './AppContext';
export interface AppStateInterface extends AppContextData {
error?: FormError;
showLoginModal: boolean;
isLoading: boolean;
}
export default class App extends Component<{}, AppStateInterface> {
public state: AppStateInterface = {
export default class App extends Component<{}, AppProps> {
public state: AppProps = {
logoUrl: window.VERDACCIO_LOGO,
user: {},
scope: window.VERDACCIO_SCOPE || '',
@ -57,7 +33,7 @@ export default class App extends Component<{}, AppStateInterface> {
}
// eslint-disable-next-line no-unused-vars
public componentDidUpdate(_: AppStateInterface, prevState: AppStateInterface): void {
public componentDidUpdate(_: AppProps, prevState: AppProps): void {
const { isUserLoggedIn } = this.state;
if (prevState.isUserLoggedIn !== isUserLoggedIn) {
this.loadOnHandler();
@ -94,6 +70,7 @@ export default class App extends Component<{}, AppStateInterface> {
public loadOnHandler = async () => {
try {
const packages = await API.request<any[]>('packages', 'GET');
// @ts-ignore: FIX THIS TYPE: Type 'any[]' is not assignable to type '[]'
this.setState({
packages,
isLoading: false,
@ -176,9 +153,7 @@ export default class App extends Component<{}, AppStateInterface> {
return (
<>
<Content>
<RouterApp onLogout={this.handleLogout} onToggleLoginModal={this.handleToggleLoginModal}>
{this.renderHeader()}
</RouterApp>
<AppRoute>{this.renderHeader()}</AppRoute>
</Content>
<Footer />
</>

20
src/App/AppContext.tsx Normal file
View 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
View 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;

View File

@ -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;

View File

@ -59,10 +59,6 @@ export function formatDateDistance(lastUpdate: Date | string | number): string {
return distanceInWordsToNow(new Date(lastUpdate));
}
export function buildScopePackage(scope: string, packageName: string): string {
return `@${scope}/${packageName}`;
}
/**
* For <LastSync /> component
* @param {array} uplinks