提交 fea69cee 编写于 作者: J Jason Park 提交者: Jason

Add BrowserRouter

上级 f4500f7e
...@@ -33,21 +33,35 @@ class App extends React.Component { ...@@ -33,21 +33,35 @@ class App extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.updateDirectory(this.props.match.params);
DirectoryApi.getCategories() DirectoryApi.getCategories()
.then(({ categories }) => { .then(({ categories }) => {
this.props.setCategories(categories); this.props.setCategories(categories);
const [category] = categories; const { categoryKey, algorithmKey, fileKey } = this.props.env;
const [algorithm] = category.algorithms; const category = categories.find(category => category.key === categoryKey) || categories[0];
const [file] = algorithm.files; const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey) || category.algorithms[0];
this.props.selectFile(category.key, algorithm.key, file.key); const file = algorithm.files.find(file => file.key === fileKey) || algorithm.files[0];
this.props.history.push(`/${category.key}/${algorithm.key}/${file.key}`);
}); });
tracerManager.setOnError(error => this.props.showErrorToast(error.message)); tracerManager.setOnError(error => this.props.showErrorToast(error.message));
} }
componentWillReceiveProps(nextProps) {
if (nextProps.match.params !== this.props.match.params) {
this.updateDirectory(nextProps.match.params);
}
}
componentWillUnmount() { componentWillUnmount() {
tracerManager.setOnError(null); tracerManager.setOnError(null);
} }
updateDirectory({ categoryKey = null, algorithmKey = null, fileKey = null }) {
this.props.setDirectory(categoryKey, algorithmKey, fileKey);
}
toggleNavigator(navigatorOpened = !this.state.navigatorOpened) { toggleNavigator(navigatorOpened = !this.state.navigatorOpened) {
this.setState({ navigatorOpened }); this.setState({ navigatorOpened });
} }
......
...@@ -2,10 +2,11 @@ import React from 'react'; ...@@ -2,10 +2,11 @@ import React from 'react';
import FontAwesomeIcon from '@fortawesome/react-fontawesome' import FontAwesomeIcon from '@fortawesome/react-fontawesome'
import styles from './stylesheet.scss'; import styles from './stylesheet.scss';
import { classes } from '/common/util'; import { classes } from '/common/util';
import { Link } from 'react-router-dom';
class Button extends React.Component { class Button extends React.Component {
render() { render() {
const { className, children, onClick, href, icon, reverse, selected, disabled, primary, active } = this.props; const { className, children, onClick, to, href, icon, reverse, selected, disabled, primary, active } = this.props;
const iconOnly = !children; const iconOnly = !children;
const props = { const props = {
...@@ -18,7 +19,9 @@ class Button extends React.Component { ...@@ -18,7 +19,9 @@ class Button extends React.Component {
] ]
}; };
return href ? ( return to ? (
<Link to={to} {...props} />
) : href ? (
<a href={href} rel="noopener" target="_blank" {...props} /> <a href={href} rel="noopener" target="_blank" {...props} />
) : ( ) : (
<div {...props} /> <div {...props} />
......
...@@ -33,11 +33,12 @@ class EditorSection extends React.Component { ...@@ -33,11 +33,12 @@ class EditorSection extends React.Component {
} }
componentDidMount() { componentDidMount() {
const { categoryKey, algorithmKey, fileKey } = this.props.env;
this.loadCodeAndData(categoryKey, algorithmKey, fileKey);
tracerManager.setDataGetter(() => this.state.data); tracerManager.setDataGetter(() => this.state.data);
tracerManager.setCodeGetter(() => this.state.code); tracerManager.setCodeGetter(() => this.state.code);
tracerManager.setOnUpdateLineIndicator(lineIndicator => this.setState({ lineMarker: this.createLineMarker(lineIndicator) })); tracerManager.setOnUpdateLineIndicator(lineIndicator => this.setState({ lineMarker: this.createLineMarker(lineIndicator) }));
const { categoryKey, algorithmKey, fileKey } = this.props.env;
this.loadCodeAndData(categoryKey, algorithmKey, fileKey);
} }
componentWillUnmount() { componentWillUnmount() {
...@@ -73,8 +74,7 @@ class EditorSection extends React.Component { ...@@ -73,8 +74,7 @@ class EditorSection extends React.Component {
loadCodeAndData(categoryKey, algorithmKey, fileKey) { loadCodeAndData(categoryKey, algorithmKey, fileKey) {
DirectoryApi.getFile(categoryKey, algorithmKey, fileKey) DirectoryApi.getFile(categoryKey, algorithmKey, fileKey)
.then(({ data, code }) => { .then(({ data, code }) => {
this.handleChangeData(data); this.setState({ data, code }, () => tracerManager.runData());
this.handleChangeCode(code);
}); });
} }
...@@ -98,14 +98,18 @@ class EditorSection extends React.Component { ...@@ -98,14 +98,18 @@ class EditorSection extends React.Component {
const category = categories.find(category => category.key === categoryKey); const category = categories.find(category => category.key === categoryKey);
const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey); const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey);
const fileKeys = algorithm.files.map(file => file.key); const tabs = algorithm.files.map(file => ({
const tabIndex = fileKeys.findIndex(v => v === fileKey); title: file.name,
props: {
to: `/${category.key}/${algorithm.key}/${file.key}`
},
}));
const tabIndex = algorithm.files.findIndex(file => file.key === fileKey);
const fileInfo = ''; // TODO const fileInfo = ''; // TODO
return ( return (
<section className={classes(styles.editor_section, className)}> <section className={classes(styles.editor_section, className)}>
<TabBar titles={fileKeys} selectedIndex={tabIndex} <TabBar tabs={tabs} tabIndex={tabIndex} />
onClickTab={tabIndex => this.props.selectFile(categoryKey, algorithmKey, fileKeys[tabIndex])} />
<div className={styles.info_container}> <div className={styles.info_container}>
<FontAwesomeIcon fixedWidth icon={faInfoCircle} className={styles.info_icon} /> <FontAwesomeIcon fixedWidth icon={faInfoCircle} className={styles.info_icon} />
<Ellipsis className={styles.info_text}>{fileInfo}</Ellipsis> <Ellipsis className={styles.info_text}>{fileInfo}</Ellipsis>
......
...@@ -62,7 +62,7 @@ class Header extends React.Component { ...@@ -62,7 +62,7 @@ class Header extends React.Component {
return ( return (
<header className={classes(styles.header, className)}> <header className={classes(styles.header, className)}>
<Button className={styles.title_bar} onClick={onClickTitleBar}> <Button className={styles.title_bar} onClick={onClickTitleBar}>
<Ellipsis>{category.ame}</Ellipsis> <Ellipsis>{category.name}</Ellipsis>
<FontAwesomeIcon className={styles.nav_arrow} fixedWidth icon={faAngleRight} /> <FontAwesomeIcon className={styles.nav_arrow} fixedWidth icon={faAngleRight} />
<Ellipsis>{algorithm.name}</Ellipsis> <Ellipsis>{algorithm.name}</Ellipsis>
<FontAwesomeIcon className={styles.nav_caret} fixedWidth <FontAwesomeIcon className={styles.nav_caret} fixedWidth
......
...@@ -94,7 +94,7 @@ class Navigator extends React.Component { ...@@ -94,7 +94,7 @@ class Navigator extends React.Component {
const [file] = algorithm.files; const [file] = algorithm.files;
return ( return (
<ListItem indent key={algorithm.key} selected={selected} <ListItem indent key={algorithm.key} selected={selected}
onClick={() => this.props.selectFile(category.key, algorithm.key, file.key)}> to={`/${category.key}/${algorithm.key}/${file.key}`}>
<Ellipsis>{algorithm.name}</Ellipsis> <Ellipsis>{algorithm.name}</Ellipsis>
</ListItem> </ListItem>
) )
......
...@@ -7,25 +7,26 @@ import styles from './stylesheet.scss'; ...@@ -7,25 +7,26 @@ import styles from './stylesheet.scss';
class TabBar extends React.Component { class TabBar extends React.Component {
render() { render() {
const { className, titles, selectedIndex, onClickTab } = this.props; const { className, tabs, tabIndex } = this.props;
const prevIndex = (tabIndex - 1 + tabs.length) % tabs.length;
const nextIndex = (tabIndex + 1) % tabs.length;
return ( return (
<div className={classes(styles.tab_bar, className)}> <div className={classes(styles.tab_bar, className)}>
<Button className={styles.tab} icon={faAngleLeft} <Button className={styles.tab} icon={faAngleLeft} {...tabs[prevIndex].props} />
onClick={() => onClickTab((selectedIndex - 1 + titles.length) % titles.length)} />
<div className={styles.wrapper}> <div className={styles.wrapper}>
{ {
titles.map((title, i) => { tabs.map((tab, i) => {
const selected = selectedIndex === i; const { title, props } = tab;
const selected = tabIndex === i;
return ( return (
<Button className={classes(styles.tab, selected && styles.selected)} <Button className={classes(styles.tab, selected && styles.selected)} key={i} {...props}>{title}</Button>
onClick={() => onClickTab(i)} key={i}>{title}</Button>
) )
}) })
} }
</div> </div>
<Button className={styles.tab} icon={faAngleRight} <Button className={styles.tab} icon={faAngleRight} {...tabs[nextIndex].props} />
onClick={() => onClickTab((selectedIndex + 1) % titles.length)} />
</div> </div>
); );
} }
......
...@@ -20,10 +20,16 @@ class ViewerSection extends React.Component { ...@@ -20,10 +20,16 @@ class ViewerSection extends React.Component {
const { className, style } = this.props; const { className, style } = this.props;
const { tabIndex } = this.state; const { tabIndex } = this.state;
const tabs = ['Visualization', 'Description', 'Tracer API'].map((title, i) => ({
title,
props: {
onClick: () => this.setTabIndex(i)
},
}));
return ( return (
<section className={classes(styles.viewer_section, className)} style={style}> <section className={classes(styles.viewer_section, className)} style={style}>
<TabBar titles={['Visualization', 'Description', 'Tracer API']} selectedIndex={tabIndex} <TabBar tabs={tabs} tabIndex={tabIndex} />
onClickTab={tabIndex => this.setTabIndex(tabIndex)} />
<div className={styles.content} data-tab_index={tabIndex}> <div className={styles.content} data-tab_index={tabIndex}>
<RendererContainer className={styles.tab} /> <RendererContainer className={styles.tab} />
<DescriptionViewer className={styles.tab} /> <DescriptionViewer className={styles.tab} />
......
...@@ -66,13 +66,13 @@ class TracerManager { ...@@ -66,13 +66,13 @@ class TracerManager {
if (this.onUpdateLineIndicator) this.onUpdateLineIndicator(lineIndicator); if (this.onUpdateLineIndicator) this.onUpdateLineIndicator(lineIndicator);
} }
getData(){ getData() {
if(this.dataGetter) return this.dataGetter(); if (this.dataGetter) return this.dataGetter();
return null; return null;
} }
getCode(){ getCode() {
if(this.codeGetter) return this.codeGetter(); if (this.codeGetter) return this.codeGetter();
return null; return null;
} }
......
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { combineReducers, createStore } from 'redux'; import { combineReducers, createStore } from 'redux';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { routerReducer } from 'react-router-redux'; import { routerReducer } from 'react-router-redux';
import App from '/components/App'; import App from '/components/App';
...@@ -15,7 +15,10 @@ const render = (Component) => { ...@@ -15,7 +15,10 @@ const render = (Component) => {
ReactDOM.render( ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter>
<Component /> <Switch>
<Route exact path="/:categoryKey/:algorithmKey/:fileKey" component={Component} />
<Route path="/" component={Component} />
</Switch>
</BrowserRouter> </BrowserRouter>
</Provider>, </Provider>,
MOUNT_NODE MOUNT_NODE
......
...@@ -3,7 +3,7 @@ import { combineActions, createAction, handleActions } from 'redux-actions'; ...@@ -3,7 +3,7 @@ import { combineActions, createAction, handleActions } from 'redux-actions';
const prefix = 'ENV'; const prefix = 'ENV';
const setCategories = createAction(`${prefix}/SET_CATEGORIES`, categories => ({ categories })); const setCategories = createAction(`${prefix}/SET_CATEGORIES`, categories => ({ categories }));
const selectFile = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithmKey, fileKey) => ({ const setDirectory = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithmKey, fileKey) => ({
categoryKey, categoryKey,
algorithmKey, algorithmKey,
fileKey, fileKey,
...@@ -11,7 +11,7 @@ const selectFile = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithm ...@@ -11,7 +11,7 @@ const selectFile = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithm
export const actions = { export const actions = {
setCategories, setCategories,
selectFile, setDirectory,
}; };
const immutables = {}; const immutables = {};
...@@ -26,7 +26,7 @@ const mutables = { ...@@ -26,7 +26,7 @@ const mutables = {
export default handleActions({ export default handleActions({
[combineActions( [combineActions(
setCategories, setCategories,
selectFile, setDirectory,
)]: (state, { payload }) => ({ )]: (state, { payload }) => ({
...state, ...state,
...payload, ...payload,
......
...@@ -41,6 +41,7 @@ module.exports = { ...@@ -41,6 +41,7 @@ module.exports = {
output: { output: {
filename: __DEV__ ? '[name].js' : '[name].[chunkhash].js', filename: __DEV__ ? '[name].js' : '[name].[chunkhash].js',
path: builtPath, path: builtPath,
publicPath: '/',
}, },
module: { module: {
rules: [ rules: [
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册