Comparar commits
74 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 5135ccef09 | |||
| 6314e00a8d | |||
| 779429e24d | |||
| a7f4eac09d | |||
| 7c645e9b23 | |||
| fc3e14644f | |||
| fd48c1b480 | |||
| 8928d0f105 | |||
| 6857da5ac7 | |||
| fee584cfde | |||
| 45fcd81739 | |||
| d831f5e032 | |||
| 65e938f489 | |||
| b9b5cea5a1 | |||
| 6c639376d1 | |||
| 58ed3048f8 | |||
| f64492061d | |||
| 552e71687d | |||
| 448de23945 | |||
| dbd00e5946 | |||
| 4d0b4ae017 | |||
| d6c201cce6 | |||
| b8bc3af524 | |||
| 72de1d44da | |||
| da6f186b52 | |||
| 5f1c50beb6 | |||
| 3a79afbc41 | |||
| ba210e4b27 | |||
| bdb21a5262 | |||
| 4b6471efbc | |||
| beeb1deb3c | |||
| 0bc6846c32 | |||
| 8a40cb95fb | |||
| 92ea4b2ff5 | |||
| e0a83b4d6c | |||
| 49268b9554 | |||
| 65164bcb76 | |||
| 1afcaf9238 | |||
| 92021a06ba | |||
| be1e4fa388 | |||
| 09505c9989 | |||
| b96f2a845a | |||
| 14c0af86c9 | |||
| 56a0b788ee | |||
| 873cbc2145 | |||
| 3e3326688c | |||
| 6e32394e01 | |||
| afed957af8 | |||
| 4c100ac001 | |||
| 29724551f0 | |||
| 1f5c8d7423 | |||
| a613a1e8f7 | |||
| 7fce6e98dd | |||
| ea572e8f6c | |||
| 36290d8dc7 | |||
| dadc09e0e1 | |||
| be3d278d13 | |||
| 32a96fbf2b | |||
| ebe391c948 | |||
| e30ebf3a45 | |||
| 9e0a780ed2 | |||
| 841637e804 | |||
| 75241262c4 | |||
| b39ac022b6 | |||
| 8486b86a05 | |||
| 322af8a4f5 | |||
| 5e1930f096 | |||
| c0f1348a14 | |||
| 383f5f9fa0 | |||
| 5cf592e103 | |||
| a14e750b6f | |||
| 73e165197f | |||
| 9dd0815625 | |||
| 8e3ac1d203 |
@@ -0,0 +1,35 @@
|
||||
---
|
||||
engines:
|
||||
csslint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
exclude_fingerprints:
|
||||
- 1e004cf4e49528a58a0ac3858112601c
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
- python
|
||||
- php
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.css"
|
||||
- "**.inc"
|
||||
- "**.js"
|
||||
- "**.jsx"
|
||||
- "**.module"
|
||||
- "**.php"
|
||||
- "**.py"
|
||||
- "**.rb"
|
||||
exclude_paths:
|
||||
- config/
|
||||
- test/
|
||||
- src/common/lua.js
|
||||
- src/common/js-yaml.min.js
|
||||
- src/visualizers/widgets/TextEditor/lib/
|
||||
- src/visualizers/widgets/PipelineIndex/styles/PipelineIndex.css
|
||||
@@ -0,0 +1,3 @@
|
||||
--exclude-exts=.min.css
|
||||
--exclude-list=src/visualizers/widgets/PipelineIndex/styles/PipelineIndex.css
|
||||
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
[](https://img.shields.io/badge/state-alpha-orange.svg)
|
||||
[](https://img.shields.io/badge/state-beta-yellow.svg)
|
||||
[](./LICENSE)
|
||||
[](https://travis-ci.org/dfst/deepforge)
|
||||
[](https://gitter.im/dfst/deepforge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://waffle.io/dfst/deepforge)
|
||||
|
||||
**Notice**: DeepForge is still very much a work in progress and is also lacking significant documentation! That being said, any contributions and/or feedback is greatly appreciated (and feel free to always ask any questions on the gitter)!
|
||||
**Notice**: DeepForge is still a work in progress and is also lacking significant documentation! That being said, any contributions and/or feedback is greatly appreciated (and feel free to always ask any questions on the gitter)!
|
||||
|
||||
# DeepForge
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks but we are planning on supporting additional deep learning classifiers such as RNNs and LSTMs. Additional features include real-time collaborative editing and version control.
|
||||
@@ -20,8 +20,8 @@ Next, follow the postinstall instructions to start MongoDB and DeepForge!
|
||||
|
||||
Finally, navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions,check out our [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
|
||||
|
||||
## Caffe Support?
|
||||
DeepForge uses Torch to perform the actual training and testing of the models. If you are interested in DeepForge using Caffe for actual training and testing, check out [DeepForge-Caffe](https://github.com/dfst/deepforge-caffe).
|
||||
|
||||
## Interested in contributing?
|
||||
Contributions are welcome! Either fork the project and submit some PR's or shoot me an email about getting more involved!
|
||||
|
||||
Sponsored by [Digital Reasoning](http://www.digitalreasoning.com/)
|
||||
|
||||
+16
-27
@@ -1,8 +1,19 @@
|
||||
{
|
||||
"AutoViz": {
|
||||
"preloadIds": [
|
||||
"ArchEditor",
|
||||
"PipelineEditor",
|
||||
"OperationEditor",
|
||||
"ExecutionView"
|
||||
]
|
||||
},
|
||||
"ArchEditor": {
|
||||
"hotkeys": "none",
|
||||
"LayerColors": {}
|
||||
},
|
||||
"BreadcrumbHeader": {
|
||||
"pathRule": "history"
|
||||
},
|
||||
"FloatingActionButton": {
|
||||
"hideOnEmpty": true
|
||||
},
|
||||
@@ -43,48 +54,26 @@
|
||||
"nodes": [
|
||||
{
|
||||
"nodeName": "MyArchitectures",
|
||||
"title": "Architectures",
|
||||
"icon": "shuffle",
|
||||
"rank": 1,
|
||||
"description": "Neural network architectures are stored here and can be used in pipelines."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyOperations",
|
||||
"icon": "mode_edit",
|
||||
"rank": 2,
|
||||
"color": "blue-grey",
|
||||
"description": "Operations are the building blocks of pipelines. Custom operations can be created and stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyPipelines",
|
||||
"title": "Pipelines",
|
||||
"color": "blue-grey",
|
||||
"icon": "input",
|
||||
"rank": 3,
|
||||
"description": "Pipelines compose operations together to effectively train, test and/or ensemble models."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyLayers",
|
||||
"icon": "clear_all",
|
||||
"rank": 4,
|
||||
"color": "blue-grey",
|
||||
"description": "Custom torch layers can be created and stored here for use in neural network architectures."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyArtifacts",
|
||||
"title": "Artifacts",
|
||||
"icon": "view_quilt",
|
||||
"color": "blue-grey",
|
||||
"rank": 5,
|
||||
"description": "Artifacts from pipeline executions are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyExecutions",
|
||||
"icon": "list",
|
||||
"rank": 6,
|
||||
"color": "blue-grey",
|
||||
"description": "Executions are read-only snapshots of pipelines that have been executed. Past and current executing pipelines are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyDataTypes",
|
||||
"icon": "settings",
|
||||
"rank": 7,
|
||||
"description": "Custom defined data types are stored here."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ var config = require('./config.webgme'),
|
||||
require('dotenv').load({silent: true});
|
||||
|
||||
// Add/overwrite any additional settings here
|
||||
config.server.port = process.env.PORT || config.server.port;
|
||||
config.server.port = +process.env.PORT || config.server.port;
|
||||
config.mongo.uri = process.env.MONGO_URI || config.mongo.uri;
|
||||
config.requirejsPaths.deepforge = './src/common';
|
||||
config.seedProjects.defaultProject = 'project';
|
||||
@@ -16,6 +16,7 @@ config.plugin.allowBrowserExecution = true;
|
||||
config.plugin.allowServerExecution = true;
|
||||
|
||||
config.executor.enable = true;
|
||||
config.executor.clearOldDataAtStartUp = true;
|
||||
|
||||
config.visualization.extraCss.push('deepforge/styles/global.css');
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ config.seedProjects.basePaths.push('src/seeds/devTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/devUtilTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push('src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/demo');
|
||||
config.seedProjects.basePaths.push('src/seeds/project');
|
||||
config.seedProjects.basePaths.push('src/seeds/cifar10');
|
||||
|
||||
|
||||
+42
-2
@@ -53,6 +53,7 @@ command -v node >/dev/null 2>&1 || {
|
||||
echo >&2 "NodeJS is not found. Installing (using nvm)...";
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash;
|
||||
source $DETECTED_PROFILE
|
||||
. $NVM_DIR/nvm.sh
|
||||
|
||||
# Install nodejs v6.2.0
|
||||
echo "Installing nodejs v6.2.0"
|
||||
@@ -61,7 +62,6 @@ command -v node >/dev/null 2>&1 || {
|
||||
|
||||
# Install npm@2
|
||||
npm install npm@2 -g
|
||||
|
||||
}
|
||||
|
||||
command -v node >/dev/null 2>&1 || {
|
||||
@@ -69,6 +69,35 @@ command -v node >/dev/null 2>&1 || {
|
||||
echo >&2 "MongoDB is not found. Installing...";
|
||||
if [[ `uname` == "Darwin" ]]; then
|
||||
brew install mongodb
|
||||
elif [[ "$(uname)" == 'Linux' ]]; then
|
||||
|
||||
if [[ -r /etc/os-release ]]; then
|
||||
# this will get the required information without dirtying any env state
|
||||
DIST_VERS="$( ( . /etc/os-release &>/dev/null
|
||||
echo "$ID $VERSION_ID") )"
|
||||
DISTRO="${DIST_VERS%% *}" # get our distro name
|
||||
VERSION="${DIST_VERS##* }" # get our version number
|
||||
elif [[ -r /etc/lsb-release ]]; then
|
||||
DIST_VERS="$( ( . /etc/lsb-release &>/dev/null
|
||||
echo "${DISTRIB_ID,,} $DISTRIB_RELEASE") )"
|
||||
DISTRO="${DIST_VERS%% *}" # get our distro name
|
||||
VERSION="${DIST_VERS##* }" # get our version number
|
||||
else # well, I'm out of ideas for now
|
||||
echo '==> Failed to determine distro and version.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect archlinux
|
||||
if [[ "$DISTRO" = "arch" ]]; then
|
||||
distribution="archlinux"
|
||||
sudo pacman -S mongodb
|
||||
# Detect Ubuntu
|
||||
elif [[ "$DISTRO" = "ubuntu" ]]; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo apt-get install mongodb
|
||||
else
|
||||
NEEDS_MONGO=true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -80,7 +109,18 @@ cd ~/deepforge
|
||||
npm install
|
||||
|
||||
mkdir ~/deepforge/data 2> /dev/null
|
||||
echo "DeepForge is installed! To run it:"
|
||||
|
||||
echo "Final Installation steps:"
|
||||
echo " 1) Close and re-open your terminal"
|
||||
echo " (or run \"source $DETECTED_PROFILE\")"
|
||||
|
||||
if [[ $NEEDS_MONGO ]]; then
|
||||
echo " 2) Install MongoDB for your OS"
|
||||
echo " (available at https://www.mongodb.com/download-center)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Then run DeepForge!"
|
||||
echo " 1) make sure MongoDB is running locally"
|
||||
echo " (start mongo w/ \"mongod --dbpath ~/deepforge/data\")"
|
||||
echo " 2) Run \"npm run local\" from ~/deepforge"
|
||||
|
||||
+3
-3
@@ -9,14 +9,14 @@
|
||||
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'",
|
||||
"build-nn": "node ./utils/nn-parser.js"
|
||||
},
|
||||
"version": "0.7.0",
|
||||
"version": "0.9.0",
|
||||
"dependencies": {
|
||||
"dotenv": "^2.0.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"nodemon": "^1.9.2",
|
||||
"webgme": "^2.0.0",
|
||||
"webgme-autoviz": "^2.0.3",
|
||||
"webgme-breadcrumbheader": "^2.0.0",
|
||||
"webgme-autoviz": "dfst/webgme-autoviz",
|
||||
"webgme-breadcrumbheader": "^2.1.0",
|
||||
"webgme-chflayout": "^2.0.0",
|
||||
"webgme-easydag": "dfst/webgme-easydag",
|
||||
"webgme-fab": "dfst/webgme-fab",
|
||||
|
||||
+97
-5
@@ -1,4 +1,4 @@
|
||||
/* globals WebGMEGlobal, define*/
|
||||
/* globals Materialize, WebGMEGlobal, define*/
|
||||
// This file creates the DeepForge namespace and defines basic actions
|
||||
define([
|
||||
'js/RegistryKeys',
|
||||
@@ -89,13 +89,14 @@ define([
|
||||
return name;
|
||||
};
|
||||
|
||||
/////////// Initializing DeepForge ///////////
|
||||
//////////////////// DeepForge places detection ////////////////////
|
||||
var TYPE_TO_CONTAINER = {
|
||||
|
||||
Architecture: 'MyArchitectures',
|
||||
Pipeline: 'MyPipelines',
|
||||
Execution: 'MyExecutions',
|
||||
Layer: 'MyLayers',
|
||||
Artifact: 'MyArtifacts',
|
||||
Operation: 'MyOperations',
|
||||
Primitive: 'MyDataTypes',
|
||||
Complex: 'MyDataTypes'
|
||||
@@ -141,8 +142,7 @@ define([
|
||||
placesTerritoryId = null;
|
||||
};
|
||||
|
||||
// Add DeepForge action primitives
|
||||
// Creating custom operations
|
||||
//////////////////// DeepForge creation actions ////////////////////
|
||||
var instances = [
|
||||
'Architecture',
|
||||
'Pipeline'
|
||||
@@ -180,6 +180,92 @@ define([
|
||||
return newId;
|
||||
};
|
||||
|
||||
var createCustomLayer = function(typeName) {
|
||||
var metanodes = client.getAllMetaNodes(),
|
||||
msg = `Created new custom ${typeName} layer`,
|
||||
newId,
|
||||
customLayerId,
|
||||
baseId,
|
||||
name,
|
||||
i = metanodes.length;
|
||||
|
||||
while (i-- && !(baseId && customLayerId)) {
|
||||
name = metanodes[i].getAttribute('name');
|
||||
if (name === 'CustomLayer') {
|
||||
customLayerId = metanodes[i].getId();
|
||||
} else if (name === typeName) {
|
||||
baseId = metanodes[i].getId();
|
||||
}
|
||||
}
|
||||
|
||||
client.startTransaction(msg);
|
||||
|
||||
newId = createNamedNode(baseId, DeepForge.places.MyLayers, true);
|
||||
addToMetaSheet(newId, 'CustomLayers');
|
||||
client.addMixin(newId, customLayerId);
|
||||
client.setRegistry(newId, REGISTRY_KEYS.IS_ABSTRACT, false);
|
||||
|
||||
client.completeTransaction();
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
};
|
||||
|
||||
// Creating Artifacts
|
||||
var UPLOAD_PLUGIN = 'ImportArtifact',
|
||||
DATA_TYPE_CONFIG = {
|
||||
name: 'dataTypeId',
|
||||
displayName: 'Data Type Id',
|
||||
valueType: 'string',
|
||||
valueItems: []
|
||||
};
|
||||
|
||||
var uploadArtifact = function() {
|
||||
// Get the data types
|
||||
var dataBase,
|
||||
dataBaseId,
|
||||
metanodes = client.getAllMetaNodes(),
|
||||
dataTypes = [];
|
||||
|
||||
dataBase = metanodes.find(n => n.getAttribute('name') === 'Data');
|
||||
|
||||
if (!dataBase) {
|
||||
this.logger.error('Could not find the base Data node!');
|
||||
return;
|
||||
}
|
||||
|
||||
dataBaseId = dataBase.getId();
|
||||
dataTypes = metanodes.filter(n => client.isTypeOf(n.getId(), dataBaseId))
|
||||
.filter(n => !n.getRegistry('isAbstract'))
|
||||
.map(node => node.getAttribute('name'));
|
||||
|
||||
//this.logger.info(`Found ${dataTypes.length} data types`);
|
||||
|
||||
// Add the target type to the pluginMetadata... hacky :/
|
||||
var metadata = WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN],
|
||||
config = metadata.configStructure
|
||||
.find(opt => opt.name === DATA_TYPE_CONFIG.name);
|
||||
|
||||
if (!config) {
|
||||
config = DATA_TYPE_CONFIG;
|
||||
WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN].configStructure.push(config);
|
||||
}
|
||||
|
||||
config.valueItems = dataTypes;
|
||||
config.value = dataTypes[0];
|
||||
|
||||
WebGMEGlobal.InterpreterManager.configureAndRun(metadata, (result) => {
|
||||
var msg = 'Artifact upload complete!';
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
if (!result.success) {
|
||||
msg = `Artifact upload failed: ${result.error}`;
|
||||
}
|
||||
Materialize.toast(msg, 2000);
|
||||
});
|
||||
};
|
||||
|
||||
DeepForge.last = {};
|
||||
DeepForge.create = {};
|
||||
instances.forEach(type => {
|
||||
DeepForge.create[type] = function() {
|
||||
@@ -193,10 +279,16 @@ define([
|
||||
};
|
||||
});
|
||||
|
||||
DeepForge.create.Layer = createCustomLayer;
|
||||
DeepForge.create.Artifact = uploadArtifact;
|
||||
|
||||
//////////////////// DeepForge prev locations ////////////////////
|
||||
// Update DeepForge on project changed
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_PROJECT_NAME, updateDeepForgeNamespace, null);
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_PROJECT_NAME,
|
||||
updateDeepForgeNamespace, null);
|
||||
|
||||
// define DeepForge globally
|
||||
window.DeepForge = DeepForge;
|
||||
|
||||
return DeepForge;
|
||||
});
|
||||
|
||||
@@ -2687,6 +2687,7 @@ function LuaContext(){
|
||||
}
|
||||
exports.stdlib(_G, helpers)();
|
||||
}
|
||||
this.__helpers = helpers;
|
||||
}
|
||||
|
||||
LuaContext.prototype = {}
|
||||
|
||||
@@ -18,3 +18,7 @@
|
||||
.deepforge-logo .item-label {
|
||||
font-family: 'Audiowide', cursive;
|
||||
}
|
||||
|
||||
.create-node text {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
.new-node-decorator rect {
|
||||
fill: #78909C;
|
||||
/*fill: #90caf9;*/
|
||||
}
|
||||
|
||||
.new-node-decorator circle {
|
||||
fill: #81c784;
|
||||
/*fill: #90caf9;*/
|
||||
}
|
||||
|
||||
.new-node-decorator line {
|
||||
stroke: white;
|
||||
stroke-width: 4px;
|
||||
}
|
||||
|
||||
.new-node-decorator .dark line {
|
||||
stroke: black;
|
||||
stroke-width: 2.5px;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* globals define */
|
||||
// This contains decorators for actions such as 'New Operation' so
|
||||
// the given action can be used as a node in NodePrompter, etc
|
||||
define([
|
||||
'css!./AddDecorator.css'
|
||||
], function(
|
||||
) {
|
||||
|
||||
var NewDecorator = function (opts) {
|
||||
this.$el = opts.parentEl.append('g')
|
||||
.attr('class', 'centering-offset');
|
||||
|
||||
this.$body = this.$el.append('g')
|
||||
.attr('class', 'new-node-decorator');
|
||||
|
||||
this.radius = opts.radius || 20;
|
||||
this.height = this.radius*2;
|
||||
this.width = opts.width || 90;
|
||||
this.size = this.radius * 1.00;
|
||||
|
||||
if (opts.circle) {
|
||||
this.render = this.renderCircle;
|
||||
} else {
|
||||
this.render = this.renderRect;
|
||||
}
|
||||
};
|
||||
|
||||
NewDecorator.prototype.renderRect = function() {
|
||||
this.$body.remove();
|
||||
this.$body = this.$el.append('g')
|
||||
.attr('class', 'new-node-decorator');
|
||||
|
||||
this.$body.append('rect')
|
||||
.attr('x', 0)
|
||||
.attr('y', 0)
|
||||
.attr('width', this.width)
|
||||
.attr('height', this.height);
|
||||
|
||||
this.renderPlus()
|
||||
.attr('class', 'dark')
|
||||
.attr('transform', `translate(${this.width/2-this.size}, 0)`);
|
||||
|
||||
};
|
||||
|
||||
NewDecorator.prototype.renderCircle = function() {
|
||||
this.$body.remove();
|
||||
this.$body = this.$el.append('g')
|
||||
.attr('class', 'new-node-decorator');
|
||||
|
||||
this.$body.append('circle')
|
||||
.attr('cx', this.radius)
|
||||
.attr('cy', this.radius)
|
||||
.attr('r', this.radius);
|
||||
|
||||
this.renderPlus();
|
||||
this.$el.attr('transform', `translate(${this.width/2-this.size}, ${this.height/2-this.size})`);
|
||||
};
|
||||
|
||||
NewDecorator.prototype.renderPlus = function() {
|
||||
// Create a large '+' symbol in a rectangle
|
||||
var start = this.radius-this.size/2,
|
||||
end = start + this.size,
|
||||
middle = (start+end)/2,
|
||||
plus = this.$body.append('g');
|
||||
|
||||
plus.append('line')
|
||||
.attr('x1', start)
|
||||
.attr('x2', end)
|
||||
.attr('y1', middle)
|
||||
.attr('y2', middle)
|
||||
.attr('stroke', 'black');
|
||||
|
||||
plus.append('line')
|
||||
.attr('x1', middle)
|
||||
.attr('x2', middle)
|
||||
.attr('y1', start)
|
||||
.attr('y2', end)
|
||||
.attr('stroke', 'black');
|
||||
|
||||
return plus;
|
||||
};
|
||||
|
||||
return NewDecorator;
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
define([
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'widgets/EasyDAG/Icons'
|
||||
], function(
|
||||
EasyDAGButtons,
|
||||
Icons
|
||||
) {
|
||||
|
||||
// Create a GoToBase button
|
||||
var client = WebGMEGlobal.Client;
|
||||
|
||||
var GoToBase = function(params) {
|
||||
// Check if it should be disabled
|
||||
var baseId = this._getBaseId(params.item),
|
||||
base = baseId && client.getNode(baseId);
|
||||
|
||||
if (!params.disabled) {
|
||||
params.disabled = base ? base.isLibraryElement() : true;
|
||||
}
|
||||
EasyDAGButtons.ButtonBase.call(this, params);
|
||||
};
|
||||
|
||||
GoToBase.SIZE = 10;
|
||||
GoToBase.BORDER = 1;
|
||||
GoToBase.prototype.BTN_CLASS = 'go-to-base';
|
||||
GoToBase.prototype = new EasyDAGButtons.ButtonBase();
|
||||
|
||||
GoToBase.prototype._render = function() {
|
||||
var lineRadius = GoToBase.SIZE - GoToBase.BORDER,
|
||||
btnColor = '#90caf9';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
}
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
.attr('r', GoToBase.SIZE)
|
||||
.attr('fill', btnColor);
|
||||
|
||||
// Show the 'code' icon
|
||||
Icons.addIcon('code', this.$el, {
|
||||
radius: lineRadius
|
||||
});
|
||||
};
|
||||
|
||||
GoToBase.prototype._onClick = function(item) {
|
||||
var node = client.getNode(item.id),
|
||||
baseId = node.getBaseId();
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(baseId);
|
||||
};
|
||||
|
||||
GoToBase.prototype._getBaseId = function(item) {
|
||||
var n = client.getNode(item.id);
|
||||
return n && n.getBaseId();
|
||||
};
|
||||
|
||||
return {
|
||||
DeleteOne: EasyDAGButtons.DeleteOne,
|
||||
GoToBase: GoToBase
|
||||
};
|
||||
});
|
||||
|
||||
@@ -7,9 +7,9 @@ define([
|
||||
var OperationControl = function() {
|
||||
};
|
||||
|
||||
OperationControl.prototype.hasMetaName = function(id, name) {
|
||||
OperationControl.prototype.hasMetaName = function(id, name, inclusive) {
|
||||
var node = this._client.getNode(id),
|
||||
bId = node.getBaseId(),
|
||||
bId = inclusive ? id : node.getBaseId(),
|
||||
baseName;
|
||||
|
||||
while (bId) {
|
||||
|
||||
@@ -72,6 +72,8 @@ define([
|
||||
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id),
|
||||
node = this._client.getNode(id);
|
||||
|
||||
desc.inputs = [];
|
||||
desc.outputs = [];
|
||||
if (this.hasMetaName(id, 'Operation')) {
|
||||
// Only decorate operations in the currently active node
|
||||
if (this._currentNodeId !== desc.parentId) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'underscore'
|
||||
], function(
|
||||
PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
_
|
||||
) {
|
||||
|
||||
var RenameablePanel = function() {
|
||||
PanelBaseWithHeader.apply(this, arguments);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
RenameablePanel.prototype,
|
||||
PanelBaseWithHeader.prototype,
|
||||
IActivePanel.prototype
|
||||
);
|
||||
|
||||
RenameablePanel.OPTIONS = PanelBaseWithHeader.OPTIONS;
|
||||
RenameablePanel.prototype.initializeRenameable = function () {
|
||||
this.$panelHeaderTitle.on('dblclick', this.editTitle.bind(this));
|
||||
};
|
||||
|
||||
RenameablePanel.prototype.currentNodeId = function () {
|
||||
return this.control._currentNodeId;
|
||||
};
|
||||
|
||||
RenameablePanel.prototype.currentBaseName = function () {
|
||||
var currentId = this.currentNodeId(),
|
||||
node = this._client.getNode(currentId),
|
||||
baseId = node.getBaseId(),
|
||||
base = this._client.getNode(baseId);
|
||||
|
||||
return base.getAttribute('name');
|
||||
};
|
||||
|
||||
RenameablePanel.prototype.editTitle = function () {
|
||||
this.$panelHeaderTitle.editInPlace({
|
||||
css: {
|
||||
'z-index': 1000
|
||||
},
|
||||
onChange: (oldValue, newValue) => {
|
||||
var nodeId = this.currentNodeId(),
|
||||
type = this.currentBaseName(),
|
||||
msg = `Renamed ${type}: ${oldValue} -> ${newValue}`;
|
||||
|
||||
if (!/^\s*$/.test(newValue)) {
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setAttributes(nodeId, 'name', newValue);
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return RenameablePanel;
|
||||
});
|
||||
@@ -53,7 +53,17 @@ define([
|
||||
ArtifactOpDecorator.prototype.savePointer = function(name, to) {
|
||||
// When the 'artifact' pointer is changed, we should change the base
|
||||
// of the data output node to the target type
|
||||
if (name === this.castOpts.ptr && (typeof to === 'string')) {
|
||||
if (typeof to !== 'string') {
|
||||
var outputId = this._node.outputs[0] && this._node.outputs[0].id;
|
||||
|
||||
// Clear the data handle of the output
|
||||
this.client.startTransaction(`Removing output of ${this.name}`);
|
||||
this.client.delPointer(this._node.id, name);
|
||||
if (outputId) {
|
||||
this.client.delAttributes(outputId, 'data');
|
||||
}
|
||||
this.client.completeTransaction();
|
||||
} else if (name === this.castOpts.ptr) { // set the casted value
|
||||
this.client.startTransaction(`Setting output of ${this.name} to ${to}`);
|
||||
this.castOutputType(to);
|
||||
this.client.makePointer(this._node.id, name, to);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* globals define, _*/
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/AttributeField'
|
||||
], function(
|
||||
AttributeFieldBase
|
||||
) {
|
||||
// Attribute field in which the label is clickable and the attribute meta is editable
|
||||
var AttributeField = function() {
|
||||
AttributeFieldBase.apply(this, arguments);
|
||||
this.$label.on('click', () => this.onLabelClick());
|
||||
};
|
||||
|
||||
_.extend(AttributeField.prototype, AttributeFieldBase.prototype);
|
||||
|
||||
return AttributeField;
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/* globals define */
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
|
||||
var CreateAttrField = function(logger, pEl, y) {
|
||||
this.$el = pEl.append('text')
|
||||
.attr('y', y)
|
||||
.attr('class', 'create-attr-field')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dominant-baseline', 'middle')
|
||||
.attr('font-weight', 'bold')
|
||||
.attr('font-style', 'italic')
|
||||
.text('New Attribute')
|
||||
.on('click', () => this.onClick());
|
||||
};
|
||||
|
||||
CreateAttrField.prototype.render =
|
||||
CreateAttrField.prototype.destroy = function() {};
|
||||
|
||||
CreateAttrField.prototype.width = function() {
|
||||
return this.$el[0][0].getBoundingClientRect().width;
|
||||
};
|
||||
|
||||
return CreateAttrField;
|
||||
});
|
||||
@@ -1,15 +1,17 @@
|
||||
/*globals define, $,_*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'./AttributeField',
|
||||
'./CreateAttributeField',
|
||||
'decorators/MetaDecorator/DiagramDesigner/AttributeDetailsDialog',
|
||||
'css!./OpIntDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
DecoratorBase
|
||||
DecoratorBase,
|
||||
AttributeField,
|
||||
CreateAttributeField,
|
||||
AttributeDetailsDialog
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
@@ -17,13 +19,7 @@ define([
|
||||
var OpIntDecorator,
|
||||
DECORATOR_ID = 'OpIntDecorator';
|
||||
|
||||
// OpInt nodes need to be able to...
|
||||
// - show their ports
|
||||
// - highlight ports
|
||||
// - unhighlight ports
|
||||
// - report the location of specific ports
|
||||
OpIntDecorator = function (options) {
|
||||
this.color = this.color || '#78909c';
|
||||
DecoratorBase.call(this, options);
|
||||
};
|
||||
|
||||
@@ -31,9 +27,9 @@ define([
|
||||
|
||||
OpIntDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
OpIntDecorator.prototype.initialize = function() {
|
||||
if (this._node.baseName === 'Operation') {
|
||||
if (this.isOperation()) {
|
||||
this.color = '#2196f3';
|
||||
} else {
|
||||
} else if (this._node.baseName) {
|
||||
// On hover, show the type
|
||||
this.enableTooltip(this._node.baseName, 'dark');
|
||||
}
|
||||
@@ -41,6 +37,108 @@ define([
|
||||
this.$name.on('dblclick', this.editName.bind(this));
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.AttributeField = AttributeField;
|
||||
OpIntDecorator.prototype.isOperation = function() {
|
||||
return this._node.baseName === 'Operation';
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.createAttributeFields = function(y, width) {
|
||||
var field,
|
||||
initialY = y;
|
||||
|
||||
if (!this.isOperation()) {
|
||||
return y;
|
||||
}
|
||||
|
||||
y = DecoratorBase.prototype.createAttributeFields.call(this, y, width);
|
||||
// Change attribute field so clicking allows user to edit/delete the field
|
||||
this.fields.forEach(field =>
|
||||
field.onLabelClick = this.editAttributeMeta.bind(this, field.name));
|
||||
|
||||
// Add the 'create new attribute' field
|
||||
y += this.ROW_HEIGHT + (y === initialY ? 0 : 10);
|
||||
field = new CreateAttributeField(this.logger, this.$attributes, y, width);
|
||||
field.onClick = this.newAttribute.bind(this);
|
||||
this.fields.push(field);
|
||||
return y;
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.newAttribute = function() {
|
||||
var defSchema = {
|
||||
type: 'string'
|
||||
};
|
||||
|
||||
this.editAttributeMeta(null, defSchema);
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.expand = function() {
|
||||
DecoratorBase.prototype.expand.call(this, this.isOperation());
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.editAttributeMeta = function(name, defSchema) {
|
||||
var dialog = new AttributeDetailsDialog(),
|
||||
attrNames = Object.keys(this._node.attributes),
|
||||
attrInfo = this._node.attributes[name] || defSchema,
|
||||
schema,
|
||||
i;
|
||||
|
||||
// Open the dialog for editing the attribute
|
||||
schema = _.extend({defaultValue: attrInfo.value}, attrInfo);
|
||||
|
||||
// Remove the current name
|
||||
i = attrNames.indexOf(name);
|
||||
if (i !== -1) {
|
||||
attrNames.splice(i, 1);
|
||||
}
|
||||
|
||||
dialog.show(schema, attrNames,
|
||||
desc => this.setAttributeMeta(name, desc),
|
||||
() => this.deleteAttribute(name));
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.deleteAttribute = function(name) {
|
||||
var opName = this._node.attributes.name.value,
|
||||
msg = `Deleting "${name}" attribute from "${opName}" operation`;
|
||||
|
||||
this.client.startTransaction(msg);
|
||||
this.client.removeAttributeSchema(this._node.id, name);
|
||||
this.client.delAttributes(this._node.id, name);
|
||||
this.client.completeTransaction();
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.setAttributeMeta = function(name, desc) {
|
||||
var schema,
|
||||
opName = this._node.attributes.name.value,
|
||||
msg = `Updating "${name}" attribute in "${opName}" operation`;
|
||||
|
||||
// Create the schema from the desc
|
||||
schema = {
|
||||
type: desc.type,
|
||||
min: desc.min,
|
||||
max: desc.max,
|
||||
regexp: desc.regexp
|
||||
};
|
||||
|
||||
if (desc.isEnum) {
|
||||
schema.enum = desc.enumValues;
|
||||
}
|
||||
|
||||
// Update the operation's attribute
|
||||
this.client.startTransaction(msg);
|
||||
|
||||
if (name !== desc.name) { // Renaming attribute
|
||||
if (name) {
|
||||
this.client.removeAttributeSchema(this._node.id, name);
|
||||
this.client.delAttributes(this._node.id, name);
|
||||
}
|
||||
name = desc.name;
|
||||
}
|
||||
|
||||
this.client.setAttributeSchema(this._node.id, name, schema);
|
||||
this.client.setAttributes(this._node.id, name, desc.defaultValue);
|
||||
this.client.completeTransaction();
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.editName = function() {
|
||||
var html = this.$name[0][0],
|
||||
position = html.getBoundingClientRect(),
|
||||
@@ -90,8 +188,5 @@ define([
|
||||
return this._node.name;
|
||||
};
|
||||
|
||||
// clicking on the name should allow the user to edit it in place
|
||||
// TODO
|
||||
|
||||
return OpIntDecorator;
|
||||
});
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/*globals define, _, Opentip*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'css!./OperationDecorator.EasyDAGWidget.css'
|
||||
@@ -47,29 +43,22 @@ define([
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.condense = function() {
|
||||
var path,
|
||||
width,
|
||||
rx;
|
||||
|
||||
width = Math.max(this.nameWidth + 2 * NAME_MARGIN, this.dense.width);
|
||||
rx = width/2;
|
||||
|
||||
path = [
|
||||
`M${-rx},0`,
|
||||
`l ${width} 0`,
|
||||
`l 0 ${this.dense.height}`,
|
||||
`l -${width} 0`,
|
||||
`l 0 -${this.dense.height}`
|
||||
].join(' ');
|
||||
|
||||
var width = Math.max(this.nameWidth + 2 * NAME_MARGIN, this.dense.width);
|
||||
|
||||
this.$body
|
||||
.attr('d', path);
|
||||
.transition()
|
||||
.attr('x', -width/2)
|
||||
.attr('y', 0)
|
||||
.attr('width', width)
|
||||
.attr('height', this.dense.height);
|
||||
|
||||
// Clear the attributes
|
||||
this.$attributes.remove();
|
||||
this.clearFields();
|
||||
this.$attributes = this.$el.append('g')
|
||||
.attr('fill', '#222222');
|
||||
.attr('fill', 'none');
|
||||
|
||||
this.createAttributeFields(0, width);
|
||||
this.createPointerFields(0, width, true);
|
||||
|
||||
this.height = this.dense.height;
|
||||
this.width = width;
|
||||
|
||||
@@ -118,7 +118,7 @@ define([
|
||||
this.core.addMember(this.activeNode, 'executions', tgtNode);
|
||||
|
||||
return this.project.createTag(
|
||||
execName.replace(/ /g, '_'),
|
||||
execName.replace(/[ -]/g, '_'),
|
||||
this.currentHash
|
||||
);
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "CreateExecution",
|
||||
"name": "CreateExecution",
|
||||
"name": "Create Execution",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
|
||||
@@ -86,8 +86,7 @@ define([
|
||||
layers;
|
||||
|
||||
try {
|
||||
layers = JSON.parse(text)
|
||||
.filter(layer => layer.type !== 'Criterion');
|
||||
layers = JSON.parse(text);
|
||||
} catch (e) {
|
||||
return callback('JSON parse error: ' + e, this.result);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
define([
|
||||
'plugin/CreateExecution/CreateExecution/CreateExecution',
|
||||
'deepforge/plugin/PtrCodeGen',
|
||||
'common/storage/constants',
|
||||
'common/core/constants',
|
||||
'q',
|
||||
'text!./metadata.json',
|
||||
@@ -14,6 +15,7 @@ define([
|
||||
], function (
|
||||
CreateExecution,
|
||||
PtrCodeGen,
|
||||
STORAGE_CONSTANTS,
|
||||
CONSTANTS,
|
||||
Q,
|
||||
pluginMetadata,
|
||||
@@ -103,10 +105,9 @@ define([
|
||||
startPromise = this.createExecution(this.activeNode)
|
||||
.then(execNode => {
|
||||
this.activeNode = execNode;
|
||||
return this.core.loadSubTree(this.activeNode);
|
||||
});
|
||||
} else if (this.core.isTypeOf(this.activeNode, this.META.Execution)) {
|
||||
startPromise = this.core.loadSubTree(this.activeNode);
|
||||
startPromise = Q();
|
||||
} else {
|
||||
return callback('Current node is not a Pipeline or Execution!', this.result);
|
||||
}
|
||||
@@ -115,7 +116,9 @@ define([
|
||||
this.debug = true; // this.getCurrentConfig().debug;
|
||||
this._callback = callback;
|
||||
|
||||
startPromise.then(subtree => {
|
||||
startPromise
|
||||
.then(() => this.core.loadSubTree(this.activeNode))
|
||||
.then(subtree => {
|
||||
var children = subtree
|
||||
.filter(n => this.core.getParent(n) === this.activeNode);
|
||||
|
||||
@@ -129,12 +132,36 @@ define([
|
||||
.fail(e => this.logger.error(e));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.updateForkName = function () {
|
||||
var basename = this.pipelineName + '_fork';
|
||||
return this.project.getBranches().then(branches => {
|
||||
var names = Object.keys(branches),
|
||||
name = basename,
|
||||
i = 2;
|
||||
|
||||
while (names.indexOf(name) !== -1) {
|
||||
name = basename + '_' + i;
|
||||
i++;
|
||||
}
|
||||
|
||||
this.forkName = name;
|
||||
});
|
||||
};
|
||||
|
||||
// Override 'save' to prevent race conditions while saving
|
||||
ExecutePipeline.prototype.save = function (msg) {
|
||||
// When 'save' is called, it should still finish any current save op
|
||||
// before continuing
|
||||
this._currentSave = this._currentSave
|
||||
.then(() => CreateExecution.prototype.save.call(this, msg));
|
||||
.then(() => this.updateForkName())
|
||||
.then(() => CreateExecution.prototype.save.call(this, msg))
|
||||
.then(result => {
|
||||
var msg;
|
||||
if (result.status === STORAGE_CONSTANTS.FORKED) {
|
||||
msg = `"${this.pipelineName}" execution has forked to "${result.forkName}"`;
|
||||
this.sendNotification(msg);
|
||||
}
|
||||
});
|
||||
|
||||
return this._currentSave;
|
||||
};
|
||||
@@ -557,10 +584,13 @@ define([
|
||||
// Create new metadata for each
|
||||
artifacts.forEach((artifact, i) => {
|
||||
var name = outputs[i][0],
|
||||
hash = artifact.descriptor.content[`outputs/${name}`].content;
|
||||
outputData = artifact.descriptor.content[`outputs/${name}`],
|
||||
hash = outputData && outputData.content;
|
||||
|
||||
this.core.setAttribute(outputMap[name], 'data', hash);
|
||||
this.logger.info(`Setting ${nodeId} data to ${hash}`);
|
||||
if (hash) {
|
||||
this.core.setAttribute(outputMap[name], 'data', hash);
|
||||
this.logger.info(`Setting ${nodeId} data to ${hash}`);
|
||||
}
|
||||
});
|
||||
|
||||
return this.onOperationComplete(node);
|
||||
@@ -743,10 +773,20 @@ define([
|
||||
tplContents = inputs.map(pair => {
|
||||
var name = pair[0],
|
||||
node = pair[2],
|
||||
deserFn = this.core.getAttribute(node, 'deserialize'),
|
||||
nodeId = this.core.getPath(node),
|
||||
fromNodeId,
|
||||
fromNode,
|
||||
deserFn,
|
||||
base,
|
||||
className;
|
||||
|
||||
// Get the deserialize function. First, try to get it from
|
||||
// the source method (this guarantees that the correct
|
||||
// deserialize method is used despite any auto-upcasting
|
||||
fromNodeId = this.inputPortsFor[nodeId][0] || nodeId;
|
||||
fromNode = this.nodes[fromNodeId];
|
||||
deserFn = this.core.getAttribute(fromNode, 'deserialize');
|
||||
|
||||
if (this.isMetaTypeOf(node, this.META.Complex)) {
|
||||
// Complex objects are expected to define their own
|
||||
// (static) deserialize factory method
|
||||
@@ -821,7 +861,7 @@ define([
|
||||
if (this.isMetaTypeOf(node, this.META.Complex)) {
|
||||
// Complex objects are expected to define their own
|
||||
// serialize methods
|
||||
serFn = 'data:serialize(path)';
|
||||
serFn = 'if data ~= nil then data:serialize(path) end';
|
||||
}
|
||||
|
||||
return [tuple[1], serFn];
|
||||
@@ -864,11 +904,6 @@ define([
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
content = {};
|
||||
|
||||
// sort the outputs by the return values?
|
||||
if (outputs.length > 1) {
|
||||
this.logger.error('Multiple outputs not yet supported!');
|
||||
}
|
||||
|
||||
// inputs and outputs
|
||||
content.name = name;
|
||||
content.outputs = outputs;
|
||||
@@ -904,13 +939,20 @@ define([
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createAttributeFile = function (node, files) {
|
||||
var skip = ['outputs', 'inputs'],
|
||||
var skip = ['code'],
|
||||
numRegex = /^\d+\.?\d*((e|e-)\d+)?$/,
|
||||
table;
|
||||
|
||||
this.logger.info('Creating attributes file...');
|
||||
table = '{\n\t' + this.core.getAttributeNames(node)
|
||||
.filter(attr => skip.indexOf(attr) === -1)
|
||||
.map(name => [name, JSON.stringify(this.core.getAttribute(node, name))])
|
||||
.map(name => {
|
||||
var value = this.core.getAttribute(node, name);
|
||||
if (!numRegex.test(value)) {
|
||||
value = `"${value}"`;
|
||||
}
|
||||
return [name, value];
|
||||
})
|
||||
.map(pair => pair.join(' = '))
|
||||
.join(',\n\t') + '\n}';
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"id": "ExecutePipeline",
|
||||
"name": "ExecutePipeline",
|
||||
"name": "Execute Pipeline",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"class": "glyphicon glyphicon-random",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- run the <%= name %> and serialize the results
|
||||
print('\n############### Running "<%= name %>" Operation ############### ')
|
||||
print('\n############### Running "<%= name.replace(/'/g, '\\\'') %>" Operation ############### ')
|
||||
results = require './main'
|
||||
print('############### "<%= name %>" Operation Complete! ###############')
|
||||
print('############### "<%= name.replace(/'/g, '\\\'') %>" Operation Complete! ###############')
|
||||
|
||||
-- serialize by type
|
||||
outputs = require './outputs'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"id": "GenerateArchitecture",
|
||||
"name": "Generate Architecture",
|
||||
"name": "Generate Torch Code",
|
||||
"version": "0.1.0",
|
||||
"description": "Generate torch architecture code",
|
||||
"icon": {
|
||||
"src": "",
|
||||
"class": "glyphicon glyphicon-ok-circle"
|
||||
"class": "glyphicon glyphicon-file"
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": false,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
define([
|
||||
'text!./metadata.json',
|
||||
'plugin/PluginBase'
|
||||
], function (
|
||||
pluginMetadata,
|
||||
PluginBase
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of GenerateCriterion.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin GenerateCriterion.
|
||||
* @constructor
|
||||
*/
|
||||
var GenerateCriterion = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
|
||||
* This is also available at the instance at this.pluginMetadata.
|
||||
* @type {object}
|
||||
*/
|
||||
GenerateCriterion.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
GenerateCriterion.prototype = Object.create(PluginBase.prototype);
|
||||
GenerateCriterion.prototype.constructor = GenerateCriterion;
|
||||
|
||||
/**
|
||||
* Main function for the plugin to execute. This will perform the execution.
|
||||
* Notes:
|
||||
* - Always log with the provided logger.[error,warning,info,debug].
|
||||
* - Do NOT put any user interaction logic UI, etc. inside this method.
|
||||
* - callback always has to be called even if error happened.
|
||||
*
|
||||
* @param {function(string, plugin.PluginResult)} callback - the result callback
|
||||
*/
|
||||
GenerateCriterion.prototype.main = function (callback) {
|
||||
// Generate the code for the criterion layer and return a file
|
||||
var name = this.core.getAttribute(this.activeNode, 'name'),
|
||||
code = `require 'nn'\nreturn nn.${name}()`,
|
||||
filename = `${name}.lua`;
|
||||
|
||||
// Using the logger.
|
||||
this.logger.debug(`Generating code for ${name} criterion layer.`);
|
||||
|
||||
// Save the file
|
||||
this.blobClient.putFile(filename, code)
|
||||
.then(hash => {
|
||||
this.result.setSuccess(true);
|
||||
this.result.addArtifact(hash);
|
||||
callback(null, this.result);
|
||||
})
|
||||
.catch(err => callback(err, this.result));
|
||||
|
||||
};
|
||||
|
||||
return GenerateCriterion;
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "GenerateCriterion",
|
||||
"name": "Generate Criterion Code",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": false,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": []
|
||||
}
|
||||
@@ -78,29 +78,32 @@ define([
|
||||
}
|
||||
|
||||
// Get the base node
|
||||
dataNode = this.core.createNode({
|
||||
base: baseType,
|
||||
parent: this.activeNode
|
||||
});
|
||||
|
||||
this.core.setAttribute(dataNode, 'data', hash);
|
||||
baseName = this.core.getAttribute(baseType, 'name');
|
||||
|
||||
var getName;
|
||||
if (config.name) {
|
||||
getName = Q().then(() => config.name);
|
||||
} else {
|
||||
getName = this.blobClient.getMetadata(hash)
|
||||
.then(md => {
|
||||
name = baseName[0].toLowerCase() + baseName.substring(1);
|
||||
if (md) {
|
||||
name = md.name.replace(/\.[^\.]*?$/, '');
|
||||
}
|
||||
return name;
|
||||
this.getArtifactsDir()
|
||||
.then(targetDir => {
|
||||
dataNode = this.core.createNode({
|
||||
base: baseType,
|
||||
parent: targetDir
|
||||
});
|
||||
}
|
||||
|
||||
getName.then(name => this.core.setAttribute(dataNode, 'name', name))
|
||||
this.core.setAttribute(dataNode, 'data', hash);
|
||||
baseName = this.core.getAttribute(baseType, 'name');
|
||||
|
||||
var getName;
|
||||
if (config.name) {
|
||||
getName = Q().then(() => config.name);
|
||||
} else {
|
||||
getName = this.blobClient.getMetadata(hash)
|
||||
.then(md => {
|
||||
name = baseName[0].toLowerCase() + baseName.substring(1);
|
||||
if (md) {
|
||||
name = md.name.replace(/\.[^\.]*?$/, '');
|
||||
}
|
||||
return name;
|
||||
});
|
||||
}
|
||||
return getName;
|
||||
})
|
||||
.then(name => this.core.setAttribute(dataNode, 'name', name))
|
||||
.then(() => this.save(`Uploaded "${name}" data`))
|
||||
.then(function () {
|
||||
self.result.setSuccess(true);
|
||||
@@ -112,5 +115,14 @@ define([
|
||||
|
||||
};
|
||||
|
||||
ImportArtifact.prototype.getArtifactsDir = function() {
|
||||
// Find the artifacts dir
|
||||
return this.core.loadChildren(this.rootNode)
|
||||
.then(children => children
|
||||
.find(child => this.core.getAttribute(child, 'name') === 'MyArtifacts') ||
|
||||
this.activeNode
|
||||
);
|
||||
};
|
||||
|
||||
return ImportArtifact;
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"id": "ImportArtifact",
|
||||
"name": "ImportArtifact",
|
||||
"name": "Import Artifact",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"class": "glyphicon glyphicon-cloud-upload",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
|
||||
@@ -57,12 +57,17 @@ define([
|
||||
|
||||
this.blobClient.getMetadata(srcHash)
|
||||
.then(mdata => { // Create the new model
|
||||
var name = mdata.name.replace('.lua', '');
|
||||
this.tgtNode = this.core.createNode({
|
||||
base: this.META.Architecture,
|
||||
parent: this.activeNode
|
||||
});
|
||||
this.core.setAttribute(this.tgtNode, 'name', name);
|
||||
// If the current node is an architecture, assume we are just extending it
|
||||
this.importedName = mdata.name.replace('.lua', '');
|
||||
if (this.isMetaTypeOf(this.activeNode, this.META.Architecture)) {
|
||||
this.tgtNode = this.activeNode;
|
||||
} else { // Create a new architecture
|
||||
this.tgtNode = this.core.createNode({
|
||||
base: this.META.Architecture,
|
||||
parent: this.activeNode
|
||||
});
|
||||
this.core.setAttribute(this.tgtNode, 'name', this.importedName);
|
||||
}
|
||||
return this.blobClient.getObjectAsString(srcHash);
|
||||
})
|
||||
.then(src => { // Retrieved the source code
|
||||
@@ -81,7 +86,7 @@ define([
|
||||
return this.save('ImportTorch updated model.');
|
||||
})
|
||||
.then(() => { // changes saved successfully
|
||||
var name = this.core.getAttribute(this.tgtNode, 'name');
|
||||
var name = this.importedName;
|
||||
this.result.setSuccess(true);
|
||||
this.createMessage(this.tgtNode,
|
||||
`Successfully imported ${name} architecture`);
|
||||
@@ -96,7 +101,7 @@ define([
|
||||
ImportTorch.prototype.loadNNMock = function () {
|
||||
// This needs a refactor...
|
||||
// createNN(this)
|
||||
var lib = createNNSearcher(this).bind(this.context);
|
||||
var lib = createNNSearcher(this, this.context).bind(this.context);
|
||||
|
||||
// Create a "searcher" to allow this 'nn' to be in the lib path
|
||||
this.context._G.get('package').set('searchers', [function(name) {
|
||||
|
||||
@@ -11,12 +11,23 @@ define([
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var createSearcher = function(plugin) {
|
||||
var createSearcher = function(plugin, context) {
|
||||
var core = plugin.core,
|
||||
META = plugin.META,
|
||||
logger = plugin.logger.fork('nn'),
|
||||
parent = plugin.tgtNode,
|
||||
LayerDict = createLayerDict(core, META);
|
||||
LayerDict = createLayerDict(core, META),
|
||||
helpers = context.__helpers,
|
||||
oldSet = helpers.__set,
|
||||
isSetting = false;
|
||||
|
||||
// Override the helper's '__set' method to detect
|
||||
// if the code is in the middle of a "set".
|
||||
helpers.__set = function() {
|
||||
isSetting = true;
|
||||
oldSet.apply(this, arguments);
|
||||
isSetting = false;
|
||||
};
|
||||
|
||||
var connect = function(src, dst) {
|
||||
var conn = core.createNode({
|
||||
@@ -145,6 +156,7 @@ define([
|
||||
var CreateLayer = function(type) {
|
||||
var res = luajs.newContext()._G,
|
||||
attrs = [].slice.call(arguments, 1),
|
||||
ltGet = luajs.types.LuaTable.prototype.get,
|
||||
node;
|
||||
|
||||
if (LAYERS[type]) {
|
||||
@@ -165,6 +177,16 @@ define([
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override get
|
||||
res.get = function noNilGet(value) {
|
||||
var result = ltGet.call(this, value);
|
||||
if (!result && !isSetting) {
|
||||
throw Error(`"${value}" is not supported for ${type}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -31,26 +31,8 @@
|
||||
},
|
||||
{
|
||||
"id": "RootViz",
|
||||
"title": "RootViz",
|
||||
"panel": "panels/RootViz/RootVizPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "TilingViz",
|
||||
"title": "TilingViz",
|
||||
"panel": "panels/TilingViz/TilingVizPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "OperationCodeEditor",
|
||||
"title": "OperationCodeEditor",
|
||||
"panel": "panels/OperationCodeEditor/OperationCodeEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "OperationInterfaceEditor",
|
||||
"title": "OperationInterfaceEditor",
|
||||
"panel": "panels/OperationInterfaceEditor/OperationInterfaceEditorPanel",
|
||||
"title": "MainView",
|
||||
"panel": "panels/MainView/MainViewPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
@@ -59,24 +41,6 @@
|
||||
"panel": "panels/DataTypeEditor/DataTypeEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "SerializeEditor",
|
||||
"title": "SerializeEditor",
|
||||
"panel": "panels/SerializeEditor/SerializeEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "DeserializeEditor",
|
||||
"title": "DeserializeEditor",
|
||||
"panel": "panels/DeserializeEditor/DeserializeEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "Footer",
|
||||
"title": "Footer",
|
||||
"panel": "panels/Footer/FooterPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "LogViewer",
|
||||
"title": "LogViewer",
|
||||
@@ -100,5 +64,11 @@
|
||||
"title": "ClassEditor",
|
||||
"panel": "panels/ClassEditor/ClassEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "PipelineIndex",
|
||||
"title": "PipelineIndex",
|
||||
"panel": "panels/PipelineIndex/PipelineIndexPanel",
|
||||
"DEBUG_ONLY": false
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 17 2016 11:25:46 GMT-0400 (EDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'deepforge/globals',
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'js/NodePropertyNames',
|
||||
'js/Utils/ComponentSettings',
|
||||
'underscore'
|
||||
], function (
|
||||
DeepForge,
|
||||
EasyDAGControl,
|
||||
nodePropertyNames,
|
||||
ComponentSettings,
|
||||
@@ -43,6 +42,16 @@ define([
|
||||
return 'ArchEditor';
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype.selectedObjectChanged = function(id) {
|
||||
EasyDAGControl.prototype.selectedObjectChanged.call(this, id);
|
||||
|
||||
DeepForge.last.Architecture = id;
|
||||
if (typeof id === 'string') {
|
||||
var name = this._client.getNode(id).getAttribute('name');
|
||||
this._widget.setTitle(name);
|
||||
}
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._getObjectDescriptor = function(id) {
|
||||
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id);
|
||||
|
||||
@@ -84,6 +93,7 @@ define([
|
||||
return desc;
|
||||
};
|
||||
|
||||
////////////////////////// Layer Selection Logic //////////////////////////
|
||||
ArchEditorControl.prototype._getValidInitialNodes = function() {
|
||||
return this._client.getChildrenMeta(this._currentNodeId).items
|
||||
// For now, anything is possible!
|
||||
@@ -95,7 +105,67 @@ define([
|
||||
return !this._client.getNode(nodeId).isAbstract();
|
||||
})
|
||||
.map(id => this._getObjectDescriptor(id))
|
||||
.filter(obj => !obj.isConnection && obj.name !== 'Connection');
|
||||
.filter(obj => !obj.isConnection && obj.name !== 'Connection')
|
||||
.filter(layer => layer.layerType !== 'Criterion');
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._getValidSuccessorNodes =
|
||||
ArchEditorControl.prototype._getValidInitialNodes =
|
||||
ArchEditorControl.prototype.getNonCriterionLayers = function() {
|
||||
// Return all (non-criterion) layer types
|
||||
var metanodes = this._client.getAllMetaNodes(),
|
||||
layerId,
|
||||
criterionId,
|
||||
allLayerIds = [],
|
||||
layers = [],
|
||||
i;
|
||||
|
||||
for (i = metanodes.length; i--;) {
|
||||
if (metanodes[i].getAttribute('name') === 'Layer') {
|
||||
layerId = metanodes[i].getId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = metanodes.length; i--;) {
|
||||
if (layerId) {
|
||||
if (!metanodes[i].isAbstract() &&
|
||||
this._client.isTypeOf(metanodes[i].getId(), layerId)) {
|
||||
|
||||
if (metanodes[i].getAttribute('name') === 'Criterion') {
|
||||
criterionId = metanodes[i].getId();
|
||||
} else {
|
||||
allLayerIds.push(metanodes[i].getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all criterion layers and abstract layers
|
||||
for (i = allLayerIds.length; i--;) {
|
||||
if (!this._client.isTypeOf(allLayerIds[i], criterionId)) {
|
||||
layers.push({node: this._getObjectDescriptor(allLayerIds[i])});
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._isValidTerminalNode = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Widget extensions
|
||||
ArchEditorControl.prototype._initWidgetEventHandlers = function() {
|
||||
EasyDAGControl.prototype._initWidgetEventHandlers.call(this);
|
||||
this._widget.getCreateNewDecorator = this.getCreateNewDecorator.bind(this);
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype.getCreateNewDecorator = function() {
|
||||
return this._client.decoratorManager.getDecoratorForWidget(
|
||||
'EllipseDecorator',
|
||||
'EasyDAG'
|
||||
);
|
||||
};
|
||||
|
||||
return ArchEditorControl;
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'deepforge/viz/RenameablePanel',
|
||||
'widgets/ArchEditor/ArchEditorWidget',
|
||||
'./ArchEditorControl'
|
||||
], function (
|
||||
PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
RenameablePanel,
|
||||
ArchEditorWidget,
|
||||
ArchEditorControl
|
||||
) {
|
||||
@@ -22,11 +20,11 @@ define([
|
||||
ArchEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'ArchEditorPanel';
|
||||
options[PanelBaseWithHeader.OPTIONS.FLOATING_TITLE] = true;
|
||||
options[RenameablePanel.OPTIONS.LOGGER_INSTANCE_NAME] = 'ArchEditorPanel';
|
||||
options[RenameablePanel.OPTIONS.FLOATING_TITLE] = true;
|
||||
|
||||
//call parent's constructor
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
RenameablePanel.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
@@ -37,9 +35,7 @@ define([
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(ArchEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(ArchEditorPanel.prototype, IActivePanel.prototype);
|
||||
_.extend(ArchEditorPanel.prototype, RenameablePanel.prototype);
|
||||
|
||||
ArchEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
@@ -60,6 +56,7 @@ define([
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
this.initializeRenameable();
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
@@ -67,7 +64,7 @@ define([
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
ArchEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
RenameablePanel.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
@@ -81,7 +78,7 @@ define([
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
RenameablePanel.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ define([
|
||||
// input/output updates are actually activeNode updates
|
||||
ClassCodeEditorControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, this._currentNodeId);
|
||||
TextEditorControl.prototype._onUpdate.call(this, id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/SerializeEditor/SerializeEditorControl',
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'underscore'
|
||||
], function (
|
||||
SerializeEditorControl,
|
||||
TextEditorControl,
|
||||
_
|
||||
) {
|
||||
@@ -20,15 +22,8 @@ define([
|
||||
|
||||
_.extend(
|
||||
DeserializeEditorControl.prototype,
|
||||
TextEditorControl.prototype
|
||||
SerializeEditorControl.prototype
|
||||
);
|
||||
|
||||
// input/output updates are actually activeNode updates
|
||||
DeserializeEditorControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, this._currentNodeId);
|
||||
}
|
||||
};
|
||||
|
||||
return DeserializeEditorControl;
|
||||
});
|
||||
|
||||
@@ -68,58 +68,6 @@ define([
|
||||
return null;
|
||||
};
|
||||
|
||||
var UPLOAD_PLUGIN = 'ImportArtifact',
|
||||
DATA_TYPE_CONFIG = {
|
||||
name: 'dataTypeId',
|
||||
displayName: 'Data Type Id',
|
||||
valueType: 'string',
|
||||
valueItems: []
|
||||
};
|
||||
var uploadArtifact = function() {
|
||||
// Get the data types
|
||||
var dataBase,
|
||||
dataBaseId,
|
||||
metanodes = this.client.getAllMetaNodes(),
|
||||
dataTypes = []; // TODO
|
||||
|
||||
dataBase = metanodes.find(n => n.getAttribute('name') === 'Data');
|
||||
|
||||
if (!dataBase) {
|
||||
this.logger.error('Could not find the base Data node!');
|
||||
return;
|
||||
}
|
||||
|
||||
dataBaseId = dataBase.getId();
|
||||
dataTypes = metanodes.filter(n => this.client.isTypeOf(n.getId(), dataBaseId))
|
||||
.map(node => node.getAttribute('name'));
|
||||
|
||||
this.logger.info(`Found ${dataTypes.length} data types`);
|
||||
|
||||
// Add the target type to the pluginMetadata... hacky :/
|
||||
// FIXME: this should create it's own plugin dialog which allows
|
||||
// users to select the data type
|
||||
var metadata = WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN],
|
||||
config = metadata.configStructure
|
||||
.find(opt => opt.name === DATA_TYPE_CONFIG.name);
|
||||
|
||||
if (!config) {
|
||||
config = DATA_TYPE_CONFIG;
|
||||
WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN].configStructure.push(config);
|
||||
}
|
||||
|
||||
config.valueItems = dataTypes;
|
||||
config.value = dataTypes[0];
|
||||
|
||||
WebGMEGlobal.InterpreterManager.configureAndRun(metadata, (result) => {
|
||||
if (!result) {
|
||||
Materialize.toast('Artifact upload failed!', 2000);
|
||||
return;
|
||||
}
|
||||
this.logger.info('Finished uploading ' + UPLOAD_PLUGIN);
|
||||
Materialize.toast('Artifact upload complete!', 2000);
|
||||
});
|
||||
};
|
||||
|
||||
var importTorch = function() {
|
||||
var pluginId = 'ImportTorch',
|
||||
context = this.client.getCurrentPluginContext(pluginId),
|
||||
@@ -144,20 +92,51 @@ define([
|
||||
fileInput.click();
|
||||
};
|
||||
|
||||
var returnToLastPipeline = () => {
|
||||
var returnId = DeepForge.lastPipeline || DeepForge.places.MyPipelines;
|
||||
var returnToLast = (place) => {
|
||||
var returnId = DeepForge.last[place];
|
||||
WebGMEGlobal.State.registerActiveObject(returnId);
|
||||
};
|
||||
|
||||
return {
|
||||
// Meta nodes
|
||||
MyPipelines_META: [
|
||||
var prototypeButtons = function(type, fromType) {
|
||||
return [
|
||||
{
|
||||
name: 'Create new pipeline',
|
||||
icon: 'queue',
|
||||
action: DeepForge.create.Pipeline
|
||||
name: `Return to ${fromType}`,
|
||||
icon: 'input',
|
||||
priority: 2,
|
||||
filter: () => {
|
||||
return DeepForge.last[fromType];
|
||||
},
|
||||
action: returnToLast.bind(null, fromType)
|
||||
},
|
||||
{
|
||||
name: `Delete ${type} Definition`,
|
||||
icon: 'delete',
|
||||
priority: 1,
|
||||
action: function() {
|
||||
// Delete and go to the last pipeline?
|
||||
var node = this.client.getNode(this._currentNodeId),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Deleted ${type} Definition for "${name}"`;
|
||||
|
||||
this.deleteCurrentNode(msg);
|
||||
setTimeout(() => Materialize.toast(msg, 2000), 10);
|
||||
returnToLast(fromType);
|
||||
}
|
||||
}
|
||||
],
|
||||
];
|
||||
};
|
||||
|
||||
var MyPipelinesButtons = [
|
||||
{
|
||||
name: 'Create new pipeline',
|
||||
icon: 'queue',
|
||||
action: DeepForge.create.Pipeline
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
HOME: MyPipelinesButtons,
|
||||
MyPipelines_META: MyPipelinesButtons,
|
||||
MyArchitectures_META: [
|
||||
{
|
||||
name: 'Create new architecture',
|
||||
@@ -200,17 +179,16 @@ define([
|
||||
{
|
||||
name: 'Upload artifact',
|
||||
icon: 'swap_vert',
|
||||
action: uploadArtifact
|
||||
}
|
||||
],
|
||||
Operation_META: [
|
||||
{
|
||||
name: 'Return to Pipeline',
|
||||
icon: 'input',
|
||||
action: returnToLastPipeline
|
||||
action: DeepForge.create.Artifact
|
||||
}
|
||||
],
|
||||
|
||||
// Creating prototypes
|
||||
Operation_META: prototypeButtons('Operation', 'Pipeline'),
|
||||
Layer_META: prototypeButtons('Layer', 'Architecture'),
|
||||
Complex_META: prototypeButtons('Class', 'Operation'),
|
||||
Primitive_META: prototypeButtons('Primitive Type', 'Operation'),
|
||||
|
||||
// Instances
|
||||
Data: [
|
||||
{
|
||||
@@ -234,14 +212,13 @@ define([
|
||||
action: function() {
|
||||
this.addOperation();
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
Architecture: [
|
||||
{
|
||||
name: 'Create new node',
|
||||
icon: 'queue',
|
||||
priority: 2,
|
||||
action: function() {
|
||||
this.addOperation();
|
||||
}
|
||||
name: 'Import Torch Architecture',
|
||||
icon: 'swap_vert',
|
||||
action: importTorch
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@ define([
|
||||
'panel/FloatingActionButton/FloatingActionButton',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'deepforge/viz/NodePrompter',
|
||||
'deepforge/viz/AddDecorator',
|
||||
'./Actions',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'js/RegistryKeys',
|
||||
@@ -21,7 +20,6 @@ define([
|
||||
PluginButton,
|
||||
PipelineControl,
|
||||
NodePrompter,
|
||||
AddDecorator,
|
||||
ACTIONS,
|
||||
AddNodeDialog,
|
||||
REGISTRY_KEYS,
|
||||
@@ -59,6 +57,13 @@ define([
|
||||
actions,
|
||||
basename;
|
||||
|
||||
if (!base) { // must be ROOT or FCO
|
||||
basename = node.getAttribute('name') || 'ROOT_NODE';
|
||||
actions = (ACTIONS[basename] || [])
|
||||
.filter(action => !action.filter || action.filter());
|
||||
return actions;
|
||||
}
|
||||
|
||||
while (base && !(actions && actions.length)) {
|
||||
basename = base.getAttribute('name') + suffix;
|
||||
base = this.client.getNode(base.getBaseId());
|
||||
@@ -183,8 +188,7 @@ define([
|
||||
|
||||
ForgeActionButton.prototype.promptLayerType = function() {
|
||||
// Prompt for the new custom layer's base type
|
||||
var deferred = Q.defer(),
|
||||
metanodes = this.client.getAllMetaNodes(),
|
||||
var metanodes = this.client.getAllMetaNodes(),
|
||||
baseLayerId = metanodes.find(n => n.getAttribute('name') === 'Layer').getId(),
|
||||
layerType,
|
||||
types;
|
||||
@@ -206,8 +210,7 @@ define([
|
||||
};
|
||||
});
|
||||
|
||||
AddNodeDialog.prompt(types, deferred.resolve);
|
||||
return deferred.promise;
|
||||
return AddNodeDialog.prompt(types);
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.uploadFile = function(event) {
|
||||
@@ -249,10 +252,7 @@ define([
|
||||
/////////////// Expanding containers ///////////////
|
||||
ForgeActionButton.prototype.addOperation = function() {
|
||||
var ops = this.getValidInitialNodes(),
|
||||
newOperation = {
|
||||
id: NEW_OPERATION_ID,
|
||||
Decorator: AddDecorator
|
||||
};
|
||||
newOperation = this.getNewOpNode();
|
||||
|
||||
// Add the 'New op button'
|
||||
ops.push(newOperation);
|
||||
@@ -260,15 +260,26 @@ define([
|
||||
this.promptNode(ops, (selected, prompter) => {
|
||||
if (selected.id === NEW_OPERATION_ID) {
|
||||
prompter.destroy();
|
||||
DeepForge.lastPipeline = this._currentNodeId;
|
||||
DeepForge.create.Operation();
|
||||
//WebGMEGlobal.State.registerActiveObject(newId);
|
||||
} else {
|
||||
this.createNode(selected.id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.getNewOpNode = function() {
|
||||
var Decorator = this.client.decoratorManager.getDecoratorForWidget(
|
||||
'OperationDecorator', 'EasyDAG');
|
||||
|
||||
return {
|
||||
id: NEW_OPERATION_ID,
|
||||
class: 'create-node',
|
||||
name: 'New Operation...',
|
||||
Decorator: Decorator,
|
||||
attributes: {}
|
||||
};
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.promptNode = function(nodes, selectFn) {
|
||||
// Get the absolute location of the given button
|
||||
var mainBtn = this.$el[0].children[0],
|
||||
@@ -301,5 +312,14 @@ define([
|
||||
return prompter.prompt(nodes, selectFn);
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.deleteCurrentNode = function(msg) {
|
||||
var nodeId = this._currentNodeId;
|
||||
if (nodeId) {
|
||||
this.client.startTransaction(msg);
|
||||
this.client.delMoreNodes([nodeId]);
|
||||
this.client.completeTransaction(msg);
|
||||
}
|
||||
};
|
||||
|
||||
return ForgeActionButton;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'blob/BlobClient',
|
||||
'js/Constants',
|
||||
'js/Utils/GMEConcepts',
|
||||
'js/NodePropertyNames',
|
||||
'deepforge/globals'
|
||||
], function (
|
||||
BlobClient,
|
||||
CONSTANTS,
|
||||
GMEConcepts,
|
||||
nodePropertyNames,
|
||||
DeepForge
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var MainViewControl;
|
||||
|
||||
MainViewControl = function (options) {
|
||||
|
||||
this._logger = options.logger.fork('Control');
|
||||
|
||||
this._client = options.client;
|
||||
|
||||
// Initialize core collections and variables
|
||||
this._widget = options.widget;
|
||||
|
||||
this._currentNodeId = null;
|
||||
this._embedded = options.embedded;
|
||||
|
||||
this.territory = {};
|
||||
this.ui = {};
|
||||
this._blobClient = new BlobClient({
|
||||
logger: this._logger.fork('BlobClient')
|
||||
});
|
||||
|
||||
this._initWidgetEventHandlers();
|
||||
this._logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
MainViewControl.prototype._initWidgetEventHandlers = function () {
|
||||
this._widget.deleteNode = id => {
|
||||
var node = this._client.getNode(id),
|
||||
baseId = node.getBaseId(),
|
||||
base = this._client.getNode(baseId),
|
||||
baseName = base.getAttribute('name'),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Deleting ${baseName} "${name}"`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
this._widget.dataUrlFor = id => {
|
||||
var node = this._client.getNode(id),
|
||||
hash = node.getAttribute('data');
|
||||
|
||||
if (hash) {
|
||||
return this._blobClient.getDownloadURL(hash);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer content update callbacks * * * * * * * */
|
||||
// One major concept here is with managing the territory. The territory
|
||||
// defines the parts of the project that the visualizer is interested in
|
||||
// (this allows the browser to then only load those relevant parts).
|
||||
MainViewControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
this._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
// Remove current territory patterns
|
||||
this.clearTerritoryRules();
|
||||
|
||||
this._currentNodeId = nodeId;
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
var terrTypes = [
|
||||
/* [type, root dir] */
|
||||
['arch', 'MyArchitectures'],
|
||||
['artifact', 'MyArtifacts']
|
||||
];
|
||||
|
||||
terrTypes.forEach(pair => {
|
||||
var type = pair[0],
|
||||
dirname = pair[1];
|
||||
|
||||
// Update the territory
|
||||
this.territory[type] = {};
|
||||
this.territory[type][DeepForge.places[dirname]] = {children: 1};
|
||||
this.ui[type] = this._client.addUI(this, this.handleEvents.bind(this, type));
|
||||
this._client.updateTerritory(this.ui[type], this.territory[type]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
MainViewControl.prototype.handleEvents = function (type, events) {
|
||||
var event;
|
||||
|
||||
// Remove the containing dir
|
||||
events = events.filter(e => !this.territory[type][e.eid]);
|
||||
this._logger.debug('_eventCallback \'' + i + '\' items');
|
||||
|
||||
for (var i = events.length; i--;) {
|
||||
event = events[i];
|
||||
switch (event.etype) {
|
||||
|
||||
case CONSTANTS.TERRITORY_EVENT_LOAD:
|
||||
this.onLoad(type, event.eid);
|
||||
break;
|
||||
case CONSTANTS.TERRITORY_EVENT_UPDATE:
|
||||
this._onUpdate(type, event.eid);
|
||||
break;
|
||||
case CONSTANTS.TERRITORY_EVENT_UNLOAD:
|
||||
this._onUnload(event.eid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._logger.debug('_eventCallback \'' + events.length + '\' items - DONE');
|
||||
};
|
||||
|
||||
MainViewControl.prototype.onLoad = function(type, id) {
|
||||
// Load a node of the given type
|
||||
var desc = this._getObjectDescriptor(type, id);
|
||||
if (type === 'arch') {
|
||||
this._widget.addArch(desc);
|
||||
} else { // artifacts
|
||||
this._widget.addArtifact(desc);
|
||||
}
|
||||
};
|
||||
|
||||
// This next function retrieves the relevant node information for the widget
|
||||
MainViewControl.prototype._getArtifactDesc = function (id) {
|
||||
var node = this._client.getNode(id),
|
||||
data = node.getAttribute('data'),
|
||||
desc = this._getBasicDesc(id);
|
||||
|
||||
desc.data = data;
|
||||
return desc;
|
||||
};
|
||||
|
||||
MainViewControl.prototype._getArchDesc =
|
||||
MainViewControl.prototype._getBasicDesc = function (id) {
|
||||
var node = this._client.getNode(id);
|
||||
|
||||
return {
|
||||
id: id,
|
||||
name: node.getAttribute('name')
|
||||
};
|
||||
};
|
||||
|
||||
MainViewControl.prototype._getObjectDescriptor = function (type, id) {
|
||||
return type === 'arch' ?
|
||||
this._getArchDesc(id) :
|
||||
this._getArtifactDesc(id);
|
||||
};
|
||||
|
||||
/* * * * * * * * Node Event Handling * * * * * * * */
|
||||
MainViewControl.prototype._onUpdate = function (type, gmeId) {
|
||||
var description = this._getObjectDescriptor(type, gmeId);
|
||||
this._widget.updateNode(description);
|
||||
};
|
||||
|
||||
MainViewControl.prototype._onUnload = function (gmeId) {
|
||||
this._widget.removeNode(gmeId);
|
||||
};
|
||||
|
||||
MainViewControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
|
||||
if (this._currentNodeId !== activeObjectId) {
|
||||
this.selectedObjectChanged(activeObjectId);
|
||||
}
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
MainViewControl.prototype.destroy = function () {
|
||||
this._detachClientEventListeners();
|
||||
this.clearTerritoryRules();
|
||||
};
|
||||
|
||||
MainViewControl.prototype._attachClientEventListeners = function () {
|
||||
this._detachClientEventListeners();
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
|
||||
this._stateActiveObjectChanged, this);
|
||||
}
|
||||
};
|
||||
|
||||
MainViewControl.prototype._detachClientEventListeners = function () {
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
|
||||
this._stateActiveObjectChanged);
|
||||
}
|
||||
};
|
||||
|
||||
MainViewControl.prototype.onActivate = function () {
|
||||
this._attachClientEventListeners();
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
WebGMEGlobal.State.registerSuppressVisualizerFromNode(true);
|
||||
WebGMEGlobal.State.registerActiveObject(this._currentNodeId);
|
||||
WebGMEGlobal.State.registerSuppressVisualizerFromNode(false);
|
||||
}
|
||||
};
|
||||
|
||||
MainViewControl.prototype.clearTerritoryRules = function () {
|
||||
if (Object.keys(this.ui).length) {
|
||||
Object.keys(this.ui).forEach(id =>
|
||||
this._client.removeUI(this.ui[id]));
|
||||
}
|
||||
};
|
||||
|
||||
MainViewControl.prototype.onDeactivate = function () {
|
||||
this._detachClientEventListeners();
|
||||
};
|
||||
|
||||
return MainViewControl;
|
||||
});
|
||||
@@ -0,0 +1,128 @@
|
||||
/*globals define, $, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
// The main panel shows the PipelineIndex w/ a bar on the left for viewing architectures
|
||||
// and pipelines
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/MainView/MainViewWidget',
|
||||
'./MainViewControl',
|
||||
'panels/PipelineIndex/PipelineIndexPanel',
|
||||
'deepforge/globals'
|
||||
], function (
|
||||
PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
MainViewWidget,
|
||||
MainViewControl,
|
||||
PipelineIndexPanel,
|
||||
DeepForge
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var MainViewPanel;
|
||||
|
||||
MainViewPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'MainViewPanel';
|
||||
options[PanelBaseWithHeader.OPTIONS.FLOATING_TITLE] = true;
|
||||
|
||||
//call parent's constructor
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
|
||||
//initialize UI
|
||||
this.$nav = $('<div>', {id: 'nav-container'});
|
||||
this.$el.css({padding: 0});
|
||||
|
||||
this.embeddedPanel = new PipelineIndexPanel(layoutManager, params);
|
||||
this.$embedded = this.embeddedPanel.$el;
|
||||
this.$embedded.addClass('embedded');
|
||||
|
||||
this.$el.append(this.$nav, this.$embedded);
|
||||
|
||||
this._initialize();
|
||||
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(MainViewPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(MainViewPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
MainViewPanel.prototype._initialize = function () {
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new MainViewWidget(this.logger, this.$nav);
|
||||
|
||||
this.control = new MainViewControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
embedded: this._embedded,
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
var controlObjectChanged = this.control.selectedObjectChanged;
|
||||
this.control.selectedObjectChanged = nodeId => {
|
||||
this.embeddedPanel.control.selectedObjectChanged(DeepForge.places.MyPipelines);
|
||||
return controlObjectChanged.call(this.control, nodeId);
|
||||
};
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
MainViewPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
MainViewPanel.prototype.onResize = function (width, height) {
|
||||
var navWidth,
|
||||
embeddedWidth;
|
||||
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
navWidth = this.widget.width();
|
||||
embeddedWidth = width-navWidth;
|
||||
this.$embedded.css({
|
||||
width: embeddedWidth,
|
||||
height: height,
|
||||
left: navWidth,
|
||||
margin: 'inherit'
|
||||
});
|
||||
this.embeddedPanel.onResize(embeddedWidth, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
MainViewPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
MainViewPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
MainViewPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return MainViewPanel;
|
||||
});
|
||||
@@ -1,15 +1,21 @@
|
||||
/*globals define, */
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'deepforge/globals',
|
||||
'deepforge/viz/RenameablePanel',
|
||||
'panels/TilingViz/TilingVizPanel',
|
||||
'panels/OperationCodeEditor/OperationCodeEditorPanel',
|
||||
'panels/OperationInterfaceEditor/OperationInterfaceEditorPanel',
|
||||
'js/Constants',
|
||||
'underscore'
|
||||
], function (
|
||||
DeepForge,
|
||||
RenameablePanel,
|
||||
TilingViz,
|
||||
CodeEditor,
|
||||
InterfaceEditor,
|
||||
CONSTANTS,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
@@ -18,13 +24,66 @@ define([
|
||||
|
||||
OperationEditorPanel = function (layoutManager, params) {
|
||||
TilingViz.call(this, layoutManager, params);
|
||||
this.initialize();
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.initialize = function () {
|
||||
this.territory = {};
|
||||
this.territoryId = null;
|
||||
this._currentNodeId = null;
|
||||
|
||||
this.control = this;
|
||||
|
||||
// Set the editable title on node change
|
||||
this.initializeRenameable();
|
||||
};
|
||||
|
||||
//inherit from TilingViz
|
||||
_.extend(OperationEditorPanel.prototype, TilingViz.prototype);
|
||||
_.extend(
|
||||
OperationEditorPanel.prototype,
|
||||
RenameablePanel.prototype,
|
||||
TilingViz.prototype
|
||||
);
|
||||
|
||||
OperationEditorPanel.prototype.selectedObjectChanged = function (id) {
|
||||
this._currentNodeId = id;
|
||||
DeepForge.last.Operation = id;
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
// Setup the territory
|
||||
this.territory = {};
|
||||
this.territory[this._currentNodeId] = {children: 0};
|
||||
this.territoryId = this._client.addUI(this, this._eventCallback.bind(this));
|
||||
this._client.updateTerritory(this.territoryId, this.territory);
|
||||
}
|
||||
TilingViz.prototype.selectedObjectChanged.call(this, id);
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype._eventCallback = function (events) {
|
||||
events = events.find(e => e.eid === this._currentNodeId);
|
||||
this.updateTitle();
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.updateTitle = function () {
|
||||
var id = this._currentNodeId,
|
||||
node = this._client.getNode(id),
|
||||
name = node && node.getAttribute('name');
|
||||
|
||||
this.setTitle(name || '');
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.getPanels = function () {
|
||||
return [CodeEditor, InterfaceEditor];
|
||||
return [InterfaceEditor, CodeEditor];
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.onDeactivate = function () {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
|
||||
this._stateActiveObjectChanged);
|
||||
|
||||
if (this.territoryId) {
|
||||
this._client.removeUI(this.territoryId);
|
||||
}
|
||||
|
||||
TilingViz.prototype.onDeactivate.call(this);
|
||||
};
|
||||
|
||||
return OperationEditorPanel;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/*globals define*/
|
||||
define({
|
||||
PRIMITIVE: '#b0bec5',
|
||||
COMPLEX: '#78909c'
|
||||
});
|
||||
+34
-8
@@ -1,6 +1,8 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'./Colors'
|
||||
], function(
|
||||
COLORS
|
||||
) {
|
||||
'use strict';
|
||||
var OperationInterfaceEditorEvents = function() {
|
||||
@@ -9,6 +11,25 @@ define([
|
||||
this._widget.addRefTo = this.addRefTo.bind(this);
|
||||
this._widget.changePtrName = this.changePtrName.bind(this);
|
||||
this._widget.removePtr = this.removePtr.bind(this);
|
||||
this._widget.getCreationNode = this.getCreationNode.bind(this);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.getCreationNode = function(type, id) {
|
||||
var typeName = type === 'Complex' ? 'Class' : 'Primitive',
|
||||
Decorator = this._client.decoratorManager.getDecoratorForWidget(
|
||||
this.DEFAULT_DECORATOR, 'EasyDAG');
|
||||
|
||||
return {
|
||||
node: {
|
||||
id: id,
|
||||
class: 'create-node',
|
||||
name: `New ${typeName}...`,
|
||||
Decorator: Decorator,
|
||||
color: COLORS[type.toUpperCase()],
|
||||
isPrimitive: type === 'Primitive',
|
||||
attributes: {}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allValidReferences = function() {
|
||||
@@ -19,7 +40,7 @@ define([
|
||||
var notTypes = ['Data', 'Operation', 'Pipeline'];
|
||||
return this._client.getAllMetaNodes()
|
||||
.filter(node => {
|
||||
var plugins = node.getRegistry('validPlugins');
|
||||
var plugins = node.getOwnRegistry('validPlugins');
|
||||
// Convention is enforced; if the plugin generates lua artifacts,
|
||||
// it should be called `Generate`.. (something)
|
||||
return plugins && plugins.indexOf('Generate') !== -1;
|
||||
@@ -34,23 +55,28 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypeIds = function() {
|
||||
return this.allDataTypes().map(node => node.getId());
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypeIds = function(incAbstract) {
|
||||
return this.allDataTypes(incAbstract).map(node => node.getId());
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypes = function() {
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypes = function(incAbstract) {
|
||||
return this._client.getAllMetaNodes()
|
||||
.filter(node => this.hasMetaName(node.getId(), 'Data'))
|
||||
.filter(node => this.hasMetaName(node.getId(), 'Data', incAbstract))
|
||||
.filter(node => !node.isAbstract());
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype._getValidSuccessorNodes = function(nodeId) {
|
||||
// Return all data types in the meta
|
||||
OperationInterfaceEditorEvents.prototype.getValidSuccessors = function(nodeId, isInput) {
|
||||
var dataTypeIds;
|
||||
|
||||
if (nodeId !== this._currentNodeId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.allDataTypeIds().map(id => {
|
||||
// Return all data types in the meta
|
||||
// If input, include abstract types
|
||||
dataTypeIds = this.allDataTypeIds(isInput);
|
||||
|
||||
return dataTypeIds.map(id => {
|
||||
return {
|
||||
node: this._getObjectDescriptor(id)
|
||||
};
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'js/Constants',
|
||||
'deepforge/lua',
|
||||
'deepforge/viz/OperationControl',
|
||||
'./OperationInterfaceEditorControl.EventHandlers',
|
||||
'./Colors',
|
||||
'underscore'
|
||||
], function (
|
||||
EasyDAGControl,
|
||||
CONSTANTS,
|
||||
luajs,
|
||||
OperationControl,
|
||||
OperationInterfaceEditorControlEvents,
|
||||
COLORS,
|
||||
_
|
||||
) {
|
||||
|
||||
@@ -30,6 +34,8 @@ define([
|
||||
OperationInterfaceEditorControlEvents.call(this);
|
||||
this._connections = {};
|
||||
this._pointers = {};
|
||||
|
||||
this._usage = {}; // info about input usage
|
||||
};
|
||||
|
||||
_.extend(
|
||||
@@ -139,18 +145,39 @@ define([
|
||||
|
||||
desc.container = cntr.toLowerCase();
|
||||
desc.attributes = {};
|
||||
|
||||
} else if (desc.id === this._currentNodeId) {
|
||||
desc.pointers = {};
|
||||
delete desc.attributes.code;
|
||||
}
|
||||
|
||||
// Extra decoration for data
|
||||
if (this.hasMetaName(desc.id, 'Data', true)) {
|
||||
desc.color = this.getDescColor(gmeId);
|
||||
desc.isPrimitive = this.hasMetaName(gmeId, 'Primitive');
|
||||
|
||||
if (desc.container === 'inputs') {
|
||||
desc.used = this.isUsedInCode(desc.name);
|
||||
this._usage[desc.id] = desc.used;
|
||||
} else {
|
||||
desc.used = true;
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.getDescColor = function(gmeId) {
|
||||
return !this.hasMetaName(gmeId, 'Primitive', true) ? COLORS.COMPLEX :
|
||||
COLORS.PRIMITIVE;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onUnload = function(gmeId) {
|
||||
EasyDAGControl.prototype._onUnload.call(this, gmeId);
|
||||
var conn = this._connections[gmeId];
|
||||
if (conn) {
|
||||
this._widget.removeNode(conn.id);
|
||||
}
|
||||
delete this._usage[gmeId];
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onLoad = function(gmeId) {
|
||||
@@ -170,12 +197,33 @@ define([
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onUpdate = function(gmeId) {
|
||||
var inputIds,
|
||||
wasUsed,
|
||||
isUsed,
|
||||
name,
|
||||
ast,
|
||||
code;
|
||||
|
||||
if (gmeId === this._currentNodeId) {
|
||||
EasyDAGControl.prototype._onUpdate.call(this, gmeId);
|
||||
|
||||
// Update the valid pointers
|
||||
this.updatePtrs();
|
||||
|
||||
// Update the remaining usage info
|
||||
inputIds = Object.keys(this._usage);
|
||||
code = this._client.getNode(this._currentNodeId).getAttribute('code');
|
||||
ast = luajs.parser.parse(code);
|
||||
for (var i = inputIds.length; i--;) {
|
||||
wasUsed = this._usage[inputIds[i]];
|
||||
name = this._client.getNode(inputIds[i]).getAttribute('name');
|
||||
|
||||
isUsed = this.isUsedInCode(name, ast);
|
||||
if (isUsed !== wasUsed) {
|
||||
this._onUpdate(inputIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this.containedInCurrent(gmeId) && this.hasMetaName(gmeId, 'Data')) {
|
||||
EasyDAGControl.prototype._onUpdate.call(this, gmeId);
|
||||
}
|
||||
@@ -199,6 +247,7 @@ define([
|
||||
isPointer: true,
|
||||
baseName: target.getAttribute('name'),
|
||||
Decorator: Decorator,
|
||||
used: this.isUsedInCode(name),
|
||||
attributes: {},
|
||||
name: name,
|
||||
parentId: this._currentNodeId
|
||||
@@ -282,5 +331,39 @@ define([
|
||||
return conn;
|
||||
};
|
||||
|
||||
////////////////////// Unused input checking //////////////////////
|
||||
OperationInterfaceEditorControl.prototype.isUsedInCode = function(name, ast) {
|
||||
var code = this._client.getNode(this._currentNodeId).getAttribute('code'),
|
||||
r = new RegExp('\\b' + name + '\\b'),
|
||||
hasText = code.match(r) !== null;
|
||||
|
||||
// verify that it is not used only in the left side of an assignment
|
||||
if (hasText) {
|
||||
ast = ast || luajs.parser.parse(code);
|
||||
return this.isUsedInNode(name, ast);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Check if it is used in the given ast node
|
||||
OperationInterfaceEditorControl.prototype.isUsedInNode = function(name, node) {
|
||||
var isUsed = false,
|
||||
checker;
|
||||
|
||||
checker = luajs.codegen.traverse((curr, parent) => {
|
||||
if (curr.type === 'variable' && curr.val === name) {
|
||||
// Ignore if it is being assigned...
|
||||
if (parent.type === 'stat.assignment') {
|
||||
return parent.right.indexOf(curr) !== -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, found => isUsed = isUsed || (found === true));
|
||||
|
||||
checker(node);
|
||||
return isUsed;
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorControl;
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ define([
|
||||
'js/Constants',
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'deepforge/globals',
|
||||
'common/core/coreQ',
|
||||
'common/storage/constants',
|
||||
'q',
|
||||
@@ -13,6 +14,7 @@ define([
|
||||
CONSTANTS,
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
DeepForge,
|
||||
Core,
|
||||
STORAGE_CONSTANTS,
|
||||
Q,
|
||||
@@ -37,6 +39,7 @@ define([
|
||||
this.addedIds = {};
|
||||
this.executionTerritory = {};
|
||||
this.executionUI = null;
|
||||
this.invalidated = {};
|
||||
this._widget.deleteNode = id => {
|
||||
this._deleteNode(id);
|
||||
};
|
||||
@@ -53,6 +56,7 @@ define([
|
||||
|
||||
PipelineEditorControl.prototype.TERRITORY_RULE = {children: 3};
|
||||
PipelineEditorControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
DeepForge.last.Pipeline = nodeId;
|
||||
this._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
// Remove current territory patterns
|
||||
@@ -65,7 +69,7 @@ define([
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
var desc = this._getObjectDescriptor(nodeId);
|
||||
this._widget.setTitle(desc.name.toUpperCase());
|
||||
this._widget.setTitle(desc.name);
|
||||
|
||||
if (typeof desc.parentId === 'string') {
|
||||
this.$btnModelHierarchyUp.show();
|
||||
@@ -80,6 +84,19 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.hasCurrentNode = function () {
|
||||
return typeof this._currentNodeId === 'string';
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.onNodeNameChanged = function (from, to) {
|
||||
var msg = `Renaming pipeline "${from}" -> "${to}"`;
|
||||
if (from !== to && !/^\s*$/.test(to)) {
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setAttributes(this._currentNodeId, 'name', to);
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.updateTerritory = function() {
|
||||
var nodeId = this._currentNodeId;
|
||||
|
||||
@@ -119,6 +136,8 @@ define([
|
||||
this._widget.getExistingPortMatches = this.getExistingPortMatches.bind(this);
|
||||
this._widget.createConnection = this.createConnection.bind(this);
|
||||
this._widget.removeConnection = this.removeConnection.bind(this);
|
||||
this._widget.getDecorator = this.getDecorator.bind(this);
|
||||
this._widget.updateThumbnail = this.updateThumbnail.bind(this);
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.isContainedInActive = function (gmeId) {
|
||||
@@ -132,7 +151,10 @@ define([
|
||||
var desc = this._getObjectDescriptor(gmeId);
|
||||
if (desc.parentId === this._currentNodeId) {
|
||||
this.addedIds[desc.id] = true;
|
||||
return EasyDAGControl.prototype._onLoad.call(this, gmeId);
|
||||
// Validate any connections
|
||||
if (this.isValid(desc)) {
|
||||
return EasyDAGControl.prototype._onLoad.call(this, gmeId);
|
||||
}
|
||||
} else if (desc.parentId !== null &&
|
||||
this.isContainedInActive(desc.parentId) && desc.isDataPort) {
|
||||
// port added!
|
||||
@@ -141,8 +163,33 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.isValid = function (desc) {
|
||||
// If it is a "dangling connection", remove it!
|
||||
if (desc.isConnection) {
|
||||
if (!(desc.src && desc.dst)) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Removing invalid connection ${desc.id} in "${name}"`;
|
||||
|
||||
this.invalidated[desc.id] = true;
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([desc.id]);
|
||||
this._client.completeTransaction();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._onUnload = function (gmeId) {
|
||||
// Check if it has been added
|
||||
if (this.invalidated[gmeId]) {
|
||||
// No need to notify the widget; this was filtered bc it was
|
||||
// an invalid connection
|
||||
delete this.invalidated[gmeId];
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.addedIds[gmeId]) {
|
||||
delete this.addedIds[gmeId];
|
||||
return EasyDAGControl.prototype._onUnload.call(this, gmeId);
|
||||
@@ -537,5 +584,65 @@ define([
|
||||
EasyDAGControl.prototype._detachClientEventListeners.call(this);
|
||||
};
|
||||
|
||||
////////////////////// Execution Support END //////////////////////
|
||||
PipelineEditorControl.prototype.getDecorator = function (nodeId) {
|
||||
var node = this._client.getNode(nodeId);
|
||||
if (node) {
|
||||
return this._getNodeDecorator(node);
|
||||
} else {
|
||||
return this._client.decoratorManager.getDecoratorForWidget(
|
||||
this.DEFAULT_DECORATOR, WIDGET_NAME);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.updateThumbnail = function (svg) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
name,
|
||||
attrs,
|
||||
currentThumbnail,
|
||||
attrName = 'thumbnail',
|
||||
msg;
|
||||
|
||||
if (node) { // may have been deleted
|
||||
name = node.getAttribute('name');
|
||||
attrs = node.getValidAttributeNames();
|
||||
currentThumbnail = node.getAttribute(attrName);
|
||||
msg = `Updating pipeline thumbnail for "${name}"`;
|
||||
|
||||
if (attrs.indexOf(attrName) > -1 && currentThumbnail !== svg) {
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setAttributes(this._currentNodeId, attrName, svg);
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////// Criterion Support //////////////////////
|
||||
PipelineEditorControl.prototype._getValidTargetsFor = function (id, ptr) {
|
||||
// Check if the pointer is a Criterion pointer -> if so, only show the meta types
|
||||
// and the ones in the custom layer dir
|
||||
var typeIds = this._client.getPointerMeta(id, ptr).items.map(item => item.id),
|
||||
types = typeIds.map(id => this._client.getNode(id)),
|
||||
criterion = types.find(node => node.getAttribute('name') === 'Criterion'),
|
||||
items,
|
||||
criterionId;
|
||||
|
||||
if (criterion) {
|
||||
// Get all criterion types
|
||||
criterionId = criterion.getId();
|
||||
items = this._client.getAllMetaNodes().map(node => node.getId())
|
||||
.filter(id => this._client.isTypeOf(id, criterionId));
|
||||
|
||||
return items.map(id => {
|
||||
return {
|
||||
node: this._getObjectDescriptor(id)
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return EasyDAGControl.prototype._getValidTargetsFor.apply(this, arguments);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return PipelineEditorControl;
|
||||
});
|
||||
|
||||
@@ -61,9 +61,25 @@ define(['js/PanelBase/PanelBaseWithHeader',
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
// Editable pipeline name
|
||||
this.$panelHeaderTitle.on('dblclick', () => this.editTitle());
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
PipelineEditorPanel.prototype.editTitle = function () {
|
||||
if (this.control.hasCurrentNode()) {
|
||||
this.$panelHeaderTitle.editInPlace({
|
||||
css: {
|
||||
'z-index': 1000
|
||||
},
|
||||
onChange: (oldValue, newValue) => {
|
||||
this.control.onNodeNameChanged(oldValue, newValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
PipelineEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'js/NodePropertyNames'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
nodePropertyNames
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var PipelineIndexControl;
|
||||
|
||||
PipelineIndexControl = function (options) {
|
||||
|
||||
this._logger = options.logger.fork('Control');
|
||||
|
||||
this._client = options.client;
|
||||
|
||||
// Initialize core collections and variables
|
||||
this._widget = options.widget;
|
||||
|
||||
this._currentNodeId = null;
|
||||
this._embedded = options.embedded;
|
||||
|
||||
this._initWidgetEventHandlers();
|
||||
this._logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._initWidgetEventHandlers = function () {
|
||||
this._widget.deletePipeline = id => {
|
||||
var node = this._client.getNode(id),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Deleting pipeline "${name}"`;
|
||||
|
||||
// Change the current active object
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
this._widget.setName = (id, name) => {
|
||||
var oldName = this._client.getNode(id).getAttribute('name'),
|
||||
msg = `Renaming Pipeline: "${oldName}" -> "${name}"`;
|
||||
|
||||
if (oldName !== name && !/^\s*$/.test(name)) {
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setAttributes(id, 'name', name);
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer content update callbacks * * * * * * * */
|
||||
// One major concept here is with managing the territory. The territory
|
||||
// defines the parts of the project that the visualizer is interested in
|
||||
// (this allows the browser to then only load those relevant parts).
|
||||
PipelineIndexControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
this._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
// Remove current territory patterns
|
||||
if (this._currentNodeId) {
|
||||
this._client.removeUI(this._territoryId);
|
||||
}
|
||||
|
||||
this._currentNodeId = nodeId;
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
// Put new node's info into territory rules
|
||||
this._selfPatterns = {};
|
||||
this._selfPatterns[nodeId] = {children: 1};
|
||||
this._territoryId = this._client.addUI(this, this._eventCallback.bind(this));
|
||||
|
||||
// Update the territory
|
||||
this._client.updateTerritory(this._territoryId, this._selfPatterns);
|
||||
}
|
||||
};
|
||||
|
||||
// This next function retrieves the relevant node information for the widget
|
||||
PipelineIndexControl.prototype._getObjectDescriptor = function (nodeId) {
|
||||
var node = this._client.getNode(nodeId),
|
||||
objDescriptor;
|
||||
|
||||
if (node) {
|
||||
objDescriptor = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
parentId: undefined,
|
||||
thumbnail: node.getAttribute('thumbnail'),
|
||||
executionCount: node.getMemberIds('executions').length
|
||||
};
|
||||
|
||||
objDescriptor.id = node.getId();
|
||||
objDescriptor.name = node.getAttribute(nodePropertyNames.Attributes.name);
|
||||
objDescriptor.parentId = node.getParentId();
|
||||
}
|
||||
|
||||
return objDescriptor;
|
||||
};
|
||||
|
||||
/* * * * * * * * Node Event Handling * * * * * * * */
|
||||
PipelineIndexControl.prototype._eventCallback = function (events) {
|
||||
var i = events ? events.length : 0,
|
||||
event;
|
||||
|
||||
this._logger.debug('_eventCallback \'' + i + '\' items');
|
||||
|
||||
while (i--) {
|
||||
event = events[i];
|
||||
switch (event.etype) {
|
||||
case CONSTANTS.TERRITORY_EVENT_LOAD:
|
||||
this._onLoad(event.eid);
|
||||
break;
|
||||
case CONSTANTS.TERRITORY_EVENT_UPDATE:
|
||||
this._onUpdate(event.eid);
|
||||
break;
|
||||
case CONSTANTS.TERRITORY_EVENT_UNLOAD:
|
||||
this._onUnload(event.eid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._logger.debug('_eventCallback \'' + events.length + '\' items - DONE');
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._onLoad = function (gmeId) {
|
||||
if (gmeId !== this._currentNodeId) {
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(description);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._onUpdate = function (gmeId) {
|
||||
if (gmeId !== this._currentNodeId) {
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.updateNode(description);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._onUnload = function (gmeId) {
|
||||
this._widget.removeNode(gmeId);
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
|
||||
if (this._currentNodeId !== activeObjectId) {
|
||||
this.selectedObjectChanged(activeObjectId);
|
||||
}
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
PipelineIndexControl.prototype.destroy = function () {
|
||||
this._detachClientEventListeners();
|
||||
this._removeToolbarItems();
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._attachClientEventListeners = function () {
|
||||
this._detachClientEventListeners();
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._detachClientEventListeners = function () {
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype.onActivate = function () {
|
||||
this._attachClientEventListeners();
|
||||
this._displayToolbarItems();
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
WebGMEGlobal.State.registerSuppressVisualizerFromNode(true);
|
||||
WebGMEGlobal.State.registerActiveObject(this._currentNodeId);
|
||||
WebGMEGlobal.State.registerSuppressVisualizerFromNode(false);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype.onDeactivate = function () {
|
||||
this._detachClientEventListeners();
|
||||
this._hideToolbarItems();
|
||||
};
|
||||
|
||||
/* * * * * * * * * * Updating the toolbar * * * * * * * * * */
|
||||
PipelineIndexControl.prototype._displayToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].show();
|
||||
}
|
||||
} else {
|
||||
this._initializeToolbar();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._hideToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._removeToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexControl.prototype._initializeToolbar = function () {
|
||||
this._toolbarItems = [];
|
||||
this._toolbarInitialized = true;
|
||||
};
|
||||
|
||||
return PipelineIndexControl;
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed Jun 29 2016 16:10:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/PipelineIndex/PipelineIndexWidget',
|
||||
'./PipelineIndexControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
PipelineIndexWidget,
|
||||
PipelineIndexControl) {
|
||||
'use strict';
|
||||
|
||||
var PipelineIndexPanel;
|
||||
|
||||
PipelineIndexPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'PipelineIndexPanel';
|
||||
options[PanelBaseWithHeader.OPTIONS.FLOATING_TITLE] = true;
|
||||
|
||||
//call parent's constructor
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(PipelineIndexPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(PipelineIndexPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
PipelineIndexPanel.prototype._initialize = function () {
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new PipelineIndexWidget(this.logger, this.$el);
|
||||
|
||||
this.control = new PipelineIndexControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
embedded: this._embedded,
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
PipelineIndexPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
PipelineIndexPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
PipelineIndexPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
PipelineIndexPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
PipelineIndexPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return PipelineIndexPanel;
|
||||
});
|
||||
@@ -16,6 +16,7 @@ define([
|
||||
SerializeEditorControl = function (options) {
|
||||
options.attributeName = 'serialize';
|
||||
TextEditorControl.call(this, options);
|
||||
this._widget.setName = this.setName.bind(this);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 08:58:20 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
@@ -47,12 +44,23 @@ define([
|
||||
`for ${id} - node doesn't have the given attribute!`);
|
||||
}
|
||||
};
|
||||
this._widget.setName = this.setName.bind(this);
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.saveTextFor = function (id, text) {
|
||||
this._client.setAttributes(id, this.ATTRIBUTE_NAME, text);
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.setName = function (name) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
oldName = node.getAttribute('name'),
|
||||
msg = `Renaming ${oldName} -> ${name}`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setAttributes(this._currentNodeId, 'name', name);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.TERRITORY_RULE = {children: 0};
|
||||
TextEditorControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
var self = this;
|
||||
@@ -178,6 +186,10 @@ define([
|
||||
TextEditorControl.prototype.destroy = function () {
|
||||
this._detachClientEventListeners();
|
||||
this._removeToolbarItems();
|
||||
|
||||
if (this._territoryId) {
|
||||
this._client.removeUI(this._territoryId);
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._attachClientEventListeners = function () {
|
||||
|
||||
@@ -57,6 +57,7 @@ define([
|
||||
(model, nodeId) => this.selectedObjectChanged(nodeId)
|
||||
);
|
||||
}
|
||||
this.$el.css({padding: 0});
|
||||
|
||||
if (panels.length > 2) {
|
||||
this.logger.error(`Unsupported number of panels (${panels.length})`);
|
||||
|
||||
@@ -1,32 +1,96 @@
|
||||
/*globals define*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 17 2016 11:25:46 GMT-0400 (EDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'deepforge/globals',
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'./Layer',
|
||||
'q',
|
||||
'underscore',
|
||||
'css!./styles/ArchEditorWidget.css'
|
||||
], function (
|
||||
DeepForge,
|
||||
EasyDAGWidget,
|
||||
AddNodeDialog,
|
||||
Layer,
|
||||
Q,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var ArchEditorWidget;
|
||||
// WIDGET_CLASS = 'arch-editor',
|
||||
var CREATE_ID = '__NEW_LAYER__',
|
||||
ArchEditorWidget,
|
||||
WIDGET_CLASS = 'arch-editor';
|
||||
|
||||
ArchEditorWidget = function (logger, container) {
|
||||
EasyDAGWidget.call(this, logger, container);
|
||||
this.$el.addClass(WIDGET_CLASS);
|
||||
};
|
||||
|
||||
_.extend(ArchEditorWidget.prototype, EasyDAGWidget.prototype);
|
||||
|
||||
ArchEditorWidget.prototype.ItemClass = Layer;
|
||||
|
||||
ArchEditorWidget.prototype.onCreateInitialNode = function() {
|
||||
var nodes = this.getValidInitialNodes();
|
||||
return this.promptLayer(nodes)
|
||||
.then(selected => this.createNode(selected.node.id));
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype.onAddButtonClicked = function(item, reverse) {
|
||||
var nodes = this.getValidSuccessors(item.id);
|
||||
|
||||
return this.promptLayer(nodes)
|
||||
.then(selected => this.onAddItemSelected(item, selected, reverse));
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype.promptLayer = function(nodes) {
|
||||
var deferred = Q.defer(),
|
||||
types = {},
|
||||
Decorator = this.getCreateNewDecorator(),
|
||||
createNews,
|
||||
opts = {}; // 'create new' nodes
|
||||
|
||||
nodes.map(pair => pair.node)
|
||||
.forEach(node => types[node.layerType] = node.color);
|
||||
|
||||
createNews = Object.keys(types).map(type =>
|
||||
this._creationNode(type, types[type], Decorator));
|
||||
|
||||
nodes = nodes.concat(createNews);
|
||||
|
||||
// Sort by layer type
|
||||
opts.tabs = Object.keys(types);
|
||||
opts.tabFilter = (tab, pair) => {
|
||||
return pair.node.layerType === tab;
|
||||
};
|
||||
|
||||
AddNodeDialog.prompt(nodes, opts)
|
||||
.then(selected => {
|
||||
if (selected.node.id === CREATE_ID) {
|
||||
DeepForge.create.Layer(selected.node.layerType);
|
||||
} else {
|
||||
deferred.resolve(selected);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype._creationNode = function(type, color, Decorator) {
|
||||
return {
|
||||
node: {
|
||||
id: CREATE_ID,
|
||||
class: 'create-node',
|
||||
attributes: {},
|
||||
name: `New ${type} Layer...`,
|
||||
baseName: `New ${type} Layer...`,
|
||||
layerType: type,
|
||||
color: color,
|
||||
Decorator: Decorator
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return ArchEditorWidget;
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ define([
|
||||
this.width = this.decorator.width;
|
||||
this.height = this.decorator.height;
|
||||
|
||||
this.initializeTooltips();
|
||||
// Set up decorator callbacks
|
||||
this.setupDecoratorCallbacks();
|
||||
};
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/TextEditor/TextEditorWidget',
|
||||
'widgets/SerializeEditor/SerializeEditorWidget',
|
||||
'underscore',
|
||||
'css!./styles/DeserializeEditorWidget.css'
|
||||
], function (
|
||||
TextEditorWidget,
|
||||
SerializeEditorWidget,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
@@ -19,10 +19,10 @@ define([
|
||||
//WIDGET_CLASS = 'deserialize-editor';
|
||||
|
||||
DeserializeEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
SerializeEditorWidget.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(DeserializeEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
_.extend(DeserializeEditorWidget.prototype, SerializeEditorWidget.prototype);
|
||||
|
||||
DeserializeEditorWidget.prototype.getHeader = function(desc) {
|
||||
return [
|
||||
@@ -34,8 +34,8 @@ define([
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
DeserializeEditorWidget.prototype.updateNode = function() {
|
||||
// nop
|
||||
DeserializeEditorWidget.prototype.getNameRegex = function() {
|
||||
return /The deserialization function for (.*)/;
|
||||
};
|
||||
|
||||
return DeserializeEditorWidget;
|
||||
|
||||
@@ -24,6 +24,7 @@ define([
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
icon: 'monitor',
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
|
||||
@@ -100,6 +100,17 @@ define([
|
||||
};
|
||||
};
|
||||
|
||||
LogViewerWidget.prototype.addNode = function (desc) {
|
||||
var atEOF = this.editor.getLastVisibleRow()+1 ===
|
||||
this.editor.session.getLength();
|
||||
|
||||
TextEditorWidget.prototype.addNode.call(this, desc);
|
||||
|
||||
if (atEOF) { // Scroll to bottom
|
||||
this.editor.gotoLine(Infinity);
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerWidget.prototype.getEditorOptions = function() {
|
||||
return {
|
||||
fontSize: '10pt'
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<li data-id="<%= id %>" class="select-node">
|
||||
<a>
|
||||
<%= name %>
|
||||
<div class="pull-right">
|
||||
<% if (typeof data !== 'undefined') { %>
|
||||
<span class="glyphicon glyphicon-cloud-download dl-node"></span>
|
||||
<% } %>
|
||||
<span class="glyphicon glyphicon-remove del-node"></span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -0,0 +1,182 @@
|
||||
/*globals $, WebGMEGlobal,define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'deepforge/globals',
|
||||
'text!./NavBar.html',
|
||||
'text!./ListItem.ejs',
|
||||
'underscore',
|
||||
'css!./styles/MainViewWidget.css'
|
||||
], function (
|
||||
DeepForge,
|
||||
NavBarHTML,
|
||||
ListItem,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var MainViewWidget,
|
||||
WIDGET_CLASS = 'main-view',
|
||||
CreateListItem = _.template(ListItem);
|
||||
|
||||
MainViewWidget = function (logger, container) {
|
||||
this._logger = logger.fork('Widget');
|
||||
this.$el = container;
|
||||
this.$el.addClass(WIDGET_CLASS);
|
||||
this.initialize();
|
||||
this._logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.initialize = function () {
|
||||
// Create the nav bar
|
||||
this.$nav = $(NavBarHTML);
|
||||
this.$el.append(this.$nav);
|
||||
|
||||
this.$archlist = this.$nav.find('#arch-list-content');
|
||||
this.$artifacts = this.$nav.find('#artifact-list-content');
|
||||
|
||||
// opening, closing
|
||||
this._closed = true;
|
||||
this.$nav.find('.side-nav-control').on('click', this.controlClicked.bind(this));
|
||||
this.$nav.on('transitionend', this.onChanged.bind(this));
|
||||
|
||||
// action buttons
|
||||
this.$nav.on('click', '#create-artifact', DeepForge.create.Artifact);
|
||||
this.$nav.on('click', '#create-arch', DeepForge.create.Architecture);
|
||||
this.$nav.on('click', '.select-node', this.onNodeClick.bind(this));
|
||||
this.$nav.on('click', '.del-node', this.onDelNodeClick.bind(this));
|
||||
this.$nav.on('click', '.dl-node', this.onDownloadNodeClick.bind(this));
|
||||
|
||||
this.htmlFor = {};
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.width = function () {
|
||||
return this._closedWidth;
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onChanged = function () {
|
||||
if (!this._closed) { // add the text back
|
||||
this.$nav.removeClass('hide-list');
|
||||
} else {
|
||||
this._closedWidth = this.$nav.width();
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.controlClicked = function () {
|
||||
this._closed = !this._closed;
|
||||
if (this._closed) {
|
||||
this.$nav.addClass('hide-list');
|
||||
this.$nav.addClass('closed');
|
||||
} else { // remove the 'closed' class
|
||||
this.$nav.removeClass('closed');
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onWidgetContainerResize = function () {
|
||||
var rect = this.$el[0].getBoundingClientRect(),
|
||||
top = rect.top;
|
||||
|
||||
this.$nav.css({
|
||||
top: top + 'px'
|
||||
});
|
||||
|
||||
if (this._closed) {
|
||||
this._closedWidth = this.$nav.width();
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.createNode = function(desc) {
|
||||
// Create the architecture list item
|
||||
var li;
|
||||
|
||||
desc.download = false;
|
||||
li = $(CreateListItem(desc));
|
||||
this.htmlFor[desc.id] = li;
|
||||
return li;
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.addArch = function(desc) {
|
||||
var html = this.createNode(desc);
|
||||
this.$archlist.append(html);
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.addArtifact = function(desc) {
|
||||
var html = this.createNode(desc);
|
||||
this.$artifacts.append(html);
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onDelNodeClick = function(event) {
|
||||
var id = this.getElementId(event.target);
|
||||
event.stopPropagation();
|
||||
if (id) {
|
||||
this.deleteNode(id);
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onDownloadNodeClick = function(event) {
|
||||
var id = this.getElementId(event.target),
|
||||
url;
|
||||
|
||||
event.stopPropagation();
|
||||
if (id) {
|
||||
url = this.dataUrlFor(id);
|
||||
if (url) {
|
||||
this._download(url);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype._download = function(url) {
|
||||
var anchor = document.createElement('a');
|
||||
anchor.setAttribute('href', url);
|
||||
anchor.setAttribute('target', '_self');
|
||||
anchor.click();
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onNodeClick = function(event) {
|
||||
var id = this.getElementId(event.target);
|
||||
event.stopPropagation();
|
||||
if (id) {
|
||||
WebGMEGlobal.State.registerActiveObject(id);
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.getElementId = function(element) {
|
||||
while(!element.getAttribute('data-id') && element.parentNode) {
|
||||
element = element.parentNode;
|
||||
}
|
||||
return element.getAttribute('data-id');
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.removeNode = function(id) {
|
||||
if (this.htmlFor[id]) {
|
||||
this.htmlFor[id].remove();
|
||||
delete this.htmlFor[id];
|
||||
}
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.updateNode = function (desc) {
|
||||
var oldHtml = this.htmlFor[desc.id],
|
||||
node;
|
||||
|
||||
if (oldHtml) {
|
||||
node = this.createNode(desc);
|
||||
node.insertAfter(oldHtml);
|
||||
oldHtml.remove();
|
||||
}
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
MainViewWidget.prototype.destroy = function () {
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onActivate = function () {
|
||||
this._logger.debug('MainViewWidget has been activated');
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onDeactivate = function () {
|
||||
this._logger.debug('MainViewWidget has been deactivated');
|
||||
};
|
||||
|
||||
return MainViewWidget;
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
<nav class="side-nav fixed closed hide-list">
|
||||
<li class="pull-right side-nav-control">
|
||||
<span class="glyphicon glyphicon-menu-hamburger" aria-hidden="true"></span>
|
||||
</li>
|
||||
<li class="no-padding">
|
||||
<ul class="collapsible" data-collapsible="accordion">
|
||||
<li>
|
||||
<a data-target="#arch-list" data-toggle="collapse">Architectures</a>
|
||||
<div id="arch-list" class="collapse">
|
||||
<ul class="sublist">
|
||||
<div id="arch-list-content"></div>
|
||||
<li><a id="create-arch" class="action" href="#">New...</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="no-padding">
|
||||
<ul class="collapsible collapsible-accordion">
|
||||
<li>
|
||||
<a data-target="#artifact-list" data-toggle="collapse">Artifacts</a>
|
||||
<div id="artifact-list" class="collapse">
|
||||
<ul class="sublist">
|
||||
<div id="artifact-list-content"></div>
|
||||
<li>
|
||||
<a id="create-artifact" class="action" href="#!">Upload...</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</nav>
|
||||
@@ -0,0 +1,276 @@
|
||||
.main-view .side-nav-control {
|
||||
padding-right: 1em;
|
||||
padding-top: 1em;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
.main-view .side-nav-control span {
|
||||
font-size: 16px;
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
/* closed */
|
||||
.main-view .side-nav.closed {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.main-view .hide-list ul {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.main-view .side-nav {
|
||||
transform: translateX(0);
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
/* closed END */
|
||||
|
||||
.main-view .side-nav .action {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.main-view .side-nav {
|
||||
background-color: #f5f5f5 !important;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.main-view .side-nav a {
|
||||
color: #444;
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.main-view .side-nav li {
|
||||
text-align: left;
|
||||
color: #f5f5f5 !important;
|
||||
}
|
||||
|
||||
.main-view .side-nav .sublist ul {
|
||||
padding-left: 20px;
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
.main-view .side-nav .sublist a {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.main-view ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.main-view .valign-wrapper {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main-view .valign-wrapper .valign {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-view ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.main-view ul li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.main-view .clearfix {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.main-view .z-depth-1,
|
||||
.main-view nav,
|
||||
.main-view .card-panel,
|
||||
.main-view .card,
|
||||
.main-view .toast,
|
||||
.main-view .btn,
|
||||
.main-view .btn-large,
|
||||
.main-view .btn-floating,
|
||||
.main-view .dropdown-content,
|
||||
.main-view .collapsible,
|
||||
.main-view .side-nav {
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible,
|
||||
.main-view .side-nav.fixed .collapsible {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible li,
|
||||
.main-view .side-nav.fixed .collapsible li {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-header,
|
||||
.main-view .side-nav.fixed .collapsible-header {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
line-height: inherit;
|
||||
height: inherit;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-header:hover,
|
||||
.main-view .side-nav.fixed .collapsible-header:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-header i,
|
||||
.main-view .side-nav.fixed .collapsible-header i {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-body,
|
||||
.main-view .side-nav.fixed .collapsible-body {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-body li a,
|
||||
.main-view .side-nav.fixed .collapsible-body li a {
|
||||
padding: 0 37.5px 0 45px;
|
||||
}
|
||||
|
||||
.main-view .side-nav {
|
||||
position: fixed;
|
||||
width: 200px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
-o-transform: translateX(-100%);
|
||||
-ms-transform: translateX(-100%);
|
||||
-webkit-transform: translateX(-100%);
|
||||
-moz-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
height: 100%;
|
||||
height: calc(100% + 60px);
|
||||
height: -moz-calc(100%);
|
||||
padding-bottom: 60px;
|
||||
background-color: #fff;
|
||||
z-index: 999;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.main-view .side-nav li {
|
||||
float: none;
|
||||
line-height: 64px;
|
||||
}
|
||||
|
||||
.main-view .side-nav li.active {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-view .side-nav a:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-view .side-nav a.btn,
|
||||
.main-view .side-nav a.btn-large,
|
||||
.main-view .side-nav a.btn-large,
|
||||
.main-view .side-nav a.btn-flat,
|
||||
.main-view .side-nav a.btn-floating {
|
||||
margin: 10px 15px;
|
||||
}
|
||||
|
||||
.main-view .side-nav a.btn,
|
||||
.main-view .side-nav a.btn-large,
|
||||
.main-view .side-nav a.btn-large,
|
||||
.main-view .side-nav a.btn-floating {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main-view .side-nav a.btn-flat {
|
||||
color: #343434;
|
||||
}
|
||||
|
||||
.main-view .side-nav a.btn:hover,
|
||||
.main-view .side-nav a.btn-large:hover,
|
||||
.main-view .side-nav a.btn-large:hover {
|
||||
background-color: #2bbbad;
|
||||
}
|
||||
|
||||
.main-view .side-nav a.btn-floating:hover {
|
||||
background-color: #26a69a;
|
||||
}
|
||||
|
||||
.main-view .drag-target {
|
||||
height: 100%;
|
||||
width: 10px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.main-view .side-nav.fixed a {
|
||||
display: block;
|
||||
padding: 0 30px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.main-view .side-nav.fixed {
|
||||
left: 0;
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-body li.active,
|
||||
.main-view .side-nav.fixed .collapsible-body li.active {
|
||||
background-color: #ee6e73;
|
||||
}
|
||||
|
||||
.main-view .side-nav .collapsible-body li.active a,
|
||||
.main-view .side-nav.fixed .collapsible-body li.active a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Improve readability of focused elements when they are also in an
|
||||
* active/hover state.
|
||||
*/
|
||||
|
||||
.main-view a:active,
|
||||
.main-view a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.main-view a {
|
||||
background-color: transparent;
|
||||
color: #039be5;
|
||||
text-decoration: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.main-view .collapsible.popout {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.main-view .action a {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ define([
|
||||
refs = desc.references.map(name => `-- ${name}`).join('\n'),
|
||||
outputs,
|
||||
header = [
|
||||
`-- Editing "${desc.name}"`,
|
||||
'-- '
|
||||
`-- Editing "${desc.name}" Implementation`
|
||||
];
|
||||
|
||||
if (inputs.length) {
|
||||
header.push('--');
|
||||
header.push('-- Defined variables:');
|
||||
header.push(inputs);
|
||||
}
|
||||
@@ -42,6 +42,7 @@ define([
|
||||
header.push(refs);
|
||||
}
|
||||
header.push('--');
|
||||
header.push('-- The following will be executed when the operation is run:');
|
||||
|
||||
// Add info about outputs
|
||||
outputs = desc.outputs.map(pair => `-- ${pair[0]} = <some ${pair[1]}>`)
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'deepforge/viz/Buttons',
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'widgets/EasyDAG/Icons',
|
||||
'underscore'
|
||||
], function(
|
||||
CommonButtons,
|
||||
EasyDAGButtons,
|
||||
Icons,
|
||||
_
|
||||
) {
|
||||
|
||||
@@ -13,14 +17,13 @@ define([
|
||||
|
||||
_.extend(AddOutput.prototype, EasyDAGButtons.Add.prototype);
|
||||
|
||||
AddOutput.BORDER = 2;
|
||||
AddOutput.prototype._render = function() {
|
||||
var lineRadius = EasyDAGButtons.Add.SIZE - EasyDAGButtons.Add.BORDER,
|
||||
btnColor = '#90caf9',
|
||||
lineColor = '#7986cb';
|
||||
var lineRadius = EasyDAGButtons.Add.SIZE - AddOutput.BORDER,
|
||||
btnColor = '#90caf9';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
@@ -28,34 +31,7 @@ define([
|
||||
.attr('r', EasyDAGButtons.Add.SIZE)
|
||||
.attr('fill', btnColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('x1', 0)
|
||||
.attr('x2', 0)
|
||||
.attr('y1', -lineRadius)
|
||||
.attr('y2', lineRadius)
|
||||
.attr('stroke-width', 2)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
// Arrow
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('y1', lineRadius)
|
||||
.attr('y2', 0)
|
||||
.attr('x1', 0)
|
||||
.attr('x2', -lineRadius)
|
||||
.attr('stroke-width', 2)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('y1', lineRadius)
|
||||
.attr('y2', 0)
|
||||
.attr('x1', 0)
|
||||
.attr('x2', lineRadius)
|
||||
.attr('stroke-width', 2)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
Icons.addIcon('chevron-bottom', this.$el, {radius: lineRadius});
|
||||
};
|
||||
|
||||
var AddInput = function(params) {
|
||||
@@ -80,12 +56,10 @@ define([
|
||||
|
||||
AddRef.prototype._render = function() {
|
||||
var lineRadius = EasyDAGButtons.Add.SIZE - EasyDAGButtons.Add.BORDER,
|
||||
btnColor = '#81c784',
|
||||
lineColor = '#7986cb';
|
||||
btnColor = '#80deea';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
@@ -93,24 +67,7 @@ define([
|
||||
.attr('r', EasyDAGButtons.Add.SIZE)
|
||||
.attr('fill', btnColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('x1', 0)
|
||||
.attr('x2', 0)
|
||||
.attr('y1', -lineRadius)
|
||||
.attr('y2', lineRadius)
|
||||
.attr('stroke-width', 2.5)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('y1', 0)
|
||||
.attr('y2', 0)
|
||||
.attr('x1', -lineRadius)
|
||||
.attr('x2', lineRadius)
|
||||
.attr('stroke-width', 2.5)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
Icons.addIcon('plus', this.$el, {radius: lineRadius});
|
||||
};
|
||||
|
||||
var Delete = function(params) {
|
||||
@@ -132,6 +89,7 @@ define([
|
||||
AddOutput: AddOutput,
|
||||
AddInput: AddInput,
|
||||
AddRef: AddRef,
|
||||
GoToBase: CommonButtons.GoToBase,
|
||||
Delete: Delete
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define*/
|
||||
/*globals define */
|
||||
define([
|
||||
'widgets/EasyDAG/DAGItem',
|
||||
'underscore'
|
||||
@@ -9,10 +9,57 @@ define([
|
||||
|
||||
var Item = function(parentEl, desc) {
|
||||
DAGItem.call(this, parentEl, desc);
|
||||
|
||||
// Show the warnings
|
||||
this.$warning = null;
|
||||
this.updateWarnings();
|
||||
};
|
||||
|
||||
_.extend(Item.prototype, DAGItem.prototype);
|
||||
|
||||
Item.prototype.update = function(desc) {
|
||||
DAGItem.prototype.update.call(this, desc);
|
||||
this.updateWarnings();
|
||||
};
|
||||
|
||||
Item.prototype.updateWarnings = function() {
|
||||
if (this.desc.used === false) {
|
||||
this.warn('Unused Input!');
|
||||
} else {
|
||||
this.clearWarning();
|
||||
}
|
||||
};
|
||||
|
||||
Item.prototype.warn = function(message) {
|
||||
// Create a temporary div over the given svg element
|
||||
if (this.$warning) {
|
||||
this.clearWarning();
|
||||
}
|
||||
|
||||
this.decorator.highlight('#ffeb3b');
|
||||
this.$warning = this.createTooltip(message, {
|
||||
showIf: () => !this.isSelected(),
|
||||
tipJoint: 'bottom',
|
||||
style: 'standard'
|
||||
});
|
||||
};
|
||||
|
||||
Item.prototype.clearWarning = function() {
|
||||
if (this.$warning) {
|
||||
this.destroyTooltip(this.$warning);
|
||||
this.$warning = null;
|
||||
}
|
||||
this.decorator.unHighlight();
|
||||
};
|
||||
|
||||
|
||||
Item.prototype.onSelect = function() {
|
||||
DAGItem.prototype.onSelect.call(this);
|
||||
if (this.$warning) {
|
||||
this.$warning.hide();
|
||||
}
|
||||
};
|
||||
|
||||
Item.prototype.setupDecoratorCallbacks = function() {
|
||||
DAGItem.prototype.setupDecoratorCallbacks.call(this);
|
||||
// Add ptr name change
|
||||
|
||||
+28
-19
@@ -1,11 +1,8 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 31 2016 09:16:24 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'deepforge/globals',
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'./SelectionManager',
|
||||
@@ -13,6 +10,7 @@ define([
|
||||
'underscore',
|
||||
'css!./styles/OperationInterfaceEditorWidget.css'
|
||||
], function (
|
||||
DeepForge,
|
||||
EasyDAG,
|
||||
AddNodeDialog,
|
||||
SelectionManager,
|
||||
@@ -22,10 +20,13 @@ define([
|
||||
'use strict';
|
||||
|
||||
var OperationInterfaceEditorWidget,
|
||||
WIDGET_CLASS = 'operation-interface-editor';
|
||||
WIDGET_CLASS = 'operation-interface-editor',
|
||||
NEW_CLASS_ID = '__NEW_CLASS__',
|
||||
NEW_PRIM_ID = '__NEW_PRIM__';
|
||||
|
||||
OperationInterfaceEditorWidget = function (logger, container) {
|
||||
EasyDAG.call(this, logger, container);
|
||||
this.$el.addClass(WIDGET_CLASS);
|
||||
};
|
||||
|
||||
_.extend(OperationInterfaceEditorWidget.prototype, EasyDAG.prototype);
|
||||
@@ -44,23 +45,31 @@ define([
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddButtonClicked = function(item, isInput) {
|
||||
var successorPairs = this.getValidSuccessorNodes(item.id),
|
||||
successor = successorPairs[0];
|
||||
var successorPairs = this.getValidSuccessors(item.id, isInput),
|
||||
newClass = this.getCreationNode('Complex', NEW_CLASS_ID),
|
||||
newPrim = this.getCreationNode('Primitive', NEW_PRIM_ID),
|
||||
opts = {};
|
||||
|
||||
if (successorPairs.length > 1) {
|
||||
// Create the modal view with all possible subsequent nodes
|
||||
var dialog = new AddNodeDialog(),
|
||||
title = this._getAddSuccessorTitle(item);
|
||||
// Add the 'Create Class' node
|
||||
successorPairs.push(newClass);
|
||||
successorPairs.push(newPrim);
|
||||
|
||||
dialog.show(title, successorPairs);
|
||||
dialog.onSelect = pair => {
|
||||
if (pair) {
|
||||
this.onAddItemSelected(pair, isInput);
|
||||
// Add tabs
|
||||
opts.tabs = ['Classes', 'Primitive'];
|
||||
opts.tabFilter = (tab, pair) => {
|
||||
return pair.node.isPrimitive === (tab === 'Primitive');
|
||||
};
|
||||
|
||||
AddNodeDialog.prompt(successorPairs, opts)
|
||||
.then(selected => {
|
||||
if (selected.node.id === NEW_CLASS_ID) {
|
||||
DeepForge.create.Complex();
|
||||
} else if (selected.node.id === NEW_PRIM_ID) {
|
||||
DeepForge.create.Primitive();
|
||||
} else {
|
||||
this.onAddItemSelected(selected, isInput);
|
||||
}
|
||||
};
|
||||
} else if (successor) {
|
||||
this.onAddItemSelected(successor, isInput);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onDeactivate = function() {
|
||||
|
||||
@@ -53,7 +53,7 @@ define([
|
||||
x: 2*width/3,
|
||||
y: 0
|
||||
});
|
||||
} else { // Data...
|
||||
} else { // Data or pointer...
|
||||
new Buttons.Delete({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
@@ -61,6 +61,16 @@ define([
|
||||
x: cx,
|
||||
y: 0
|
||||
});
|
||||
|
||||
if (!this.selectedItem.desc.isPointer) {
|
||||
new Buttons.GoToBase({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
define([
|
||||
'widgets/EasyDAG/Buttons'
|
||||
], function(
|
||||
EasyDAGButtons
|
||||
) {
|
||||
|
||||
// Create a GoToBase button
|
||||
var client = WebGMEGlobal.Client,
|
||||
LocalOps = {
|
||||
ArtifactLoader: true,
|
||||
Save: true
|
||||
};
|
||||
|
||||
var GoToBase = function(params) {
|
||||
// Check if it should be disabled
|
||||
var baseId = this._getBaseId(params.item),
|
||||
base = client.getNode(baseId);
|
||||
|
||||
params.disabled = base ? base.isLibraryElement() : false;
|
||||
EasyDAGButtons.ButtonBase.call(this, params);
|
||||
};
|
||||
|
||||
GoToBase.SIZE = 10;
|
||||
GoToBase.BORDER = 5;
|
||||
GoToBase.prototype.BTN_CLASS = 'add';
|
||||
GoToBase.prototype = new EasyDAGButtons.ButtonBase();
|
||||
|
||||
GoToBase.prototype._render = function() {
|
||||
var lineRadius = GoToBase.SIZE - GoToBase.BORDER,
|
||||
btnColor = '#90caf9',
|
||||
lineColor = '#7986cb';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
.attr('r', GoToBase.SIZE)
|
||||
.attr('fill', btnColor);
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
//.attr('cx', -)
|
||||
//.attr('cy', 0)
|
||||
.attr('r', GoToBase.SIZE/3)
|
||||
.attr('stroke-width', 3)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('y1', 0)
|
||||
.attr('y2', 0)
|
||||
.attr('x1', -lineRadius)
|
||||
.attr('x2', lineRadius)
|
||||
.attr('stroke-width', 3)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
};
|
||||
|
||||
GoToBase.prototype._onClick = function(item) {
|
||||
var node = client.getNode(item.id),
|
||||
baseId = node.getBaseId();
|
||||
|
||||
window.DeepForge = window.DeepForge || {};
|
||||
window.DeepForge.lastPipeline = item.desc.parentId;
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(baseId);
|
||||
};
|
||||
|
||||
GoToBase.prototype._getBaseId = function(item) {
|
||||
var n = client.getNode(item.id);
|
||||
return n.getBaseId();
|
||||
};
|
||||
|
||||
return {
|
||||
DeleteOne: EasyDAGButtons.DeleteOne,
|
||||
GoToBase: GoToBase
|
||||
};
|
||||
});
|
||||
@@ -6,16 +6,20 @@
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'deepforge/globals',
|
||||
'./OperationNode',
|
||||
'./Connection',
|
||||
'./SelectionManager',
|
||||
'underscore',
|
||||
'css!./styles/PipelineEditorWidget.css'
|
||||
], function (
|
||||
AddNodeDialog,
|
||||
EasyDAGWidget,
|
||||
PipelineControl,
|
||||
DeepForge,
|
||||
OperationNode,
|
||||
Connection,
|
||||
SelectionManager,
|
||||
@@ -31,6 +35,7 @@ define([
|
||||
DEFAULT: 'default',
|
||||
CONNECTING: 'connecting'
|
||||
},
|
||||
UPLOAD_ARTIFACT_ID = '__UPLOAD_ARTIFACT__',
|
||||
STATUS_TO_CLASS = {
|
||||
running: 'warning',
|
||||
success: 'success',
|
||||
@@ -85,6 +90,7 @@ define([
|
||||
// Update the given port...
|
||||
dstItem.refreshPorts();
|
||||
}
|
||||
this.refreshThumbnail();
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.addNode = function(desc) {
|
||||
@@ -104,6 +110,7 @@ define([
|
||||
this.PORT_STATE = STATE.DEFAULT;
|
||||
this.connectPort.apply(this, this.srcPortToConnectArgs);
|
||||
}
|
||||
this.refreshThumbnail();
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype._removeConnection = function(id) {
|
||||
@@ -118,6 +125,7 @@ define([
|
||||
dst.refreshPorts();
|
||||
}
|
||||
EasyDAGWidget.prototype._removeConnection.call(this, id);
|
||||
this.refreshThumbnail();
|
||||
};
|
||||
|
||||
// May not actually need these port methods
|
||||
@@ -137,6 +145,7 @@ define([
|
||||
this.removePort(gmeId);
|
||||
} else {
|
||||
EasyDAGWidget.prototype.removeNode.call(this, gmeId);
|
||||
this.refreshThumbnail();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -338,5 +347,91 @@ define([
|
||||
this.updateExecutions();
|
||||
};
|
||||
|
||||
////////////////////////// Action Overrides //////////////////////////
|
||||
PipelineEditorWidget.prototype.selectTargetFor = function(itemId) {
|
||||
// If it is an 'ArtifactLoader', then we will need to add 'upload artifact'
|
||||
// options
|
||||
if (this.items[itemId].desc.baseName === 'ArtifactLoader') {
|
||||
this.selectTargetForLoader.apply(this, arguments);
|
||||
} else {
|
||||
return EasyDAGWidget.prototype.selectTargetFor.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.selectTargetForLoader = function(itemId, ptr, filter) {
|
||||
var validTargets = this.getValidTargetsFor(itemId, ptr, filter),
|
||||
nodeId = validTargets.length ? validTargets[0].node.id : null,
|
||||
uploadNode;
|
||||
|
||||
// Add the 'Upload Artifact' option
|
||||
uploadNode = {
|
||||
node: {
|
||||
id: UPLOAD_ARTIFACT_ID,
|
||||
name: 'Upload Artifact',
|
||||
class: 'create-node',
|
||||
attributes: {},
|
||||
Decorator: this.getDecorator(nodeId)
|
||||
}
|
||||
};
|
||||
validTargets.push(uploadNode);
|
||||
|
||||
AddNodeDialog.prompt(validTargets)
|
||||
.then(selected => {
|
||||
if (selected.node.id === UPLOAD_ARTIFACT_ID) {
|
||||
DeepForge.create.Artifact();
|
||||
} else {
|
||||
var item = this.items[itemId];
|
||||
if (item.decorator.savePointer) {
|
||||
return item.decorator.savePointer(ptr, selected.node.id);
|
||||
} else {
|
||||
this.setPointerForNode(itemId, ptr, selected.node.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
////////////////////////// Action Overrides END //////////////////////////
|
||||
|
||||
////////////////////////// Thumbnail updates //////////////////////////
|
||||
PipelineEditorWidget.prototype.getSvgDistanceDim = function(dim) {
|
||||
var maxValue = this._getMaxAlongAxis(dim),
|
||||
nodes,
|
||||
minValue;
|
||||
|
||||
nodes = this.graph.nodes().map(id => this.graph.node(id));
|
||||
minValue = Math.min.apply(null, nodes.map(node => node[dim]));
|
||||
return maxValue-minValue;
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.getSvgWidth = function() {
|
||||
return this.getSvgDistanceDim('x');
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.getSvgHeight = function() {
|
||||
return this.getSvgDistanceDim('y');
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.getViewBox = function() {
|
||||
var maxX = this.getSvgWidth('x'),
|
||||
maxY = this.getSvgHeight('y');
|
||||
|
||||
return `0 0 ${maxX} ${maxY}`;
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.refreshThumbnail = _.debounce(function() {
|
||||
// Get the svg...
|
||||
var svg = document.createElement('svg'),
|
||||
group = this.$svg.node(),
|
||||
child;
|
||||
|
||||
svg.setAttribute('viewBox', this.getViewBox());
|
||||
for (var i = 0; i < group.children.length; i++) {
|
||||
child = $(group.children[i]);
|
||||
svg.appendChild(child.clone()[0]);
|
||||
}
|
||||
|
||||
this.updateThumbnail(svg.outerHTML);
|
||||
}, 1000);
|
||||
|
||||
return PipelineEditorWidget;
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'./Buttons',
|
||||
'deepforge/viz/Buttons',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
@@ -26,15 +26,18 @@ define([
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
// If the operation has a user-defined base type,
|
||||
// show a button for jumping to the base def
|
||||
new Buttons.GoToBase({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
|
||||
if (!this.selectedItem.isConnection) {
|
||||
// If the operation has a user-defined base type,
|
||||
// show a button for jumping to the base def
|
||||
new Buttons.GoToBase({
|
||||
$pEl: this.$selection,
|
||||
context: this._widget,
|
||||
item: this.selectedItem,
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
SelectionManager.prototype.deselect = function() {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<div class="col s6 m3 l2">
|
||||
<div class="pipeline card" data-id="<%= id %>" style="overflow: hidden;">
|
||||
<div class="center preview card-image waves-effect waves-block waves-light">
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<span data-id="<%= id %>" class="card-title activator grey-text text-darken-4 pipeline-name"><%= name %></span>
|
||||
<p>
|
||||
<% if (executionCount === 0) { %>
|
||||
No executions
|
||||
<% } else if (executionCount === 1){ %>
|
||||
Executed once
|
||||
<% } else if (executionCount === 2){ %>
|
||||
Executed twice
|
||||
<% } else { %>
|
||||
Executed <%= executionCount %> times
|
||||
<% } %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-reveal" style="display: none; transform: translateY(0px);">
|
||||
<span class="card-title grey-text text-darken-4">"<%= name %>" Executions<i class="material-icons right">close</i></span>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="open-pipeline" href="#">Open</a>
|
||||
<a class="delete-pipeline" data-id="<%= id %>" href="#">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,154 @@
|
||||
/*globals define, $, WebGMEGlobal */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'text!./Pipeline.ejs',
|
||||
'underscore',
|
||||
'css!./styles/PipelineIndexWidget.css'
|
||||
], function (
|
||||
PipelineHtml,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var PipelineIndexWidget,
|
||||
PipelineTemplate = _.template(PipelineHtml),
|
||||
EMPTY_MSG = 'No Existing Pipelines... yet!',
|
||||
WIDGET_CLASS = 'pipeline-index';
|
||||
|
||||
PipelineIndexWidget = function (logger, container) {
|
||||
this._logger = logger.fork('Widget');
|
||||
|
||||
this.$el = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
container.append(this.$el);
|
||||
container.addClass(`${WIDGET_CLASS} container`);
|
||||
|
||||
this.cards = {};
|
||||
this.nodes = {};
|
||||
|
||||
this.$backgroundText = null;
|
||||
this.updateBackgroundText();
|
||||
|
||||
this._initializeEventHandlers();
|
||||
this._logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype._initializeEventHandlers = function () {
|
||||
this.$el.on('click', '.open-pipeline', this.openPipeline);
|
||||
this.$el.on('click', '.preview.card-image', this.openPipeline);
|
||||
|
||||
this.$el.on('click', '.delete-pipeline', event => {
|
||||
var id = event.target.getAttribute('data-id');
|
||||
this.deletePipeline(id);
|
||||
});
|
||||
|
||||
this.$el.on('dblclick', '.pipeline-name', event => {
|
||||
var html = $(event.target),
|
||||
id = html.data('id');
|
||||
|
||||
html.editInPlace({
|
||||
css: {
|
||||
'z-index': 1000
|
||||
},
|
||||
onChange: (oldVal, newVal) => {
|
||||
this.setName(id, newVal);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.updateBackgroundText = function() {
|
||||
if (this.$backgroundText) {
|
||||
this.$backgroundText.remove();
|
||||
}
|
||||
|
||||
// Add background text if empty
|
||||
if (Object.keys(this.cards).length === 0) {
|
||||
this.$backgroundText = $('<div>', {class: 'background-text'});
|
||||
this.$backgroundText.text(EMPTY_MSG);
|
||||
this.$el.append(this.$backgroundText);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.openPipeline = function (event) {
|
||||
var target = event.target,
|
||||
indexOf = Array.prototype.indexOf,
|
||||
id;
|
||||
|
||||
while (!target.classList || indexOf.call(target.classList, 'pipeline') === -1) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
id = target.getAttribute('data-id');
|
||||
WebGMEGlobal.State.registerActiveObject(id);
|
||||
};
|
||||
|
||||
// Adding/Removing/Updating items
|
||||
PipelineIndexWidget.prototype.addNode = function (desc) {
|
||||
var node;
|
||||
|
||||
if (desc) {
|
||||
// Add node to a table of cards
|
||||
this.nodes[desc.id] = desc;
|
||||
node = $(PipelineTemplate(desc));
|
||||
this.cards[desc.id] = node;
|
||||
|
||||
// Add click listeners
|
||||
this.$el.append(node);
|
||||
|
||||
// Add the thumbnail
|
||||
if (desc.thumbnail) {
|
||||
this.addThumbnail(desc.thumbnail, node);
|
||||
}
|
||||
this.updateBackgroundText();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.addThumbnail = function (thumbnail, node) {
|
||||
var container = node.find('.preview'),
|
||||
svg = $(thumbnail);
|
||||
|
||||
// scale and shift the thumbnail
|
||||
svg.attr('width', 150)
|
||||
.attr('height', 150);
|
||||
|
||||
container.empty();
|
||||
container.append(svg);
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.removeNode = function (gmeId) {
|
||||
var html = this.cards[gmeId];
|
||||
if (html) {
|
||||
html.remove();
|
||||
delete this.cards[gmeId];
|
||||
this.updateBackgroundText();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.updateNode = function (desc) {
|
||||
if (desc && this.cards[desc.id]) {
|
||||
this.cards[desc.id].outerHTML = PipelineTemplate(desc);
|
||||
// Check if the preview changed
|
||||
if (desc.thumbnail !== this.nodes[desc.id].thumbnail) {
|
||||
this.addThumbnail(desc.thumbnail, this.cards[desc.id]);
|
||||
}
|
||||
this.nodes[desc.id] = desc;
|
||||
}
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
PipelineIndexWidget.prototype.destroy = function () {
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.onActivate = function () {
|
||||
this._logger.debug('PipelineIndexWidget has been activated');
|
||||
};
|
||||
|
||||
PipelineIndexWidget.prototype.onDeactivate = function () {
|
||||
this._logger.debug('PipelineIndexWidget has been deactivated');
|
||||
};
|
||||
|
||||
return PipelineIndexWidget;
|
||||
});
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file is for any scss that you may want for this visualizer.
|
||||
*/
|
||||
|
||||
.pipeline-index {
|
||||
outline: none;
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed Jun 01 2016 14:44:21 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/TextEditor/TextEditorWidget',
|
||||
'underscore',
|
||||
@@ -20,11 +16,13 @@ define([
|
||||
|
||||
SerializeEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
this._name = null;
|
||||
};
|
||||
|
||||
_.extend(SerializeEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
|
||||
SerializeEditorWidget.prototype.getHeader = function(desc) {
|
||||
this._name = desc.name;
|
||||
return [
|
||||
`-- The serialization function for ${desc.name}`,
|
||||
'-- Globals:',
|
||||
@@ -33,8 +31,36 @@ define([
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
SerializeEditorWidget.prototype.updateNode = function() {
|
||||
// nop
|
||||
SerializeEditorWidget.prototype.getNameRegex = function () {
|
||||
return /The serialization function for (.*)/;
|
||||
};
|
||||
|
||||
SerializeEditorWidget.prototype.getName = function () {
|
||||
var text = this.editor.getValue(),
|
||||
r = this.getNameRegex(),
|
||||
match = text.match(r);
|
||||
|
||||
return match && match[1].replace(/\s+$/, '');
|
||||
};
|
||||
|
||||
SerializeEditorWidget.prototype.saveText = function () {
|
||||
var name = this.getName();
|
||||
|
||||
if (this.readOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name && this._name !== name) {
|
||||
this.setName(name);
|
||||
}
|
||||
TextEditorWidget.prototype.saveText.call(this);
|
||||
};
|
||||
|
||||
SerializeEditorWidget.prototype.updateNode = function(desc) {
|
||||
if (this._name !== desc.name) {
|
||||
// Check if the name updated. If so, update the text
|
||||
this.addNode(desc);
|
||||
}
|
||||
};
|
||||
|
||||
return SerializeEditorWidget;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe('GenerateCriterion', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
logger = testFixture.logger.fork('GenerateCriterion'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'GenerateCriterion',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should run plugin and update the branch', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/1',
|
||||
};
|
||||
|
||||
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
|
||||
expect(err).to.equal(null);
|
||||
expect(typeof pluginResult).to.equal('object');
|
||||
expect(pluginResult.success).to.equal(true);
|
||||
|
||||
project.getBranchHash('test')
|
||||
.then(function (branchHash) {
|
||||
expect(branchHash).to.equal(commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
-- Copy of googlenet.lua which uses setters (the other googlenet has them removed)
|
||||
require 'nn'
|
||||
nGPU = 10
|
||||
local function inception(input_size, config)
|
||||
local concat = nn.Concat(2)
|
||||
if config[1][1] ~= 0 then
|
||||
local conv1 = nn.Sequential()
|
||||
conv1:add(nn.SpatialConvolution(input_size, config[1][1],1,1,1,1)):add(nn.ReLU(true))
|
||||
concat:add(conv1)
|
||||
end
|
||||
|
||||
local conv3 = nn.Sequential()
|
||||
conv3:add(nn.SpatialConvolution( input_size, config[2][1],1,1,1,1)):add(nn.ReLU(true))
|
||||
conv3:add(nn.SpatialConvolution(config[2][1], config[2][2],3,3,1,1,1,1)):add(nn.ReLU(true))
|
||||
concat:add(conv3)
|
||||
|
||||
local conv3xx = nn.Sequential()
|
||||
conv3xx:add(nn.SpatialConvolution( input_size, config[3][1],1,1,1,1)):add(nn.ReLU(true))
|
||||
conv3xx:add(nn.SpatialConvolution(config[3][1], config[3][2],3,3,1,1,1,1)):add(nn.ReLU(true))
|
||||
conv3xx:add(nn.SpatialConvolution(config[3][2], config[3][2],3,3,1,1,1,1)):add(nn.ReLU(true))
|
||||
concat:add(conv3xx)
|
||||
|
||||
local pool = nn.Sequential()
|
||||
pool:add(nn.SpatialZeroPadding(1,1,1,1)) -- remove after getting nn R2 into fbcode
|
||||
if config[4][1] == 'max' then
|
||||
pool:add(nn.SpatialMaxPooling(3,3,1,1):ceil())
|
||||
elseif config[4][1] == 'avg' then
|
||||
pool:add(nn.SpatialAveragePooling(3,3,1,1):ceil())
|
||||
else
|
||||
error('Unknown pooling')
|
||||
end
|
||||
if config[4][2] ~= 0 then
|
||||
pool:add(nn.SpatialConvolution(input_size, config[4][2],1,1,1,1)):add(nn.ReLU(true))
|
||||
end
|
||||
concat:add(pool)
|
||||
|
||||
return concat
|
||||
end
|
||||
|
||||
local features = nn.Sequential()
|
||||
features:add(nn.SpatialConvolution(3,64,7,7,2,2,3,3)):add(nn.ReLU(true))
|
||||
features:add(nn.SpatialMaxPooling(3,3,2,2):ceil())
|
||||
features:add(nn.SpatialConvolution(64,64,1,1)):add(nn.ReLU(true))
|
||||
features:add(nn.SpatialConvolution(64,192,3,3,1,1,1,1)):add(nn.ReLU(true))
|
||||
features:add(nn.SpatialMaxPooling(3,3,2,2):ceil())
|
||||
features:add(inception( 192, {{ 64},{ 64, 64},{ 64, 96},{'avg', 32}})) -- 3(a)
|
||||
features:add(inception( 256, {{ 64},{ 64, 96},{ 64, 96},{'avg', 64}})) -- 3(b)
|
||||
features:add(inception( 320, {{ 0},{128,160},{ 64, 96},{'max', 0}})) -- 3(c)
|
||||
features:add(nn.SpatialConvolution(576,576,2,2,2,2))
|
||||
features:add(inception( 576, {{224},{ 64, 96},{ 96,128},{'avg',128}})) -- 4(a)
|
||||
features:add(inception( 576, {{192},{ 96,128},{ 96,128},{'avg',128}})) -- 4(b)
|
||||
features:add(inception( 576, {{160},{128,160},{128,160},{'avg', 96}})) -- 4(c)
|
||||
features:add(inception( 576, {{ 96},{128,192},{160,192},{'avg', 96}})) -- 4(d)
|
||||
|
||||
local main_branch = nn.Sequential()
|
||||
main_branch:add(inception( 576, {{ 0},{128,192},{192,256},{'max', 0}})) -- 4(e)
|
||||
main_branch:add(nn.SpatialConvolution(1024,1024,2,2,2,2))
|
||||
main_branch:add(inception(1024, {{352},{192,320},{160,224},{'avg',128}})) -- 5(a)
|
||||
main_branch:add(inception(1024, {{352},{192,320},{192,224},{'max',128}})) -- 5(b)
|
||||
main_branch:add(nn.SpatialAveragePooling(7,7,1,1))
|
||||
main_branch:add(nn.View(1024):setNumInputDims(3))
|
||||
main_branch:add(nn.Linear(1024,nClasses))
|
||||
main_branch:add(nn.LogSoftMax())
|
||||
|
||||
-- add auxillary classifier here (thanks to Christian Szegedy for the details)
|
||||
local aux_classifier = nn.Sequential()
|
||||
aux_classifier:add(nn.SpatialAveragePooling(5,5,3,3):ceil())
|
||||
aux_classifier:add(nn.SpatialConvolution(576,128,1,1,1,1))
|
||||
aux_classifier:add(nn.View(128*4*4):setNumInputDims(3))
|
||||
aux_classifier:add(nn.Linear(128*4*4,768))
|
||||
aux_classifier:add(nn.ReLU())
|
||||
aux_classifier:add(nn.Linear(768,nClasses))
|
||||
aux_classifier:add(nn.LogSoftMax())
|
||||
|
||||
local splitter = nn.Concat(2)
|
||||
splitter:add(main_branch):add(aux_classifier)
|
||||
local model = nn.Sequential():add(features):add(splitter)
|
||||
|
||||
model.imageSize = 256
|
||||
model.imageCrop = 224
|
||||
|
||||
|
||||
return model
|
||||
+18
-3
@@ -36,6 +36,10 @@
|
||||
"ImportArtifact": {
|
||||
"src": "src/plugins/ImportArtifact",
|
||||
"test": "test/plugins/ImportArtifact"
|
||||
},
|
||||
"GenerateCriterion": {
|
||||
"src": "src/plugins/GenerateCriterion",
|
||||
"test": "test/plugins/GenerateCriterion"
|
||||
}
|
||||
},
|
||||
"layouts": {},
|
||||
@@ -165,6 +169,20 @@
|
||||
"panel": "src/visualizers/panels/ClassEditor",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/ClassEditor"
|
||||
},
|
||||
"PipelineIndex": {
|
||||
"src": "panels/PipelineIndex/PipelineIndexPanel",
|
||||
"title": "PipelineIndex",
|
||||
"panel": "src/visualizers/panels/PipelineIndex",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/PipelineIndex"
|
||||
},
|
||||
"MainView": {
|
||||
"src": "panels/MainView/MainViewPanel",
|
||||
"title": "MainView",
|
||||
"panel": "src/visualizers/panels/MainView",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/MainView"
|
||||
}
|
||||
},
|
||||
"addons": {},
|
||||
@@ -204,9 +222,6 @@
|
||||
"devPipelineTests": {
|
||||
"src": "src/seeds/devPipelineTests"
|
||||
},
|
||||
"demo": {
|
||||
"src": "src/seeds/demo"
|
||||
},
|
||||
"project": {
|
||||
"src": "src/seeds/project"
|
||||
},
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário