0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-23 22:27:34 -05:00

feat: migrate react router from hash to history api #1013

This commit is contained in:
Juan Picado @jotadeveloper 2019-01-20 22:16:54 +01:00
parent 8c06f968f9
commit 1a456fb8a6
No known key found for this signature in database
GPG key ID: 18AC54485952D158
9 changed files with 67 additions and 40 deletions

View file

@ -53,13 +53,7 @@ module.exports = function(config, auth, storage) {
});
});
router.get('/-/verdaccio/logo', function(req, res) {
const installPath = _.get(config, 'url_prefix', '');
res.send(_.get(config, 'web.logo') || spliceURL(installPath, '/-/static/logo.png'));
});
router.get('/', function(req, res) {
function renderHTML(req, res) {
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix);
const webPage = template
@ -70,6 +64,20 @@ module.exports = function(config, auth, storage) {
res.setHeader('Content-Type', 'text/html');
res.send(webPage);
}
router.get('/-/web/:pkg', function(req, res) {
renderHTML(req, res);
});
router.get('/-/verdaccio/logo', function(req, res) {
const installPath = _.get(config, 'url_prefix', '');
res.send(_.get(config, 'web.logo') || spliceURL(installPath, '/-/static/logo.png'));
});
router.get('/', function(req, res) {
renderHTML(req, res);
});
return router;

View file

@ -5,16 +5,16 @@ import storage from './utils/storage';
import logo from './utils/logo';
import { makeLogin, isTokenExpire } from './utils/login';
import Footer from './components/Footer';
import Loading from './components/Loading';
import LoginModal from './components/Login';
import Header from './components/Header';
import { Container, Content } from './components/Layout';
import Route from './router';
import RouterApp from './router';
import API from './utils/api';
import './styles/typeface-roboto.scss';
import './styles/main.scss';
import 'normalize.css';
import Footer from './components/Footer';
export const AppContext = React.createContext();
@ -143,15 +143,14 @@ export default class App extends Component {
}
render() {
const { isLoading, isUserLoggedIn, packages } = this.state;
const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state;
return (
<Container isLoading={isLoading}>
{isLoading ? (
<Loading />
) : (
<Fragment>
<AppContextProvider value={{isUserLoggedIn, packages}}>
{this.renderHeader()}
<AppContextProvider value={{isUserLoggedIn, packages, logoUrl, user, scope}}>
{this.renderContent()}
</AppContextProvider>
</Fragment>
@ -178,7 +177,11 @@ export default class App extends Component {
return (
<Fragment>
<Content>
<Route></Route>
<RouterApp
onLogout={this.handleLogout}
onToggleLoginModal={this.handleToggleLoginModal}>
{this.renderHeader()}
</RouterApp>
</Content>
<Footer />
</Fragment>

View file

@ -34,14 +34,14 @@ class DepDetail extends Component<any, any> {
const { onLoading, history } = this.props;
onLoading();
history.push(`/version/${name}`);
history.push(`/-/web/version/${name}`);
};
}
const WrappDepDetail = withRouter(DepDetail);
class DependencyBlock extends Component<any, any> {
renderTags = (deps: object, enableLoading: boolean) =>
renderTags = (deps: any, enableLoading: boolean) =>
deps.map(dep => {
const [name, version] = dep;

View file

@ -5,6 +5,7 @@
import React, { Component } from 'react';
import type { Node } from 'react';
import { Link } from 'react-router-dom';
import Button from '@material-ui/core/Button/index';
import IconButton from '@material-ui/core/IconButton/index';
@ -17,7 +18,7 @@ import AccountCircle from '@material-ui/icons/AccountCircle';
import { default as IconSearch } from '@material-ui/icons/Search';
import { getRegistryURL } from '../../utils/url';
import Link from '../Link';
import ExternalLink from '../Link';
import Logo from '../Logo';
import RegistryInfoDialog from '../RegistryInfoDialog';
import Label from '../Label';
@ -128,7 +129,7 @@ class Header extends Component<IProps, IState> {
switch (type) {
case 'help':
content = (
<IconButton blank={true} color={'inherit'} component={Link} to={'https://verdaccio.org/docs/en/installation'}>
<IconButton blank={true} color={'inherit'} component={ExternalLink} to={'https://verdaccio.org/docs/en/installation'}>
<Help />
</IconButton>
);

View file

@ -80,7 +80,7 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
);
return (
<WrapperLink className={'package'} to={`version/${label}`}>
<WrapperLink className={'package'} to={`/-/web/version/${label}`}>
<Header>
{renderMainInfo()}
<Overview>

View file

@ -5,6 +5,7 @@
import React, { Component } from 'react';
import type { Node } from 'react';
import { withRouter } from 'react-router-dom';
import { default as IconSearch } from '@material-ui/icons/Search';
import InputAdornment from '@material-ui/core/InputAdornment';
@ -13,7 +14,6 @@ import debounce from 'lodash/debounce';
import API from '../../utils/api';
import AutoComplete from '../AutoComplete';
import colors from '../../utils/styles/colors';
import { getDetailPageURL } from '../../utils/url';
import { IProps, IState } from './types';
import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } from './types';
@ -92,13 +92,15 @@ class Search extends Component<IProps, IState> {
* When an user select any package by clicking or pressing return key.
*/
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
const { history } = this.props;
// stops event bubbling
event.stopPropagation();
switch (method) {
case 'click':
case 'enter':
this.setState({ search: '' });
window.location.assign(getDetailPageURL(suggestionValue));
// $FlowFixMe
history.push(`/-/web/version/${suggestionValue}`);
break;
}
};
@ -181,4 +183,4 @@ class Search extends Component<IProps, IState> {
}
}
export default Search;
export default withRouter(Search);

View file

@ -3,7 +3,9 @@
* @flow
*/
export interface IProps {}
export interface IProps {
history?: any;
}
export interface IState {
search: string;

View file

@ -2,9 +2,9 @@
* @prettier
*/
import { createHashHistory } from 'history';
import { createBrowserHistory } from 'history';
const history = createHashHistory();
const history = createBrowserHistory();
// Listen for changes to the current location.
history.listen((location, action) => {

View file

@ -3,39 +3,50 @@
* @flow
*/
import React, { Component } from 'react';
/* eslint react/jsx-max-depth:0 */
import React, { Component, Fragment } from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { AppContextConsumer } from './app';
import { asyncComponent } from './utils/asyncComponent';
import history from './history';
import Header from './components/Header';
const DetailPackage = asyncComponent(() => import('./pages/detail'));
const VersionPackage = asyncComponent(() => import('./pages/version'));
const HomePage = asyncComponent(() => import('./pages/home'));
interface IProps {
isUserLoggedIn: boolean;
packages: Array<Object>;
}
interface IState {}
class RouterApp extends Component<IProps, IState> {
class RouterApp extends Component<any, any> {
render() {
return (
<Router history={history}>
<Switch>
<Route exact={true} path={'/'} render={this.renderHomePage} />
<Route exact={true} path={'/detail/@:scope/:package'} render={this.renderDetailPage} />
<Route exact={true} path={'/detail/:package'} render={this.renderDetailPage} />
<Route exact={true} path={'/version/@:scope/:package'} render={this.renderVersionPage} />
<Route exact={true} path={'/version/:package'} render={this.renderVersionPage} />
</Switch>
<Fragment>
{this.renderHeader()}
<Switch>
<Route exact={true} path={'/'} render={this.renderHomePage} />
<Route exact={true} path={'/-/web/detail/@:scope/:package'} render={this.renderDetailPage} />
<Route exact={true} path={'/-/web/detail/:package'} render={this.renderDetailPage} />
<Route exact={true} path={'/-/web/version/@:scope/:package'} render={this.renderVersionPage} />
<Route exact={true} path={'/-/web/version/:package'} render={this.renderVersionPage} />
</Switch>
</Fragment>
</Router>
);
}
renderHeader = () => {
const { onLogout, onToggleLoginModal } = this.props;
return (
<AppContextConsumer>
{function renderConsumerVersionPage({ logoUrl, scope, user }) {
return <Header logo={logoUrl} onLogout={onLogout} onToggleLoginModal={onToggleLoginModal} scope={scope} username={user.username} />;
}}
</AppContextConsumer>
);
};
renderHomePage = () => {
return (
<AppContextConsumer>