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

Load categories/algorithms from filesystem, not from category.json

上级 2bf8a4a5
......@@ -21,8 +21,6 @@ if (__DEV__) {
const compiler = webpack(webpackConfig);
const app = express();
app.use(apiEndpoint + '/algorithm', express.static(algorithmApiSrcPath));
app.use(apiEndpoint + '/wiki', express.static(wikiApiSrcPath));
app.use(express.static(path.resolve(frontendSrcPath, 'static')));
app.use(webpackDev(compiler, {
stats: {
......
......@@ -8,8 +8,8 @@ const {
} = require('../environment');
const frontend = require('./frontend');
//const backend = require('./backend');
//app.use(apiEndpoint, backend);
const backend = require('./backend');
app.use(apiEndpoint, backend);
app.use(history());
app.use(compression());
app.use(frontend);
......
const path = require('path');
const fs = require('fs');
const getPath = (...args) => path.resolve(__dirname, '..', 'algorithm', ...args);
const readCategories = () => {
const createKey = name => name.toLowerCase().replace(/ /g, '-');
const subdirectories = dirPath => fs.readdirSync(dirPath).filter(subdir => !subdir.startsWith('.'));
const getCategory = categoryName => {
const categoryPath = getPath(categoryName);
const categoryKey = createKey(categoryName);
const algorithms = subdirectories(categoryPath).map(algorithmName => getAlgorithm(categoryName, algorithmName));
return {
key: categoryKey,
name: categoryName,
algorithms,
};
};
const getAlgorithm = (categoryName, algorithmName) => {
const algorithmPath = getPath(categoryName, algorithmName);
const algorithmKey = createKey(algorithmName);
const files = subdirectories(algorithmPath).filter(fileName => fileName !== 'desc.json');
return {
key: algorithmKey,
name: algorithmName,
files,
}
};
return subdirectories(getPath()).map(getCategory);
};
const categories = readCategories();
categories.forEach(category => {
category.algorithms.forEach(algorithm => {
algorithm.files.forEach(fileKey => {
const fileName = ['basic', 'normal'].includes(fileKey) ? algorithm.name : fileKey.split('_').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');
const oldPath = getPath(category.name, algorithm.name, fileKey);
const newPath = getPath(category.name, algorithm.name, fileName);
//fs.renameSync(oldPath, newPath);
console.log(oldPath + '->', newPath);
})
})
});
/*Object.values(hierarchy).forEach(({ name: categoryName, list }) => {
Object.values(list).forEach(algorithmName => {
const desc = require(path.resolve(algorithmPath, categoryName, algorithmName, 'desc.json'));
Object.keys(desc.files).forEach(fileKey => {
const fileName = fileKey.split('_').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');
const oldPath = path.resolve(algorithmPath, categoryName, algorithmName, fileKey);
const newPath = path.resolve(algorithmPath, categoryName, algorithmName, fileName);
//fs.renameSync(newPath, oldPath);
console.log(oldPath, newPath);
});
});
});*/
\ No newline at end of file
......@@ -16,16 +16,10 @@ const proxyPort = parseInt(PROXY_PORT);
const builtPath = path.resolve(__dirname, 'built');
const frontendBuiltPath = path.resolve(builtPath, 'frontend');
const backendBuiltPath = path.resolve(builtPath, 'backend');
const apiBuiltPath = path.resolve(frontendBuiltPath, 'api');
const algorithmApiBuiltPath = path.resolve(apiBuiltPath, 'algorithm');
const wikiApiBuiltPath = path.resolve(apiBuiltPath, 'wiki');
const srcPath = path.resolve(__dirname, 'src');
const frontendSrcPath = path.resolve(srcPath, 'frontend');
const backendSrcPath = path.resolve(srcPath, 'backend');
const apiSrcPath = path.resolve(__dirname);
const algorithmApiSrcPath = path.resolve(apiSrcPath, 'algorithm');
const wikiApiSrcPath = path.resolve(apiSrcPath, 'wiki');
const apiEndpoint = '/api';
......@@ -36,13 +30,7 @@ module.exports = {
proxyPort,
frontendBuiltPath,
backendBuiltPath,
apiBuiltPath,
algorithmApiBuiltPath,
wikiApiBuiltPath,
frontendSrcPath,
backendSrcPath,
apiSrcPath,
algorithmApiSrcPath,
wikiApiSrcPath,
apiEndpoint,
};
\ No newline at end of file
import express from 'express';
const router = express.Router();
const createAuth = (req, res, next) => {
res.json({});
};
const destroyAuth = (req, res, next) => {
res.json({});
};
router.route('/')
.post(createAuth)
.delete(destroyAuth);
export default router;
\ No newline at end of file
import express from 'express';
import fs from 'fs';
import path from 'path';
import { NotFoundError } from '/common/error';
const router = express.Router();
const getPath = (...args) => path.resolve(__dirname, '..', '..', '..', 'algorithm', ...args);
const readCategories = () => {
const createKey = name => name.toLowerCase().replace(/ /g, '-');
const list = dirPath => fs.readdirSync(dirPath).filter(filename => !/\./.test(filename)); // visible directories only
const getCategory = categoryName => {
const categoryKey = createKey(categoryName);
const categoryPath = getPath(categoryName);
const algorithms = list(categoryPath).map(algorithmName => getAlgorithm(categoryName, algorithmName));
return {
key: categoryKey,
name: categoryName,
algorithms,
};
};
const getAlgorithm = (categoryName, algorithmName) => {
const algorithmKey = createKey(algorithmName);
const algorithmPath = getPath(categoryName, algorithmName);
const files = list(algorithmPath).map(fileName => getFile(categoryName, algorithmName, fileName));
return {
key: algorithmKey,
name: algorithmName,
files,
}
};
const getFile = (categoryName, algorithmName, fileName) => {
const fileKey = createKey(fileName);
return {
key: fileKey,
name: fileName,
};
};
return list(getPath()).map(getCategory);
};
const categories = readCategories();
const getCategories = (req, res, next) => {
res.json({ categories });
};
const getFile = (req, res, next) => {
const { categoryKey, algorithmKey, fileKey } = req.params;
const category = categories.find(category => category.key === categoryKey);
if (!category) return next(new NotFoundError());
const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey);
if (!algorithm) return next(new NotFoundError());
const file = algorithm.files.find(file => file.key === fileKey);
if (!file) return next(new NotFoundError());
const dataPath = getPath(category.name, algorithm.name, file.name, 'data.js');
const codePath = getPath(category.name, algorithm.name, file.name, 'code.js');
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) return next(err);
fs.readFile(codePath, 'utf8', (err, code) => {
if (err) return next(err);
res.json({ data, code });
});
});
};
const getDescription = (req, res, next) => {
const { categoryKey, algorithmKey } = req.params;
const category = categories.find(category => category.key === categoryKey);
if (!category) return next(new NotFoundError());
const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey);
if (!algorithm) return next(new NotFoundError());
const descriptionPath = getPath(category.name, algorithm.name, 'desc.json');
fs.readFile(descriptionPath, 'utf8', (err, raw) => {
if (err) return next(err);
const description = JSON.parse(raw);
res.json({ description });
});
};
router.route('/')
.get(getCategories);
router.route('/description/:categoryKey/:algorithmKey')
.get(getDescription);
router.route('/:categoryKey/:algorithmKey/:fileKey')
.get(getFile);
export default router;
\ No newline at end of file
import express from 'express';
import { AuthorizationError, NotFoundError, PermissionError } from '/common/error';
import auth from './auth';
import directory from './directory';
import wiki from './wiki';
const router = new express.Router();
router.use('/auth', auth);
router.use('/directory', directory);
router.use('/wiki', wiki);
router.use((req, res, next) => next(new NotFoundError()));
router.use((err, req, res, next) => {
const statusMap = [
......
import express from 'express';
import fs from 'fs';
import path from 'path';
import { NotFoundError } from '/common/error';
const router = express.Router();
const getPath = (...args) => path.resolve(__dirname, '..', '..', '..', 'wiki', ...args);
const readWikis = () => {
const createKey = name => name.slice(0, -3);
const list = dirPath => fs.readdirSync(dirPath).filter(filename => /(\.md)$/.test(filename));
return list(getPath()).map(wikiName => ({
key: createKey(wikiName),
name: wikiName,
}));
};
const wikis = readWikis();
const getWikis = (req, res, next) => {
res.json({ wikis });
};
const getWiki = (req, res, next) => {
const { wikiKey } = req.params;
const wiki = wikis.find(wiki => wiki.key === wikiKey);
if (!wiki) return next(new NotFoundError());
const wikiPath = getPath(wiki.name);
fs.readFile(wikiPath, 'utf8', (err, wiki) => {
if (err) return next(err);
res.json({ wiki });
});
};
router.route('/')
.get(getWikis);
router.route('/:wikiKey')
.get(getWiki);
export default router;
\ No newline at end of file
......@@ -46,23 +46,23 @@ const PUT = URL => {
});
};
const AlgorithmApi = {
getCategories: GET('/algorithm/category.json'),
getAlgorithm: GET('/algorithm/:category/:algorithm/desc.json'),
getDataFile: GET('/algorithm/:category/:algorithm/:file/data.js'),
getCodeFile: GET('/algorithm/:category/:algorithm/:file/code.js'),
};
const ScratchApi = {
getScratch: GET('https://api.github.com/gists/:gist_id'),
const DirectoryApi = {
getCategories: GET('/directory'),
getDescription: GET('/directory/description/:categoryKey/:algorithmKey'),
getFile: GET('/directory/:categoryKey/:algorithmKey/:fileKey'),
};
const WikiApi = {
getWikis: GET('/wiki'),
getWiki: GET('/wiki/:wiki'),
};
const ScratchApi = {
getScratch: GET('https://api.github.com/gists/:gist_id'),
};
export {
AlgorithmApi,
ScratchApi,
DirectoryApi,
WikiApi,
ScratchApi,
};
\ No newline at end of file
......@@ -5,7 +5,7 @@ import { Divider, EditorSection, Header, Navigator, ToastContainer, ViewerSectio
import { actions as toastActions } from '/reducers/toast';
import { actions as envActions } from '/reducers/env';
import { calculatePercentageWidth } from '/common/util';
import { AlgorithmApi } from '/apis';
import { DirectoryApi } from '/apis';
import { tracerManager } from '/core';
import styles from './stylesheet.scss';
import 'axios-progress-bar/dist/nprogress.css'
......@@ -33,12 +33,13 @@ class App extends React.Component {
}
componentDidMount() {
AlgorithmApi.getCategories()
.then(categories => {
DirectoryApi.getCategories()
.then(({ categories }) => {
this.props.setCategories(categories);
const categoryKey = Object.keys(categories)[0];
const algorithmKey = Object.keys(categories[categoryKey].list)[0];
this.props.selectAlgorithm(categoryKey, algorithmKey);
const [category] = categories;
const [algorithm] = category.algorithms;
const [file] = algorithm.files;
this.props.selectFile(category.key, algorithm.key, file.key);
});
tracerManager.setOnError(error => this.props.showErrorToast(error.message));
}
......@@ -47,18 +48,6 @@ class App extends React.Component {
tracerManager.setOnError(null);
}
componentWillReceiveProps(nextProp) {
const { categoryKey, algorithmKey } = nextProp.env;
if (categoryKey !== this.props.env.categoryKey || algorithmKey !== this.props.env.algorithmKey) {
AlgorithmApi.getAlgorithm(categoryKey, algorithmKey)
.then(algorithm => {
this.props.setAlgorithm(algorithm);
const fileKey = Object.keys(algorithm.files)[0];
this.props.selectFile(categoryKey, algorithmKey, fileKey);
});
}
}
toggleNavigator(navigatorOpened = !this.state.navigatorOpened) {
this.setState({ navigatorOpened });
}
......@@ -75,15 +64,9 @@ class App extends React.Component {
render() {
const { navigatorOpened, navigatorWidth, viewerSectionWidth } = this.state;
const { categories, algorithm } = this.props.env;
if (!categories || !algorithm) {
return (
<div className={styles.app} />
);
}
const { categories, categoryKey, algorithmKey, fileKey } = this.props.env;
return (
return categories && categoryKey && algorithmKey && fileKey && (
<div className={styles.app}>
<Header onClickTitleBar={() => this.toggleNavigator()} navigatorOpened={navigatorOpened} />
<main className={styles.main} ref={ref => this.elMain = ref}>
......
......@@ -12,8 +12,10 @@ body {
body {
font-family: 'Roboto', sans-serif;
-webkit-font-smoothing: subpixel-antialiased;
color: $color-font;
user-select: none;
background-color: $theme-normal;
color: $color-font;
font-size: $font-size-normal;
}
a {
......@@ -34,8 +36,6 @@ input {
flex-direction: column;
align-items: stretch;
height: 100%;
background-color: $theme-normal;
font-size: $font-size-normal;
.loading_slider {
position: absolute;
......
......@@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import { classes } from '/common/util';
import { actions as envActions } from '/reducers/env';
import styles from './stylesheet.scss';
import { DirectoryApi } from '/apis/index';
@connect(
({ env }) => ({
......@@ -12,6 +13,32 @@ import styles from './stylesheet.scss';
}
)
class DescriptionViewer extends React.Component {
constructor(props) {
super(props);
this.state = {
description: null,
};
}
componentDidMount() {
const { categoryKey, algorithmKey } = this.props.env;
this.loadDescription(categoryKey, algorithmKey);
}
componentWillReceiveProps(nextProps) {
const { categoryKey, algorithmKey } = nextProps.env;
if (categoryKey !== this.props.env.categoryKey ||
algorithmKey !== this.props.env.algorithmKey) {
this.loadDescription(categoryKey, algorithmKey);
}
}
loadDescription(categoryKey, algorithmKey) {
DirectoryApi.getDescription(categoryKey, algorithmKey)
.then(({ description }) => this.setState({ description }));
}
getChild(value) {
if (typeof value === 'string') {
return (
......@@ -44,15 +71,15 @@ class DescriptionViewer extends React.Component {
}
render() {
const { description } = this.state;
const { className } = this.props;
const { algorithm } = this.props.env;
return (
return description && (
<div className={classes(styles.description_viewer, className)}>
{
Object.keys(algorithm).map((key, i) => {
Object.keys(description).map((key, i) => {
if (key === 'files') return null;
const value = algorithm[key];
const value = description[key];
return (
<div key={i}>
<h3>{key}</h3>
......
......@@ -8,18 +8,15 @@ import faInfoCircle from '@fortawesome/fontawesome-free-solid/faInfoCircle';
import { calculatePercentageHeight, classes } from '/common/util';
import { Divider, Ellipsis, TabBar } from '/components';
import { actions as envActions } from '/reducers/env';
import { actions as tracerActions } from '/reducers/tracer';
import { tracerManager } from '/core';
import { AlgorithmApi } from '/apis';
import { DirectoryApi } from '/apis';
import styles from './stylesheet.scss';
@connect(
({ env, tracer }) => ({
({ env }) => ({
env,
tracer,
}), {
...envActions,
...tracerActions,
}
)
class EditorSection extends React.Component {
......@@ -30,16 +27,22 @@ class EditorSection extends React.Component {
this.state = {
dataContainerHeight: '30%',
lineMarker: this.createLineMarker(lineIndicator),
data: '',
code: '',
};
}
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) }));
}
componentWillUnmount() {
tracerManager.setDataGetter(null);
tracerManager.setCodeGetter(null);
tracerManager.setOnUpdateLineIndicator(null);
}
......@@ -68,11 +71,11 @@ class EditorSection extends React.Component {
}
loadCodeAndData(categoryKey, algorithmKey, fileKey) {
if (!fileKey) return;
AlgorithmApi.getDataFile(categoryKey, algorithmKey, fileKey)
.then(data => this.handleChangeData(data))
.then(() => AlgorithmApi.getCodeFile(categoryKey, algorithmKey, fileKey))
.then(code => this.handleChangeCode(code));
DirectoryApi.getFile(categoryKey, algorithmKey, fileKey)
.then(({ data, code }) => {
this.handleChangeData(data);
this.handleChangeCode(code);
});
}
handleResizeDataContainer(x, y) {
......@@ -81,29 +84,23 @@ class EditorSection extends React.Component {
}
handleChangeData(data) {
this.props.setData(data);
this.executeData(data);
this.setState({ data }, () => tracerManager.runData());
}
handleChangeCode(code) {
this.props.setCode(code);
const { data } = this.props.tracer;
this.executeData(data);
}
executeData(data) {
tracerManager.runData(data);
this.setState({ code }, () => tracerManager.runData());
}
render() {
const { dataContainerHeight, lineMarker } = this.state;
const { dataContainerHeight, lineMarker, data, code } = this.state;
const { className } = this.props;
const { categoryKey, algorithmKey, fileKey, algorithm } = this.props.env;
const { data, code } = this.props.tracer;
const { categories, categoryKey, algorithmKey, fileKey } = this.props.env;
const fileKeys = Object.keys(algorithm.files);
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 fileInfo = algorithm.files[fileKey];
const fileInfo = ''; // TODO
return (
<section className={classes(styles.editor_section, className)}>
......
......@@ -13,19 +13,16 @@ import faChevronLeft from '@fortawesome/fontawesome-free-solid/faChevronLeft';
import faPause from '@fortawesome/fontawesome-free-solid/faPause';
import faExpandArrowsAlt from '@fortawesome/fontawesome-free-solid/faExpandArrowsAlt';
import { actions as envActions } from '/reducers/env';
import { actions as tracerActions } from '/reducers/tracer';
import { classes } from '/common/util';
import { Button, Ellipsis } from '/components';
import { tracerManager } from '/core';
import styles from './stylesheet.scss';
@connect(
({ env, tracer }) => ({
({ env }) => ({
env,
tracer,
}), {
...envActions,
...tracerActions,
}
)
class Header extends React.Component {
......@@ -58,17 +55,16 @@ class Header extends React.Component {
const { interval, paused, started } = this.state;
const { className, onClickTitleBar, navigatorOpened } = this.props;
const { categories, categoryKey, algorithmKey } = this.props.env;
const { data, code } = this.props.tracer;
const { name: categoryName, list: algorithmList } = categories[categoryKey];
const algorithmName = algorithmList[algorithmKey];
const category = categories.find(category => category.key === categoryKey);
const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey);
return (
<header className={classes(styles.header, className)}>
<Button className={styles.title_bar} onClick={onClickTitleBar}>
<Ellipsis>{categoryName}</Ellipsis>
<Ellipsis>{category.ame}</Ellipsis>
<FontAwesomeIcon className={styles.nav_arrow} fixedWidth icon={faAngleRight} />
<Ellipsis>{algorithmName}</Ellipsis>
<Ellipsis>{algorithm.name}</Ellipsis>
<FontAwesomeIcon className={styles.nav_caret} fixedWidth
icon={navigatorOpened ? faCaretDown : faCaretRight} />
</Button>
......@@ -80,9 +76,9 @@ class Header extends React.Component {
</Button>
{
started ? (
<Button icon={faPlay} primary onClick={() => tracerManager.run(data, code)} active>Rerun</Button>
<Button icon={faPlay} primary onClick={() => tracerManager.run()} active>Rerun</Button>
) : (
<Button icon={faPlay} primary onClick={() => tracerManager.run(data, code)}>Run</Button>
<Button icon={faPlay} primary onClick={() => tracerManager.run()}>Run</Button>
)
}
<Button icon={faChevronLeft} primary disabled={!started}
......
......@@ -49,11 +49,9 @@ class Navigator extends React.Component {
const { categories } = this.props.env;
const categoriesOpened = {};
const query = e.target.value;
Object.keys(categories).forEach(categoryKey => {
const { name, list } = categories[categoryKey];
let algorithmKeys = Object.keys(list);
if (this.testQuery(name) || algorithmKeys.find(algorithmKey => this.testQuery(list[algorithmKey]))) {
categoriesOpened[categoryKey] = true;
categories.forEach(category => {
if (this.testQuery(name) || category.algorithms.find(algorithm => this.testQuery(algorithm.name))) {
categoriesOpened[category.key] = true;
}
});
......@@ -79,25 +77,25 @@ class Navigator extends React.Component {
</div>
<div className={styles.algorithm_list}>
{
Object.keys(categories).map(categoryKey => {
const { name, list } = categories[categoryKey];
const categoryOpened = categoriesOpened[categoryKey];
let algorithmKeys = Object.keys(list);
if (!this.testQuery(name)) {
algorithmKeys = algorithmKeys.filter(algorithmKey => this.testQuery(list[algorithmKey]));
if (!algorithmKeys.length) return null;
categories.map(category => {
const categoryOpened = categoriesOpened[category.key];
let algorithms = category.algorithms;
if (!this.testQuery(category.name)) {
algorithms = algorithms.filter(algorithm => this.testQuery(algorithm.name));
if (!algorithms.length) return null;
}
return (
<ExpandableListItem key={categoryKey} onClick={() => this.toggleCategory(categoryKey)} label={name}
<ExpandableListItem key={category.key} onClick={() => this.toggleCategory(category.key)}
label={category.name}
opened={categoryOpened}>
{
algorithmKeys.map(algorithmKey => {
const name = list[algorithmKey];
const selected = categoryKey === selectedCategoryKey && algorithmKey === selectedAlgorithmKey;
algorithms.map(algorithm => {
const selected = category.key === selectedCategoryKey && algorithm.key === selectedAlgorithmKey;
const [file] = algorithm.files;
return (
<ListItem indent key={algorithmKey} selected={selected}
onClick={() => this.props.selectAlgorithm(categoryKey, algorithmKey)}>
<Ellipsis>{name}</Ellipsis>
<ListItem indent key={algorithm.key} selected={selected}
onClick={() => this.props.selectFile(category.key, algorithm.key, file.key)}>
<Ellipsis>{algorithm.name}</Ellipsis>
</ListItem>
)
})
......
import React from 'react';
import { connect } from 'react-redux';
import { classes } from '/common/util';
import { DescriptionViewer, RendererContainer, TabBar, WikiViewer } from '/components';
import { actions as envActions } from '/reducers/env';
import styles from './stylesheet.scss';
@connect(
({ env }) => ({
env
}), {
...envActions
}
)
class ViewerSection extends React.Component {
constructor(props) {
super(props);
......@@ -21,13 +12,6 @@ class ViewerSection extends React.Component {
};
}
componentWillReceiveProps(nextProp) {
const { algorithm } = nextProp.env;
if (algorithm !== this.props.env.algorithm) {
this.setTabIndex(0);
}
}
setTabIndex(tabIndex) {
this.setState({ tabIndex });
}
......
......@@ -14,12 +14,12 @@ class WikiViewer extends React.Component {
}
componentDidMount() {
this.load('Tracer');
this.loadWiki('Tracer');
}
load(wikiKey) {
WikiApi.getWiki(wikiKey + '.md')
.then(wiki => this.setState({ wiki: `# ${wikiKey}\n${wiki}` }));
loadWiki(wikiKey) {
WikiApi.getWiki(wikiKey)
.then(({ wiki }) => this.setState({ wiki: `# ${wikiKey}\n${wiki}` }));
}
render() {
......@@ -28,7 +28,7 @@ class WikiViewer extends React.Component {
const InnerLink = ({ href, ...rest }) => {
return /^\w+$/.test(href) ? (
<a {...rest} onClick={() => this.load(href)} />
<a {...rest} onClick={() => this.loadWiki(href)} />
) : (
<a href={href} rel="noopener" target="_blank" {...rest} />
);
......
import React from 'react';
import { Seed } from '/core';
import * as Tracers from '/core/tracers';
import * as Datas from '/core/datas';
import { Tracer } from '/core/tracers';
import { Array1DRenderer, Array2DRenderer, ChartRenderer, GraphRenderer, LogRenderer, Renderer } from '/core/renderers';
import * as Datas from '/core/datas';
import { Array1DData, Array2DData, ChartData, Data, GraphData, LogData } from '/core/datas';
import { Array1DRenderer, Array2DRenderer, ChartRenderer, GraphRenderer, LogRenderer, Renderer } from '/core/renderers';
Object.assign(window, Tracers);
Object.assign(window, Datas);
......@@ -34,6 +34,14 @@ class TracerManager {
this.onError = onError;
}
setDataGetter(dataGetter) {
this.dataGetter = dataGetter;
}
setCodeGetter(codeGetter) {
this.codeGetter = codeGetter;
}
render() {
if (this.onRender) this.onRender(this.renderers);
}
......@@ -58,6 +66,16 @@ class TracerManager {
if (this.onUpdateLineIndicator) this.onUpdateLineIndicator(lineIndicator);
}
getData(){
if(this.dataGetter) return this.dataGetter();
return null;
}
getCode(){
if(this.codeGetter) return this.codeGetter();
return null;
}
reset(seed) {
this.traces = seed.traces;
this.resetCursor();
......@@ -156,11 +174,14 @@ class TracerManager {
}
}
runData(data) {
runData() {
const data = this.getData();
this.execute(data, '', () => this.applyTraceChunk());
}
run(data, code) {
run() {
const data = this.getData();
const code = this.getCode();
const error = this.execute(data, code, () => this.resume());
if (error) {
this.handleError(error);
......
......@@ -3,12 +3,6 @@ import { combineActions, createAction, handleActions } from 'redux-actions';
const prefix = 'ENV';
const setCategories = createAction(`${prefix}/SET_CATEGORIES`, categories => ({ categories }));
const selectAlgorithm = createAction(`${prefix}/SELECT_ALGORITHM`, (categoryKey, algorithmKey) => ({
categoryKey,
algorithmKey,
fileKey: null,
}));
const setAlgorithm = createAction(`${prefix}/SET_ALGORITHM`, algorithm => ({ algorithm }));
const selectFile = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithmKey, fileKey) => ({
categoryKey,
algorithmKey,
......@@ -17,8 +11,6 @@ const selectFile = createAction(`${prefix}/SELECT_FILE`, (categoryKey, algorithm
export const actions = {
setCategories,
selectAlgorithm,
setAlgorithm,
selectFile,
};
......@@ -29,14 +21,11 @@ const mutables = {
categoryKey: null,
algorithmKey: null,
fileKey: null,
algorithm: null,
};
export default handleActions({
[combineActions(
setCategories,
selectAlgorithm,
setAlgorithm,
selectFile,
)]: (state, { payload }) => ({
...state,
......
export { default as env } from './env';
export { default as toast } from './toast';
export { default as tracer } from './tracer';
\ No newline at end of file
export { default as toast } from './toast';
\ No newline at end of file
import { combineActions, createAction, handleActions } from 'redux-actions';
const prefix = 'TRACER';
const setData = createAction(`${prefix}/SET_DATA`, data => ({ data }));
const setCode = createAction(`${prefix}/SET_CODE`, code => ({ code }));
export const actions = {
setData,
setCode,
};
const immutables = {};
const mutables = {
data: '',
code: '',
};
export default handleActions({
[combineActions(
setData,
setCode,
)]: (state, { payload }) => ({
...state,
...payload,
}),
}, {
...immutables,
...mutables,
});
......@@ -18,6 +18,9 @@ fs.readdirSync(srcPath).forEach(name => {
module.exports = {
target: 'node',
node: {
__dirname: true,
},
entry: srcPath,
externals: [nodeExternals()],
resolve: {
......
......@@ -13,11 +13,7 @@ const {
__PROD__,
__DEV__,
frontendBuiltPath: builtPath,
algorithmApiBuiltPath,
wikiApiBuiltPath,
frontendSrcPath: srcPath,
algorithmApiSrcPath,
wikiApiSrcPath,
} = require('./environment');
const filter = arr => arr.filter(v => v);
......@@ -102,11 +98,7 @@ module.exports = {
},
plugins: filter([
new CleanWebpackPlugin([builtPath]),
new CopyWebpackPlugin([
{ from: path.resolve(srcPath, 'static'), to: builtPath },
{ from: algorithmApiSrcPath, to: algorithmApiBuiltPath },
{ from: wikiApiSrcPath, to: wikiApiBuiltPath },
]),
new CopyWebpackPlugin([{ from: path.resolve(srcPath, 'static'), to: builtPath }]),
new HtmlWebpackPlugin({
template: path.resolve(srcPath, 'template.html'),
hash: false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册