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

Add BrowserRouter

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