diff --git a/src/frontend/components/App/index.jsx b/src/frontend/components/App/index.jsx index b5fa1ec4acb556f2e767a425997fb0a4d9463496..79df7ed7c53a90c2a01e96712866446d4cd6a82d 100644 --- a/src/frontend/components/App/index.jsx +++ b/src/frontend/components/App/index.jsx @@ -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 }); } diff --git a/src/frontend/components/Button/index.jsx b/src/frontend/components/Button/index.jsx index d30693b926880ba21e5175c2f3d54695c4bd1dae..851fe39c6f8ed7babd9e6d07dafde7cc99dd7082 100644 --- a/src/frontend/components/Button/index.jsx +++ b/src/frontend/components/Button/index.jsx @@ -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 ? ( + + ) : href ? ( ) : (
diff --git a/src/frontend/components/EditorSection/index.jsx b/src/frontend/components/EditorSection/index.jsx index 0172f90b26808619744ba7cef612884c8932554b..d221e42f4d092c394668200dc2731b8de92acc5f 100644 --- a/src/frontend/components/EditorSection/index.jsx +++ b/src/frontend/components/EditorSection/index.jsx @@ -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 (
- this.props.selectFile(categoryKey, algorithmKey, fileKeys[tabIndex])} /> +
{fileInfo} diff --git a/src/frontend/components/Header/index.jsx b/src/frontend/components/Header/index.jsx index 905a5d64707cbb0d8fff10015eff3ca8e2d1eefd..f02e6395a10acb5a3ec7b47fc0f5b1e849ed70ca 100644 --- a/src/frontend/components/Header/index.jsx +++ b/src/frontend/components/Header/index.jsx @@ -62,7 +62,7 @@ class Header extends React.Component { return (
+ ) }) }
-
); } diff --git a/src/frontend/components/ViewerSection/index.jsx b/src/frontend/components/ViewerSection/index.jsx index e60a39cae4b79a281fdcaa3d5d345ee19704df76..866492275f2d68b249b8b15dab020a78fc670e2b 100644 --- a/src/frontend/components/ViewerSection/index.jsx +++ b/src/frontend/components/ViewerSection/index.jsx @@ -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 (
- this.setTabIndex(tabIndex)} /> +
diff --git a/src/frontend/core/tracerManager.jsx b/src/frontend/core/tracerManager.jsx index 86c6de7c7bbfbf13bb7b1f640ee91371977f3e26..6f2bba3c2ecf0800179a98cb14169212e1690278 100644 --- a/src/frontend/core/tracerManager.jsx +++ b/src/frontend/core/tracerManager.jsx @@ -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; } diff --git a/src/frontend/index.jsx b/src/frontend/index.jsx index 1b6f8f9008745b6da019655c242ba31a1cfa458d..6aec2e735cb3dd03d3f8f5d2ba8d923ea86c80ba 100644 --- a/src/frontend/index.jsx +++ b/src/frontend/index.jsx @@ -1,7 +1,7 @@ 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( - + + + + , MOUNT_NODE diff --git a/src/frontend/reducers/env.js b/src/frontend/reducers/env.js index e59d4382428bd8c115de4efe5451a3b6026f4e31..7813348c29c791f34527828508f255a52d8a28bf 100644 --- a/src/frontend/reducers/env.js +++ b/src/frontend/reducers/env.js @@ -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, diff --git a/webpack.frontend.config.js b/webpack.frontend.config.js index a1c0946572d24e0efcd87a3d14c9d32998c95add..23dd9b28a738ff86c5b314a7a88eacd06c718757 100644 --- a/webpack.frontend.config.js +++ b/webpack.frontend.config.js @@ -41,6 +41,7 @@ module.exports = { output: { filename: __DEV__ ? '[name].js' : '[name].[chunkhash].js', path: builtPath, + publicPath: '/', }, module: { rules: [