mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-02-17 03:19:36 +01:00
feat: migrate react router from hash to history api #1013
This commit is contained in:
parent
8c06f968f9
commit
1a456fb8a6
@ -53,13 +53,7 @@ module.exports = function(config, auth, storage) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/-/verdaccio/logo', function(req, res) {
|
function renderHTML(req, res) {
|
||||||
const installPath = _.get(config, 'url_prefix', '');
|
|
||||||
|
|
||||||
res.send(_.get(config, 'web.logo') || spliceURL(installPath, '/-/static/logo.png'));
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/', function(req, res) {
|
|
||||||
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix);
|
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix);
|
||||||
|
|
||||||
const webPage = template
|
const webPage = template
|
||||||
@ -70,6 +64,20 @@ module.exports = function(config, auth, storage) {
|
|||||||
res.setHeader('Content-Type', 'text/html');
|
res.setHeader('Content-Type', 'text/html');
|
||||||
|
|
||||||
res.send(webPage);
|
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;
|
return router;
|
||||||
|
@ -5,16 +5,16 @@ import storage from './utils/storage';
|
|||||||
import logo from './utils/logo';
|
import logo from './utils/logo';
|
||||||
import { makeLogin, isTokenExpire } from './utils/login';
|
import { makeLogin, isTokenExpire } from './utils/login';
|
||||||
|
|
||||||
import Footer from './components/Footer';
|
|
||||||
import Loading from './components/Loading';
|
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 Route from './router';
|
import RouterApp from './router';
|
||||||
import API from './utils/api';
|
import API from './utils/api';
|
||||||
import './styles/typeface-roboto.scss';
|
import './styles/typeface-roboto.scss';
|
||||||
import './styles/main.scss';
|
import './styles/main.scss';
|
||||||
import 'normalize.css';
|
import 'normalize.css';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
export const AppContext = React.createContext();
|
export const AppContext = React.createContext();
|
||||||
|
|
||||||
@ -143,15 +143,14 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isLoading, isUserLoggedIn, packages } = this.state;
|
const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state;
|
||||||
return (
|
return (
|
||||||
<Container isLoading={isLoading}>
|
<Container isLoading={isLoading}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<AppContextProvider value={{isUserLoggedIn, packages}}>
|
<AppContextProvider value={{isUserLoggedIn, packages, logoUrl, user, scope}}>
|
||||||
{this.renderHeader()}
|
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -178,7 +177,11 @@ export default class App extends Component {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Content>
|
<Content>
|
||||||
<Route></Route>
|
<RouterApp
|
||||||
|
onLogout={this.handleLogout}
|
||||||
|
onToggleLoginModal={this.handleToggleLoginModal}>
|
||||||
|
{this.renderHeader()}
|
||||||
|
</RouterApp>
|
||||||
</Content>
|
</Content>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -34,14 +34,14 @@ class DepDetail extends Component<any, any> {
|
|||||||
const { onLoading, history } = this.props;
|
const { onLoading, history } = this.props;
|
||||||
|
|
||||||
onLoading();
|
onLoading();
|
||||||
history.push(`/version/${name}`);
|
history.push(`/-/web/version/${name}`);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const WrappDepDetail = withRouter(DepDetail);
|
const WrappDepDetail = withRouter(DepDetail);
|
||||||
|
|
||||||
class DependencyBlock extends Component<any, any> {
|
class DependencyBlock extends Component<any, any> {
|
||||||
renderTags = (deps: object, enableLoading: boolean) =>
|
renderTags = (deps: any, enableLoading: boolean) =>
|
||||||
deps.map(dep => {
|
deps.map(dep => {
|
||||||
const [name, version] = dep;
|
const [name, version] = dep;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Button from '@material-ui/core/Button/index';
|
import Button from '@material-ui/core/Button/index';
|
||||||
import IconButton from '@material-ui/core/IconButton/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 { default as IconSearch } from '@material-ui/icons/Search';
|
||||||
|
|
||||||
import { getRegistryURL } from '../../utils/url';
|
import { getRegistryURL } from '../../utils/url';
|
||||||
import Link from '../Link';
|
import ExternalLink from '../Link';
|
||||||
import Logo from '../Logo';
|
import Logo from '../Logo';
|
||||||
import RegistryInfoDialog from '../RegistryInfoDialog';
|
import RegistryInfoDialog from '../RegistryInfoDialog';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
@ -128,7 +129,7 @@ class Header extends Component<IProps, IState> {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'help':
|
case 'help':
|
||||||
content = (
|
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 />
|
<Help />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
|
@ -80,7 +80,7 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WrapperLink className={'package'} to={`version/${label}`}>
|
<WrapperLink className={'package'} to={`/-/web/version/${label}`}>
|
||||||
<Header>
|
<Header>
|
||||||
{renderMainInfo()}
|
{renderMainInfo()}
|
||||||
<Overview>
|
<Overview>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { default as IconSearch } from '@material-ui/icons/Search';
|
import { default as IconSearch } from '@material-ui/icons/Search';
|
||||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||||
@ -13,7 +14,6 @@ import debounce from 'lodash/debounce';
|
|||||||
import API from '../../utils/api';
|
import API from '../../utils/api';
|
||||||
import AutoComplete from '../AutoComplete';
|
import AutoComplete from '../AutoComplete';
|
||||||
import colors from '../../utils/styles/colors';
|
import colors from '../../utils/styles/colors';
|
||||||
import { getDetailPageURL } from '../../utils/url';
|
|
||||||
|
|
||||||
import { IProps, IState } from './types';
|
import { IProps, IState } from './types';
|
||||||
import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } 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.
|
* When an user select any package by clicking or pressing return key.
|
||||||
*/
|
*/
|
||||||
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
|
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
|
||||||
|
const { history } = this.props;
|
||||||
// stops event bubbling
|
// stops event bubbling
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'click':
|
case 'click':
|
||||||
case 'enter':
|
case 'enter':
|
||||||
this.setState({ search: '' });
|
this.setState({ search: '' });
|
||||||
window.location.assign(getDetailPageURL(suggestionValue));
|
// $FlowFixMe
|
||||||
|
history.push(`/-/web/version/${suggestionValue}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -181,4 +183,4 @@ class Search extends Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Search;
|
export default withRouter(Search);
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface IProps {}
|
export interface IProps {
|
||||||
|
history?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IState {
|
export interface IState {
|
||||||
search: string;
|
search: string;
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
* @prettier
|
* @prettier
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createHashHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
|
|
||||||
const history = createHashHistory();
|
const history = createBrowserHistory();
|
||||||
|
|
||||||
// Listen for changes to the current location.
|
// Listen for changes to the current location.
|
||||||
history.listen((location, action) => {
|
history.listen((location, action) => {
|
||||||
|
@ -3,39 +3,50 @@
|
|||||||
* @flow
|
* @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 { Router, Route, Switch } from 'react-router-dom';
|
||||||
import { AppContextConsumer } from './app';
|
import { AppContextConsumer } from './app';
|
||||||
|
|
||||||
import { asyncComponent } from './utils/asyncComponent';
|
import { asyncComponent } from './utils/asyncComponent';
|
||||||
import history from './history';
|
import history from './history';
|
||||||
|
import Header from './components/Header';
|
||||||
|
|
||||||
const DetailPackage = asyncComponent(() => import('./pages/detail'));
|
const DetailPackage = asyncComponent(() => import('./pages/detail'));
|
||||||
const VersionPackage = asyncComponent(() => import('./pages/version'));
|
const VersionPackage = asyncComponent(() => import('./pages/version'));
|
||||||
const HomePage = asyncComponent(() => import('./pages/home'));
|
const HomePage = asyncComponent(() => import('./pages/home'));
|
||||||
|
|
||||||
interface IProps {
|
class RouterApp extends Component<any, any> {
|
||||||
isUserLoggedIn: boolean;
|
|
||||||
packages: Array<Object>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IState {}
|
|
||||||
|
|
||||||
class RouterApp extends Component<IProps, IState> {
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Switch>
|
<Fragment>
|
||||||
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
{this.renderHeader()}
|
||||||
<Route exact={true} path={'/detail/@:scope/:package'} render={this.renderDetailPage} />
|
<Switch>
|
||||||
<Route exact={true} path={'/detail/:package'} render={this.renderDetailPage} />
|
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
||||||
<Route exact={true} path={'/version/@:scope/:package'} render={this.renderVersionPage} />
|
<Route exact={true} path={'/-/web/detail/@:scope/:package'} render={this.renderDetailPage} />
|
||||||
<Route exact={true} path={'/version/:package'} render={this.renderVersionPage} />
|
<Route exact={true} path={'/-/web/detail/:package'} render={this.renderDetailPage} />
|
||||||
</Switch>
|
<Route exact={true} path={'/-/web/version/@:scope/:package'} render={this.renderVersionPage} />
|
||||||
|
<Route exact={true} path={'/-/web/version/:package'} render={this.renderVersionPage} />
|
||||||
|
</Switch>
|
||||||
|
</Fragment>
|
||||||
</Router>
|
</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 = () => {
|
renderHomePage = () => {
|
||||||
return (
|
return (
|
||||||
<AppContextConsumer>
|
<AppContextConsumer>
|
||||||
|
Loading…
Reference in New Issue
Block a user