Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
tianyazhichiC
algorithm-visualizer
提交
f4500f7e
A
algorithm-visualizer
项目概览
tianyazhichiC
/
algorithm-visualizer
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
algorithm-visualizer
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f4500f7e
编写于
4月 12, 2018
作者:
J
Jason Park
提交者:
Jason
4月 30, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Load categories/algorithms from filesystem, not from category.json
上级
2bf8a4a5
变更
23
显示空白变更内容
内联
并排
Showing
23 changed file
with
336 addition
and
211 deletion
+336
-211
app/frontend.js
app/frontend.js
+0
-2
app/index.js
app/index.js
+2
-2
bin/temporary_action.js
bin/temporary_action.js
+57
-0
environment.js
environment.js
+0
-12
src/backend/controllers/auth.js
src/backend/controllers/auth.js
+0
-17
src/backend/controllers/directory.js
src/backend/controllers/directory.js
+95
-0
src/backend/controllers/index.js
src/backend/controllers/index.js
+4
-2
src/backend/controllers/wiki.js
src/backend/controllers/wiki.js
+44
-0
src/frontend/apis/index.js
src/frontend/apis/index.js
+11
-11
src/frontend/components/App/index.jsx
src/frontend/components/App/index.jsx
+9
-26
src/frontend/components/App/stylesheet.scss
src/frontend/components/App/stylesheet.scss
+3
-3
src/frontend/components/DescriptionViewer/index.jsx
src/frontend/components/DescriptionViewer/index.jsx
+31
-4
src/frontend/components/EditorSection/index.jsx
src/frontend/components/EditorSection/index.jsx
+21
-24
src/frontend/components/Header/index.jsx
src/frontend/components/Header/index.jsx
+7
-11
src/frontend/components/Navigator/index.jsx
src/frontend/components/Navigator/index.jsx
+17
-19
src/frontend/components/ViewerSection/index.jsx
src/frontend/components/ViewerSection/index.jsx
+0
-16
src/frontend/components/WikiViewer/index.jsx
src/frontend/components/WikiViewer/index.jsx
+5
-5
src/frontend/core/tracerManager.jsx
src/frontend/core/tracerManager.jsx
+25
-4
src/frontend/reducers/env.js
src/frontend/reducers/env.js
+0
-11
src/frontend/reducers/index.js
src/frontend/reducers/index.js
+1
-2
src/frontend/reducers/tracer.js
src/frontend/reducers/tracer.js
+0
-31
webpack.backend.config.js
webpack.backend.config.js
+3
-0
webpack.frontend.config.js
webpack.frontend.config.js
+1
-9
未找到文件。
app/frontend.js
浏览文件 @
f4500f7e
...
...
@@ -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
:
{
...
...
app/index.js
浏览文件 @
f4500f7e
...
...
@@ -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
);
...
...
bin/temporary_action.js
0 → 100644
浏览文件 @
f4500f7e
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
environment.js
浏览文件 @
f4500f7e
...
...
@@ -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
src/backend/controllers/auth.js
已删除
100644 → 0
浏览文件 @
2bf8a4a5
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
src/backend/controllers/directory.js
0 → 100644
浏览文件 @
f4500f7e
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
src/backend/controllers/index.js
浏览文件 @
f4500f7e
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
=
[
...
...
src/backend/controllers/wiki.js
0 → 100644
浏览文件 @
f4500f7e
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
src/frontend/apis/index.js
浏览文件 @
f4500f7e
...
...
@@ -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
src/frontend/components/App/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -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
{
Algorithm
Api
}
from
'
/apis
'
;
import
{
Directory
Api
}
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
()
{
Algorithm
Api
.
getCategories
()
.
then
(
categories
=>
{
Directory
Api
.
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
}
>
...
...
src/frontend/components/App/stylesheet.scss
浏览文件 @
f4500f7e
...
...
@@ -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
;
...
...
src/frontend/components/DescriptionViewer/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -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
>
...
...
src/frontend/components/EditorSection/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -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
{
Algorithm
Api
}
from
'
/apis
'
;
import
{
Directory
Api
}
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
)
}
>
...
...
src/frontend/components/Header/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -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
algorithm
Name
=
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
>
{
category
N
ame
}
</
Ellipsis
>
<
Ellipsis
>
{
category
.
ame
}
</
Ellipsis
>
<
FontAwesomeIcon
className
=
{
styles
.
nav_arrow
}
fixedWidth
icon
=
{
faAngleRight
}
/>
<
Ellipsis
>
{
algorithm
N
ame
}
</
Ellipsis
>
<
Ellipsis
>
{
algorithm
.
n
ame
}
</
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
}
...
...
src/frontend/components/Navigator/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -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
}
>
{
algorithm
Keys
.
map
(
algorithmKey
=>
{
const
name
=
list
[
algorithmKey
]
;
const
selected
=
categoryKey
===
selectedCategoryKey
&&
algorithmKey
===
selectedAlgorithmKey
;
algorithm
s
.
map
(
algorithm
=>
{
const
selected
=
category
.
key
===
selectedCategoryKey
&&
algorithm
.
key
===
selectedAlgorithmKey
;
const
[
file
]
=
algorithm
.
files
;
return
(
<
ListItem
indent
key
=
{
algorithm
K
ey
}
selected
=
{
selected
}
onClick
=
{
()
=>
this
.
props
.
select
Algorithm
(
categoryKey
,
algorithmK
ey
)
}
>
<
Ellipsis
>
{
name
}
</
Ellipsis
>
<
ListItem
indent
key
=
{
algorithm
.
k
ey
}
selected
=
{
selected
}
onClick
=
{
()
=>
this
.
props
.
select
File
(
category
.
key
,
algorithm
.
key
,
file
.
k
ey
)
}
>
<
Ellipsis
>
{
algorithm
.
name
}
</
Ellipsis
>
</
ListItem
>
)
})
...
...
src/frontend/components/ViewerSection/index.jsx
浏览文件 @
f4500f7e
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
});
}
...
...
src/frontend/components/WikiViewer/index.jsx
浏览文件 @
f4500f7e
...
...
@@ -14,12 +14,12 @@ class WikiViewer extends React.Component {
}
componentDidMount
()
{
this
.
load
(
'
Tracer
'
);
this
.
load
Wiki
(
'
Tracer
'
);
}
load
(
wikiKey
)
{
WikiApi
.
getWiki
(
wikiKey
+
'
.md
'
)
.
then
(
wiki
=>
this
.
setState
({
wiki
:
`#
${
wikiKey
}
\n
${
wiki
}
`
}));
load
Wiki
(
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
.
load
Wiki
(
href
)
}
/>
)
:
(
<
a
href
=
{
href
}
rel
=
"noopener"
target
=
"_blank"
{
...
rest
}
/>
);
...
...
src/frontend/core/tracerManager.jsx
浏览文件 @
f4500f7e
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/renderer
s
'
;
import
*
as
Datas
from
'
/core/data
s
'
;
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
);
...
...
src/frontend/reducers/env.js
浏览文件 @
f4500f7e
...
...
@@ -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
,
...
...
src/frontend/reducers/index.js
浏览文件 @
f4500f7e
export
{
default
as
env
}
from
'
./env
'
;
export
{
default
as
toast
}
from
'
./toast
'
;
\ No newline at end of file
export
{
default
as
tracer
}
from
'
./tracer
'
;
\ No newline at end of file
src/frontend/reducers/tracer.js
已删除
100644 → 0
浏览文件 @
2bf8a4a5
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
,
});
webpack.backend.config.js
浏览文件 @
f4500f7e
...
...
@@ -18,6 +18,9 @@ fs.readdirSync(srcPath).forEach(name => {
module
.
exports
=
{
target
:
'
node
'
,
node
:
{
__dirname
:
true
,
},
entry
:
srcPath
,
externals
:
[
nodeExternals
()],
resolve
:
{
...
...
webpack.frontend.config.js
浏览文件 @
f4500f7e
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录