diff --git a/ide/static/css/style.css b/ide/static/css/style.css index 08adb3fa5..3c4472b22 100644 --- a/ide/static/css/style.css +++ b/ide/static/css/style.css @@ -25,18 +25,18 @@ body { height: calc(100% - 50px); overflow-y: auto; } -#sidebar-content{ +#sidebar-content { padding: 0 5% 0 5%; } -.sidebar-heading{ +.sidebar-heading { font-family: 'ProximaNova-Bold', sans-serif; color: #9ea2a9; margin: 0px; padding: 10px 0px 10px 0px; } -.sidebar-badge{ +.sidebar-badge { padding: 10px; border-radius: 3px; margin-right: 10px; @@ -132,7 +132,28 @@ input#netName.hidden { right: 4%; } -.canvas-icon > p{ +#deleteSelected { + margin: 0px; + position: fixed; + bottom: 15%; + right: 3.5%; +} + +#deleteSelected > button { + border-radius: 15px; + box-shadow: 0px 0px 30px #5C5960; + -o-box-shadow: 0px 0px 15px #5C5960; + -webkit-box-shadow: 0px 0px 15px #5C5960; + -moz-box-shadow: 0px 0px 15px #5C5960; +} + +.selected-layer { + -webkit-box-shadow: 0px 0px 0px 6px #4483DA; + -moz-box-shadow: 0px 0px 0px 6px #4483DA; + box-shadow: 0px 0px 0px 6px #4483DA; +} + +.canvas-icon > p { margin: 0px; color: #9ea2a9; } @@ -1213,4 +1234,4 @@ input[type="file"] { background: white; transform: rotate(-45deg) } -} \ No newline at end of file +} diff --git a/ide/static/img/zoo/vnect_net.png b/ide/static/img/zoo/vnect_net.png new file mode 100644 index 000000000..a2caeef71 Binary files /dev/null and b/ide/static/img/zoo/vnect_net.png differ diff --git a/ide/static/js/canvas.js b/ide/static/js/canvas.js index 6d28f1541..70bd3b2f8 100644 --- a/ide/static/js/canvas.js +++ b/ide/static/js/canvas.js @@ -10,7 +10,11 @@ import $ from 'jquery' class Canvas extends React.Component { constructor(props) { super(props); + this.state = { + selectCount : 0 + } this.allowDrop = this.allowDrop.bind(this); + this.deleteLayers = this.deleteLayers.bind(this); this.drop = this.drop.bind(this); this.scrollCanvas = this.scrollCanvas.bind(this); this.clickCanvas = this.clickCanvas.bind(this); @@ -380,6 +384,31 @@ class Canvas extends React.Component { } this.props.setDraggingLayer(null); } + addLayerToSelectedList(id) { + if(this.props.selectedLayer != id) { + this.props.selectedLayers.push(id); + this.setState({ + selectCount:this.state.selectCount+1 + }); + } + } + removeLayerFromSelectedList(id) { + if(this.props.selectedLayer != id) { + var index = this.props.selectedLayers.indexOf(id); + if (index > -1) { + this.props.selectedLayers.splice(index, 1); + this.setState({ + selectCount:this.state.selectCount-1 + }); + } + } + } + deleteLayers() { + this.props.deleteMultipleLayers() + this.setState({ + selectCount:0 + }); + } render() { const layers = []; const errors = []; @@ -415,11 +444,12 @@ class Canvas extends React.Component { } }); } - } if ((layer.info.phase === this.props.selectedPhase) || (layer.info.phase === null)) { layers.push( this.addLayerToSelectedList(id)} + removeLayerFromSelectedList={(id) => this.removeLayerFromSelectedList(id)} id={layerId} key={layerId} type={layer.info.type} @@ -432,6 +462,7 @@ class Canvas extends React.Component { layer={layer} net={this.props.net} addSharedComment={this.props.addSharedComment} + selectedLayer={this.props.selectedLayer} isShared={this.props.isShared} isForked={this.props.isForked} changeCommentOnLayer={this.props.changeCommentOnLayer} @@ -500,12 +531,46 @@ class Canvas extends React.Component { +
0? 'visible': 'hidden'}} + id="deleteSelected" > + +
+ ); } } Canvas.propTypes = { + deleteMultipleLayers: React.PropTypes.func, + selectedLayers:React.PropTypes.array, nextLayerId: React.PropTypes.number, selectedPhase: React.PropTypes.number, net: React.PropTypes.object.isRequired, diff --git a/ide/static/js/content.js b/ide/static/js/content.js index 9a0c92d4c..3c820a15a 100644 --- a/ide/static/js/content.js +++ b/ide/static/js/content.js @@ -37,6 +37,7 @@ class Content extends React.Component { constructor(props) { super(props); this.state = { + selectedLayers:[], net: {}, net_name: 'Untitled', networkId: 0, @@ -70,6 +71,7 @@ class Content extends React.Component { this.adjustParameters = this.adjustParameters.bind(this); this.modifyLayerParams = this.modifyLayerParams.bind(this); this.deleteLayer = this.deleteLayer.bind(this); + this.deleteMultipleLayers = this.deleteMultipleLayers.bind(this); this.exportPrep = this.exportPrep.bind(this); this.exportNet = this.exportNet.bind(this); this.importNet = this.importNet.bind(this); @@ -488,13 +490,10 @@ class Content extends React.Component { this.setState({ net }); } } - deleteLayer(layerId, publishUpdate=true) { + deleteLayer(layerId, publishUpdate=true) { const net = this.state.net; const input = net[layerId].connection.input; const output = net[layerId].connection.output; - const layerIdNum = parseInt(layerId.substring(1,layerId.length)); //numeric value of the layerId - const nextLayerId = this.state.nextLayerId - 1 == layerIdNum ? layerIdNum : this.state.nextLayerId; - //if last layer was deleted nextLayerId is replaced by deleted layer's id var totalParameters = this.state.totalParameters; let index; totalParameters -= this.getLayerParameters(net[layerId], net); @@ -507,6 +506,14 @@ class Content extends React.Component { index = net[outputId].connection.input.indexOf(layerId); net[outputId].connection.input.splice(index, 1); }); + let layersIds = Object.keys(net); + //if a layer was deleted nextLayerId is replaced by index of last layer id in the net + let nextLayerId; + if(layersIds[layersIds.length - 1]) { + nextLayerId = parseInt(layersIds[layersIds.length - 1].substring(1,layersIds.length))+1; + } else { + nextLayerId = 0; + } this.setState({ net, selectedLayer: null, nextLayerId: nextLayerId, totalParameters: totalParameters }); // if model is in RTC mode send updates to respective sockets // to avoid infinite loop of deletion over multiple session @@ -1113,7 +1120,7 @@ class Content extends React.Component { here.
Q: What do the Train/Test buttons mean?
- A: They are two different modes of your model: + A: They are two different modes of your model: Train and Test - respectively for training your model with data and testing how and if it works.
Q: What does the import fuction do?
A: It allows you to import your previously created models in Caffe (.protoxt files), @@ -1127,7 +1134,7 @@ class Content extends React.Component { A: Please see the instructions listed here

- + If you have anymore questions, please visit Fabrik's Github page available here for more information.

); @@ -1282,6 +1289,37 @@ class Content extends React.Component { this.addNewLayer(layer); } } + deleteMultipleLayers() { + var net = this.state.net; + var totalParameters = this.state.totalParameters; + // var layerIdNum; + var _nextLayerId = this.state.nextLayerId; + if(this.state.selectedLayers.length > 0) { + this.state.selectedLayers.forEach((layerId)=>{ + const input = net[layerId].connection.input; + const output = net[layerId].connection.output; + let index; + totalParameters -= this.getLayerParameters(net[layerId], net); + delete net[layerId]; + input.forEach(inputId => { + index = net[inputId].connection.output.indexOf(layerId); + net[inputId].connection.output.splice(index, 1); + }); + output.forEach(outputId => { + index = net[outputId].connection.input.indexOf(layerId); + net[outputId].connection.input.splice(index, 1); + }); + }); + var layersIds = Object.keys(net); + if(layersIds[layersIds.length - 1]) { + _nextLayerId = parseInt(layersIds[layersIds.length - 1].substring(1,layersIds.length))+1; + } else { + _nextLayerId = 0; + } + this.setState({ net, nextLayerId: _nextLayerId, totalParameters: totalParameters }); + this.state.selectedLayers.splice(0,this.state.selectedLayers.length); + } + } render() { let loader = null; if (this.state.load) { @@ -1338,6 +1376,8 @@ class Content extends React.Component { {loader} 0) { highlightClass = 'highlighted'; @@ -78,19 +100,21 @@ class Layer extends React.Component { ); } + const layerStyle = { + top:this.props.top, + left:this.props.left, + background: this.defaultColor, + borderColor: highlightColor + } return (
this.props.click(event, this.props.id)} + onClick={(event) => this.leftClick(event)} onMouseEnter={(event) => this.props.hover(event, this.props.id)} + onContextMenu={(event) => this.select(event, this.props.id)} onMouseUp={(event) => this.props.mouseUp(event, this.props.id)} data-tip='tooltip' data-for='getContent' @@ -116,10 +140,13 @@ Layer.propTypes = { mouseUp: React.PropTypes.func, layer: React.PropTypes.object, net: React.PropTypes.object, + addLayerToSelectedList:React.PropTypes.func, + removeLayerFromSelectedList:React.PropTypes.func, addSharedComment: React.PropTypes.func, isShared: React.PropTypes.bool, isForked: React.PropTypes.bool, - changeCommentOnLayer: React.PropTypes.func + changeCommentOnLayer: React.PropTypes.func, + selectedLayer: React.PropTypes.string }; export default Layer;