Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
beat
beat.editor
Commits
b72d91f5
Commit
b72d91f5
authored
Oct 09, 2017
by
Jaden
Browse files
added basic algorithm editor, need to wire it up to API
parent
8cc78422
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
package-lock.json
View file @
b72d91f5
This diff is collapsed.
Click to expand it.
package.json
View file @
b72d91f5
...
...
@@ -34,11 +34,11 @@
"
enzyme
"
:
"
^3.1.0
"
,
"
eslint
"
:
"
^4.8.0
"
,
"
eslint-plugin-compat
"
:
"
^1.0.4
"
,
"
eslint-plugin-flowtype
"
:
"
^2.3
7.0
"
,
"
eslint-plugin-flowtype
"
:
"
^2.3
9.1
"
,
"
eslint-plugin-import
"
:
"
^2.7.0
"
,
"
eslint-plugin-react
"
:
"
^7.4.0
"
,
"
flow-bin
"
:
"
^0.56.0
"
,
"
flow-typed
"
:
"
^2.
1.5
"
,
"
flow-typed
"
:
"
^2.
2.0
"
,
"
html-webpack-harddisk-plugin
"
:
"
^0.1.0
"
,
"
html-webpack-plugin
"
:
"
^2.30.1
"
,
"
husky
"
:
"
^0.14.3
"
,
...
...
@@ -49,9 +49,9 @@
"
karma-mocha
"
:
"
^1.3.0
"
,
"
karma-mocha-reporter
"
:
"
^2.2.4
"
,
"
karma-sourcemap-loader
"
:
"
^0.3.7
"
,
"
karma-webpack
"
:
"
^2.0.
4
"
,
"
mocha
"
:
"
^
3.5.3
"
,
"
postcss
"
:
"
^6.0.1
2
"
,
"
karma-webpack
"
:
"
^2.0.
5
"
,
"
mocha
"
:
"
^
4.0.1
"
,
"
postcss
"
:
"
^6.0.1
3
"
,
"
postcss-cli
"
:
"
^4.1.1
"
,
"
postcss-cssnext
"
:
"
^3.0.2
"
,
"
postcss-loader
"
:
"
^2.0.6
"
,
...
...
@@ -60,8 +60,8 @@
"
redux-devtools
"
:
"
^3.4.0
"
,
"
rimraf
"
:
"
^2.6.2
"
,
"
sinon
"
:
"
^4.0.1
"
,
"
style-loader
"
:
"
^0.1
8.2
"
,
"
stylelint
"
:
"
^8.
1.1
"
,
"
style-loader
"
:
"
^0.1
9.0
"
,
"
stylelint
"
:
"
^8.
2.0
"
,
"
stylelint-config-standard
"
:
"
^17.0.0
"
,
"
svg-inline-loader
"
:
"
^0.8.0
"
,
"
webpack
"
:
"
^3.6.0
"
,
...
...
@@ -71,6 +71,7 @@
},
"dependencies"
:
{
"
bootstrap
"
:
"
^4.0.0-beta
"
,
"
classnames
"
:
"
^2.2.5
"
,
"
react
"
:
"
^16.0.0
"
,
"
react-dom
"
:
"
^16.0.0
"
,
"
react-popper
"
:
"
^0.7.3
"
,
...
...
src/components/AlgorithmsDetail.jsx
View file @
b72d91f5
...
...
@@ -4,6 +4,18 @@ import {
Container
,
Row
,
Col
,
Button
,
Form
,
FormGroup
,
Label
,
Input
,
InputGroup
,
FormText
,
Collapse
,
Card
,
CardHeader
,
CardBody
,
TabContent
,
TabPane
,
Nav
,
NavItem
,
NavLink
,
CardTitle
,
CardText
,
}
from
'
reactstrap
'
;
...
...
@@ -12,28 +24,656 @@ import {
Link
}
from
'
react-router-dom
'
;
import
EntityDetail
from
'
./EntityDetail.jsx
'
;
import
cn
from
'
classnames
'
;
import
EntityDetail
,
{
mapParamsToData
}
from
'
./EntityDetail.jsx
'
;
import
{
objToArr
}
from
'
./EntityList.jsx
'
;
type
Props
=
{
match
:
any
match
:
any
,
data
:
any
,
allData
:
any
,
};
const
data
=
{
user
:
{
test
:
{
'
1
'
:
{
name
:
'
user/test/1
'
}
}
}
type
State
=
{
activeTab
:
string
,
cache
:
any
,
dfs
:
any
[],
};
const
mapParamsToData
=
(
params
)
=>
data
[
params
.
user
][
params
.
name
][
params
.
version
];
const
orderedParams
=
(
params
:
any
):
string
[]
=>
[
params
.
user
,
params
.
name
,
params
.
version
];
const
getDescField
=
(
obj
)
=>
obj
&&
obj
[
'
#description
'
]
?
'
#description
'
:
'
description
'
;
const
AlgorithmsDetail
=
({
match
}:
Props
)
=>
(
<
div
>
<
EntityDetail
instance
=
{
mapParamsToData
(
match
.
params
)
}
/>
</
div
>
const
getValidObj
=
({
match
,
data
}:
Props
)
=>
{
const
getObj
=
{
contents
:
{},
...
JSON
.
parse
(
JSON
.
stringify
(
mapParamsToData
(
orderedParams
(
match
.
params
),
data
)))
};
return
{
name
:
''
,
...
getObj
,
contents
:
{
splittable
:
false
,
parameters
:
{},
uses
:
{},
groups
:
[
],
...
getObj
.
contents
,
[
getDescField
(
getObj
.
contents
)]:
getObj
.
contents
[
getDescField
(
getObj
.
contents
)]
||
''
},
};
};
const
DeleteInputBtn
=
({
deleteFunc
}:
any
)
=>
(
<
span
className
=
'input-group-btn'
>
<
Button
color
=
'danger'
onClick
=
{
(
e
)
=>
deleteFunc
(
e
)
}
>
X
</
Button
>
</
span
>
);
const
GroupIOBlock
=
({
name
,
ioObj
,
dfs
,
updateFunc
,
deleteFunc
}:
any
)
=>
(
<
FormGroup
>
<
Row
>
<
Col
sm
=
'6'
>
<
InputGroup
>
<
DeleteInputBtn
deleteFunc
=
{
()
=>
deleteFunc
(
name
)
}
/>
<
Input
type
=
'text'
placeholder
=
'Name...'
value
=
{
name
}
onChange
=
{
(
e
)
=>
updateFunc
(
name
,
e
.
target
.
value
,
ioObj
)
}
/>
</
InputGroup
>
</
Col
>
<
Col
sm
=
'6'
>
<
Input
type
=
'select'
className
=
'custom-select'
value
=
{
ioObj
.
type
||
ioObj
}
onChange
=
{
(
e
)
=>
updateFunc
(
name
,
name
,
ioObj
.
type
?
{
...
ioObj
,
type
:
e
.
target
.
value
}
:
e
.
target
.
value
)
}
>
<
option
disabled
>
Dataformat...
</
option
>
{
dfs
.
map
((
d
,
i
)
=>
(
<
option
key
=
{
i
}
value
=
{
d
.
name
}
>
{
d
.
name
}
</
option
>
))
}
</
Input
>
</
Col
>
</
Row
>
</
FormGroup
>
);
const
changeObjFieldName
=
(
obj
:
{},
oldName
:
string
,
newName
:
string
):
{}
=>
{
return
Object
.
entries
(
obj
)
.
map
(([
name
,
val
])
=>
[
name
===
oldName
?
newName
:
name
,
val
])
.
reduce
((
o
,
[
name
,
val
])
=>
({...
o
,
[
name
]:
val
}),
{});
};
const
builtinDfs
=
[
'
int8
'
,
'
int16
'
,
'
int32
'
,
'
int64
'
,
'
uint8
'
,
'
uint16
'
,
'
uint32
'
,
'
uint64
'
,
'
float32
'
,
'
float64
'
,
'
complex64
'
,
'
complex128
'
,
'
bool
'
,
'
string
'
];
const
resultDfs
=
[
'
int32
'
,
'
float32
'
,
'
bool
'
,
'
string
'
];
class
AlgorithmsDetail
extends
React
.
Component
<
Props
,
State
>
{
constructor
(
props
:
Props
)
{
super
(
props
);
}
state
=
{
activeTab
:
'
0
'
,
cache
:
getValidObj
(
this
.
props
),
dfs
:
objToArr
(
this
.
props
.
allData
.
dataformats
)
||
[],
libs
:
objToArr
(
this
.
props
.
allData
.
libraries
)
||
[],
resultDfs
:
resultDfs
.
concat
((
objToArr
(
this
.
props
.
allData
.
dataformats
)
||
[]).
filter
(
d
=>
d
.
name
.
startsWith
(
'
plot
'
)).
map
(
d
=>
d
.
name
)),
}
tabTo
=
(
tab
:
string
)
=>
{
if
(
this
.
activeTab
!==
tab
)
this
.
setState
({
activeTab
:
tab
});
}
changeContentsVal
=
(
field
:
string
,
val
:
any
)
=>
{
this
.
setState
({
cache
:
{
...
this
.
state
.
cache
,
contents
:
{
...
this
.
state
.
cache
.
contents
,
[
field
]:
val
}
}
});
}
updateGroup
=
(
oldGroup
:
any
,
newGroup
:
any
)
=>
{
const
gIdx
=
this
.
state
.
cache
.
contents
.
groups
.
findIndex
(
g
=>
JSON
.
stringify
(
g
)
===
JSON
.
stringify
(
oldGroup
));
const
newGroups
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
cache
.
contents
.
groups
));
newGroups
[
gIdx
]
=
newGroup
;
this
.
changeContentsVal
(
'
groups
'
,
newGroups
);
}
updateParameter
=
(
name
,
param
)
=>
{
const
ps
=
this
.
state
.
cache
.
contents
.
parameters
;
ps
[
name
]
=
param
;
this
.
changeContentsVal
(
'
parameters
'
,
ps
);
}
updateLibrary
=
(
name
,
lib
)
=>
{
const
ls
=
this
.
state
.
cache
.
contents
.
uses
;
ls
[
name
]
=
lib
;
this
.
changeContentsVal
(
'
uses
'
,
ls
);
}
updateResult
=
(
name
,
res
)
=>
{
const
rs
=
this
.
state
.
cache
.
contents
.
results
;
rs
[
name
]
=
res
;
this
.
changeContentsVal
(
'
results
'
,
rs
);
}
changeToAnalyzer
=
()
=>
{
const
contents
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
cache
.
contents
));
contents
.
groups
=
contents
.
groups
.
map
(
g
=>
{
delete
g
[
'
outputs
'
];
return
g
;
});
contents
.
results
=
{};
this
.
setState
({
cache
:
{
...
this
.
state
.
cache
,
contents
}
});
}
changeToNormal
=
()
=>
{
const
contents
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
state
.
cache
.
contents
));
delete
contents
.
results
;
if
(
contents
.
groups
.
length
>
0
)
contents
.
groups
[
0
].
outputs
=
{};
this
.
setState
({
cache
:
{
...
this
.
state
.
cache
,
contents
}
});
}
isAnalyzer
=
()
=>
{
return
this
.
state
.
cache
.
contents
.
results
?
true
:
false
;
}
descField
=
()
=>
{
return
getDescField
(
this
.
state
.
contents
);
}
deleteIO
=
(
group
,
type
)
=>
(
name
)
=>
{
delete
group
[
type
][
name
];
this
.
updateGroup
(
group
,
{
...
group
});
}
render
()
{
return
(
<
div
>
{
JSON
.
stringify
(
this
.
state
.
cache
)
}
<
Form
>
<
FormGroup
tag
=
'fieldset'
>
<
legend
>
Algorithm Settings
</
legend
>
<
FormGroup
>
<
Label
for
=
'algName'
>
Name
</
Label
>
<
Input
type
=
'text'
name
=
'name'
id
=
'algName'
placeholder
=
'New algorithm name...'
value
=
{
this
.
state
.
cache
.
name
}
onChange
=
{
(
e
)
=>
this
.
setState
({
cache
:
{
...
this
.
state
.
cache
,
name
:
e
.
target
.
value
}})
}
/>
</
FormGroup
>
<
FormGroup
>
<
Label
for
=
'algDesc'
>
Short Description
</
Label
>
<
Input
type
=
'text'
name
=
'desc'
id
=
'algDesc'
placeholder
=
'Algorithm description...'
value
=
{
this
.
state
.
cache
.
contents
[
this
.
descField
()]
}
onChange
=
{
(
e
)
=>
this
.
changeContentsVal
(
this
.
descField
(),
e
.
target
.
value
)
}
/>
</
FormGroup
>
<
FormGroup
check
>
<
Label
check
>
<
Input
type
=
'checkbox'
checked
=
{
this
.
isAnalyzer
()
}
onChange
=
{
e
=>
e
.
target
.
checked
?
this
.
changeToAnalyzer
()
:
this
.
changeToNormal
()
}
/>
{
'
'
}
Analyser
</
Label
>
</
FormGroup
>
<
FormGroup
check
>
<
Label
check
>
<
Input
type
=
'checkbox'
checked
=
{
this
.
state
.
cache
.
contents
.
splittable
?
true
:
false
}
onChange
=
{
e
=>
this
.
changeContentsVal
(
'
splittable
'
,
e
.
target
.
checked
)
}
/>
{
'
'
}
Splittable
</
Label
>
</
FormGroup
>
</
FormGroup
>
<
div
className
=
'mt-3 mb-3'
>
<
Nav
tabs
>
<
NavItem
>
<
NavLink
className
=
{
cn
({
active
:
this
.
state
.
activeTab
===
'
0
'
})
}
onClick
=
{
()
=>
this
.
tabTo
(
'
0
'
)
}
>
Endpoints
</
NavLink
>
</
NavItem
>
<
NavItem
>
<
NavLink
className
=
{
cn
({
active
:
this
.
state
.
activeTab
===
'
1
'
})
}
onClick
=
{
()
=>
this
.
tabTo
(
'
1
'
)
}
>
Parameters
</
NavLink
>
</
NavItem
>
<
NavItem
>
<
NavLink
className
=
{
cn
({
active
:
this
.
state
.
activeTab
===
'
2
'
})
}
onClick
=
{
()
=>
this
.
tabTo
(
'
2
'
)
}
>
Libraries
</
NavLink
>
</
NavItem
>
{
this
.
state
.
cache
.
contents
.
results
?
(
<
NavItem
>
<
NavLink
className
=
{
cn
({
active
:
this
.
state
.
activeTab
===
'
3
'
})
}
onClick
=
{
()
=>
this
.
tabTo
(
'
3
'
)
}
>
Results
</
NavLink
>
</
NavItem
>
)
:
''
}
</
Nav
>
<
TabContent
className
=
'mt-3'
activeTab
=
{
this
.
state
.
activeTab
}
>
<
TabPane
tabId
=
'0'
>
{
this
.
state
.
cache
.
contents
.
groups
.
map
((
group
,
i
)
=>
{
const
ioUpdate
=
(
subObj
:
string
)
=>
(
oldName
:
string
,
newName
:
string
,
newObj
:
any
)
=>
{
console
.
log
(
`changing
${
subObj
}
"
${
oldName
}
" -> "
${
newName
}
":"
${
newObj
.
type
}
"`
);
const
changedObj
=
changeObjFieldName
(
group
[
subObj
],
oldName
,
newName
);
changedObj
[
newName
]
=
newObj
;
this
.
updateGroup
(
group
,
{
...
group
,
[
subObj
]:
changedObj
}
);
};
const
inputsUpdate
=
ioUpdate
(
'
inputs
'
);
const
outputsUpdate
=
ioUpdate
(
'
outputs
'
);
return
(
<
Row
key
=
{
i
}
className
=
'mb-2'
>
<
Col
sm
=
'12'
>
<
Card
>
<
CardHeader
>
<
InputGroup
>
<
DeleteInputBtn
deleteFunc
=
{
()
=>
this
.
changeContentsVal
(
'
groups
'
,
this
.
state
.
cache
.
contents
.
groups
.
filter
(
g
=>
g
.
name
!==
group
.
name
)
)
}
/>
<
Input
type
=
'text'
placeholder
=
'Group Name...'
value
=
{
group
.
name
}
onChange
=
{
(
e
)
=>
this
.
updateGroup
(
group
,
{...
group
,
name
:
e
.
target
.
value
}
)
}
/>
</
InputGroup
>
</
CardHeader
>
<
CardBody
>
<
Row
>
{
group
.
inputs
?
(
<
Col
sm
=
{
group
.
outputs
?
'
6
'
:
'
12
'
}
>
{
Object
.
entries
(
group
.
inputs
)
.
map
(([
name
,
ioObj
],
i
,
gEntries
)
=>
<
GroupIOBlock
key
=
{
i
}
name
=
{
name
}
ioObj
=
{
ioObj
}
dfs
=
{
this
.
state
.
dfs
}
updateFunc
=
{
inputsUpdate
}
deleteFunc
=
{
this
.
deleteIO
(
group
,
'
inputs
'
)
}
/>
)
}
<
Button
outline
block
onClick
=
{
(
e
)
=>
this
.
updateGroup
(
group
,
{
...
group
,
inputs
:
{
...
group
.
inputs
,
[
`input
${
Object
.
keys
(
group
.
inputs
).
length
}
`
]:
{
type
:
undefined
}
}
})
}
>
New Input
</
Button
>
</
Col
>
)
:
''
}
{
group
.
outputs
?
(
<
Col
sm
=
'6'
>
{
Object
.
entries
(
group
.
outputs
)
.
map
(([
name
,
ioObj
],
i
)
=>
<
GroupIOBlock
key
=
{
i
}
name
=
{
name
}
ioObj
=
{
ioObj
}
dfs
=
{
this
.
state
.
dfs
}
updateFunc
=
{
outputsUpdate
}
deleteFunc
=
{
this
.
deleteIO
(
group
,
'
outputs
'
)
}
/>
)
}
<
Button
outline
block
onClick
=
{
(
e
)
=>
this
.
updateGroup
(
group
,
{
...
group
,
outputs
:
{
...
group
.
outputs
,
[
`output
${
Object
.
keys
(
group
.
outputs
).
length
}
`
]:
{
type
:
undefined
}
}
})
}
>
New Output
</
Button
>
</
Col
>
)
:
''
}
</
Row
>
</
CardBody
>
</
Card
>
</
Col
>
</
Row
>
);
})
}
<
Button
outline
block
onClick
=
{
(
e
)
=>
this
.
changeContentsVal
(
'
groups
'
,
this
.
state
.
cache
.
contents
.
groups
.
concat
([
[
[
'
name
'
,
`group
${
this
.
state
.
cache
.
contents
.
groups
.
length
}
`
],
[
'
inputs
'
,
{}]
].
reduce
((
o
,
[
name
,
val
])
=>
({...
o
,
[
name
]:
val
}),
!
this
.
isAnalyzer
()
&&
this
.
state
.
cache
.
contents
.
groups
.
length
===
0
?
{
outputs
:
{}
}
:
{})
]))
}
>
New Group
</
Button
>
</
TabPane
>
<
TabPane
tabId
=
'1'
>
{
this
.
state
.
cache
.
contents
.
parameters
?
(
Object
.
entries
(
this
.
state
.
cache
.
contents
.
parameters
).
map
(([
name
,
param
],
i
)
=>
(
<
Row
key
=
{
i
}
className
=
'mb-2'
>
<
Col
sm
=
'12'
>
<
FormGroup
row
>
<
Col
sm
=
'4'
>
<
InputGroup
>
<
DeleteInputBtn
deleteFunc
=
{
()
=>
{
const
ps
=
this
.
state
.
cache
.
contents
.
parameters
;
delete
ps
[
name
];
this
.
changeContentsVal
(
'
parameters
'
,
ps
);
}
}
/>
<
Input
type
=
'text'
placeholder
=
'Name'
value
=
{
name
}
onChange
=
{
(
e
)
=>
this
.
changeContentsVal
(
'
parameters
'
,
changeObjFieldName
(
this
.
state
.
cache
.
contents
.
parameters
,
name
,
e
.
target
.
value
)
)
}
/>
</
InputGroup
>
</
Col
>
<
Col
sm
=
'2'
>
<
Input
type
=
'select'
className
=
'custom-select'
value
=
{
param
.
type
}
onChange
=
{
(
e
)
=>
this
.
updateParameter
(
name
,
{
...
param
,
type
:
e
.
target
.
value
})
}
>
<
option
disabled
>
Type
</
option
>
{
builtinDfs
.
map
((
d
,
i
)
=>
(
<
option
key
=
{
i
}
value
=
{
d
}
>
{
d
}
</
option
>
))
}
</
Input
>
</
Col
>
<
Col
sm
=
'2'
>
<
Input
type
=
'text'
placeholder
=
'Default'
value
=
{
param
.
default
}
onChange
=
{
(
e
)
=>
this
.
updateParameter
(
name
,
{
...
param
,
default
:
e
.
target
.
value
})
}
/>
</
Col
>
<
Col
>
<
Input
type
=
'text'
placeholder
=
'Description'
value
=
{
param
[
name
]
||
param
.
description
||
''
}
onChange
=
{
(
e
)
=>
this
.
updateParameter
(
name
,
{
...
param
,
description
:
e
.
target
.
value
})
}
/>
</
Col
>
</
FormGroup
>
</
Col
>
</
Row
>
)))
:
''
}
<
Button
outline
block
onClick
=
{
()
=>
this
.
changeContentsVal
(
'
parameters
'
,
{...(
this
.
state
.
cache
.
contents
.
parameters
||
{}),
[
`parameter
${
Object
.
keys
(
this
.
state
.
cache
.
contents
.
parameters
||
{}).
length
}
`
]:
{
type
:
undefined
,
default
:
''
,
description
:
''
,