Comparar commits
55 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 0207e73f6a | |||
| d5ec893264 | |||
| c0c36e8774 | |||
| 3ea0099347 | |||
| 8ab026c5aa | |||
| 8e07b4de97 | |||
| 949100545d | |||
| f37ed09777 | |||
| 0bcc0981dc | |||
| 649df26bd4 | |||
| 970822ffee | |||
| 025728729c | |||
| c7d29110b5 | |||
| 0774c11ec2 | |||
| 6cc7565e97 | |||
| 90964afa23 | |||
| 12439b15b9 | |||
| 317f033997 | |||
| 716b4aacff | |||
| 6f8612233f | |||
| e5acb09206 | |||
| d8fac840b0 | |||
| 9bce45a786 | |||
| b8a82cf0fc | |||
| 5090df8358 | |||
| 6ca72a5b83 | |||
| 3a8454b582 | |||
| e25d376080 | |||
| b7a823cf37 | |||
| 504fe4652a | |||
| b8021f467c | |||
| 4d49036e81 | |||
| d738a54cb2 | |||
| c2213d216b | |||
| fd9d728b1e | |||
| 32a3802244 | |||
| c61009b67f | |||
| bb3ce453c4 | |||
| c9fb8fe855 | |||
| 814995214f | |||
| c993c1784b | |||
| 788abb1512 | |||
| 13f7f470e0 | |||
| a835c02e52 | |||
| c46d70ebe2 | |||
| e7d554578d | |||
| 289277aaf0 | |||
| 0671b7ade6 | |||
| f6da8485b5 | |||
| cbd31c51d2 | |||
| 9508351c54 | |||
| 6a7f22bd3e | |||
| 3c06fd6289 | |||
| e31206658d | |||
| 68f46eb5d2 |
@@ -0,0 +1,4 @@
|
||||
src/common/lua.js
|
||||
src/visualizers/widgets/TextEditor/lib/*
|
||||
src/common/js-yaml.min.js
|
||||
src/visualizers/Visualizers.json
|
||||
@@ -0,0 +1,18 @@
|
||||
env:
|
||||
browser: true
|
||||
mocha: true
|
||||
es6: true
|
||||
extends: 'eslint:recommended'
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
linebreak-style:
|
||||
- error
|
||||
- unix
|
||||
quotes:
|
||||
- error
|
||||
- single
|
||||
semi:
|
||||
- error
|
||||
- always
|
||||
@@ -0,0 +1 @@
|
||||
*.webgmex filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -1,6 +1,8 @@
|
||||
src/worker/tmp
|
||||
.env
|
||||
*.swp
|
||||
*.swo
|
||||
**.sass-cache
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
@@ -29,4 +31,5 @@ build/Release
|
||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||
node_modules
|
||||
tmp/
|
||||
test-tmp/
|
||||
blob-local-storage/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"esversion": 6
|
||||
}
|
||||
+7
-3
@@ -8,6 +8,10 @@ var gmeConfig = require('./config'),
|
||||
webgme.addToRequireJsPaths(gmeConfig);
|
||||
|
||||
myServer = new webgme.standaloneServer(gmeConfig);
|
||||
myServer.start(function () {
|
||||
//console.log('server up');
|
||||
});
|
||||
myServer.start(function (err) {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('DeepForge now listening on port', gmeConfig.server.port);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Run `npm start` and listen for 'DeepForge' then start worker
|
||||
var spawn = require('child_process').spawn,
|
||||
stdout = '',
|
||||
execJob,
|
||||
workerJob = null;
|
||||
|
||||
execJob = spawn('npm', [
|
||||
'start'
|
||||
]);
|
||||
execJob.stdout.pipe(process.stdout);
|
||||
execJob.stderr.pipe(process.stderr);
|
||||
|
||||
execJob.stdout.on('data', function(chunk) {
|
||||
if (!workerJob) {
|
||||
stdout += chunk;
|
||||
if (stdout.indexOf('DeepForge') > -1) {
|
||||
workerJob = spawn('npm', ['run', 'worker']);
|
||||
workerJob.stdout.pipe(process.stdout);
|
||||
workerJob.stderr.pipe(process.stderr);
|
||||
workerJob.on('close', code => code && process.exit(code));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
execJob.on('close', code => code && process.exit(code));
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ArchEditor": {
|
||||
"hotkeys": "none",
|
||||
"LayerColors": {}
|
||||
"LayerColors": {}
|
||||
},
|
||||
"CHFLayout": {
|
||||
"panels": [
|
||||
@@ -31,5 +31,33 @@
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
"RootViz": {
|
||||
"nodes": [
|
||||
{
|
||||
"nodeName": "MyArchitectures",
|
||||
"description": "Neural network architectures are stored here and can be used in pipelines."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyExecutions",
|
||||
"description": "Executions are read-only snapshots of pipelines that have been executed. Past and current executing pipelines are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyPipelines",
|
||||
"description": "Pipelines are used for training, testing and ensembling models."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyOperations",
|
||||
"description": "Operations are the building blocks of pipelines. Custom operations can be created and stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyArtifacts",
|
||||
"description": "Artifacts from pipeline executions are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyDataTypes",
|
||||
"description": "Custom defined data types are stored here."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
/*globals require, module, process*/
|
||||
'use strict';
|
||||
|
||||
var config = require('./config.webgme'),
|
||||
validateConfig = require('webgme/config/validator');
|
||||
|
||||
require('dotenv').load();
|
||||
// Add/overwrite any additional settings here
|
||||
// config.server.port = 8080;
|
||||
// config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme_my_app';
|
||||
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 = 'nn';
|
||||
config.seedProjects.defaultProject = 'project';
|
||||
|
||||
config.plugin.allowBrowserExecution = true;
|
||||
config.plugin.allowServerExecution = true;
|
||||
|
||||
config.executor.enable = true;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ var config = require('webgme/config/config.default'),
|
||||
config.plugin.basePaths.push('src/plugins');
|
||||
config.plugin.basePaths.push('node_modules/webgme-simple-nodes/src/plugins');
|
||||
config.visualization.layout.basePaths.push('node_modules/webgme-chflayout/src/layouts');
|
||||
config.visualization.decoratorPaths.push('src/decorators');
|
||||
config.visualization.decoratorPaths.push('node_modules/webgme-easydag/src/decorators');
|
||||
config.seedProjects.basePaths.push('src/seeds/nn');
|
||||
config.seedProjects.basePaths.push('src/seeds/devTests');
|
||||
@@ -19,6 +20,7 @@ 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');
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-3
@@ -4,17 +4,19 @@
|
||||
"start": "node app.js",
|
||||
"start-dev": "NODE_ENV=dev node app.js",
|
||||
"worker": "node ./bin/start-worker.js",
|
||||
"local": "node ./bin/start-local.js",
|
||||
"test": "node ./node_modules/mocha/bin/mocha --recursive test"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"version": "0.4.0",
|
||||
"dependencies": {
|
||||
"dotenv": "^2.0.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"webgme": "^2.0.0",
|
||||
"webgme-autoviz": "^2.0.0",
|
||||
"webgme-autoviz": "^2.0.3",
|
||||
"webgme-breadcrumbheader": "^2.0.0",
|
||||
"webgme-chflayout": "^2.0.0",
|
||||
"webgme-easydag": "dfst/webgme-easydag",
|
||||
"webgme-fab": "^2.0.0",
|
||||
"webgme-fab": "^2.0.2",
|
||||
"webgme-simple-nodes": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* globals define */
|
||||
define([
|
||||
'deepforge/js-yaml.min'
|
||||
], function(
|
||||
@@ -148,28 +149,11 @@ define([
|
||||
|
||||
GraphChecker.prototype = new Importer();
|
||||
|
||||
// Check if two models are isomorphic
|
||||
var modelMatches = function(gmeNodes, text) {
|
||||
var nodes = convertNodes(gmeNodes),
|
||||
soln = yaml.load(text);
|
||||
|
||||
nodes.concat(soln).forEach(node => {
|
||||
node.next = node.next || [];
|
||||
node.attributes = node.attributes || {};
|
||||
});
|
||||
|
||||
return _modelMatches(nodes, soln);
|
||||
};
|
||||
|
||||
//////////////// Operators ////////////////
|
||||
// Check if two models are isomorphic
|
||||
var _modelMatches = function(soln, nodes) {
|
||||
var nodeMap = createMap(nodes),
|
||||
solnMap = createMap(soln),
|
||||
sInits, // soln start nodes
|
||||
nInits, // 'nodes' start nodes
|
||||
resMap = {}, // soln node id to node id
|
||||
solnIds = soln.map(n => n.id),
|
||||
nodeIds = nodes.map(n => n.id);
|
||||
solnMap = createMap(soln);
|
||||
|
||||
if (nodes.length !== soln.length) {
|
||||
return false;
|
||||
@@ -187,8 +171,7 @@ define([
|
||||
};
|
||||
|
||||
var getMostConstrained = function(soln, nodes) {
|
||||
var options = soln.map(sn => [sn, nodes.filter(n => nodesMatch(sn, n))]),
|
||||
startId;
|
||||
var options = soln.map(sn => [sn, nodes.filter(n => nodesMatch(sn, n))]);
|
||||
|
||||
options.sort((a, b) => b[1].length < a[1].length);
|
||||
return options[0];
|
||||
@@ -199,8 +182,7 @@ define([
|
||||
nodes = Object.keys(nodeMap).map(id => nodeMap[id]),
|
||||
snode = solnMap[id],
|
||||
options,
|
||||
used,
|
||||
node;
|
||||
used;
|
||||
|
||||
mappings = mappings || {};
|
||||
|
||||
@@ -247,14 +229,16 @@ define([
|
||||
snext.push(startId);
|
||||
}
|
||||
|
||||
var inferNext = (prev, curr) => {
|
||||
mappings2 = inferGraph(curr, solnMap, nodeMap, mappings2);
|
||||
return prev && mappings;
|
||||
};
|
||||
|
||||
for (var i = options.length; i--;) {
|
||||
mappings[id] = options[i].id; // need to clone the object
|
||||
|
||||
mappings2 = clone(mappings);
|
||||
result = snext.reduce((prev, curr) => {
|
||||
mappings2 = inferGraph(curr, solnMap, nodeMap, mappings2);
|
||||
return prev && mappings;
|
||||
}, true);
|
||||
result = snext.reduce(inferNext, true);
|
||||
|
||||
if (result) {
|
||||
return mappings2;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* globals define*/
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
@@ -25,7 +26,6 @@ define([
|
||||
var createLayerDict = function(core, meta) {
|
||||
var node,
|
||||
names = Object.keys(meta),
|
||||
attributes,
|
||||
layers = {};
|
||||
|
||||
for (var i = names.length; i--;) {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* globals define */
|
||||
// A mixin containing helpers for working with operations
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
'use strict';
|
||||
var OperationControl = function() {
|
||||
};
|
||||
|
||||
OperationControl.prototype.hasMetaName = function(id, name) {
|
||||
var node = this._client.getNode(id),
|
||||
bId = node.getBaseId(),
|
||||
baseName;
|
||||
|
||||
while (bId) {
|
||||
node = this._client.getNode(bId);
|
||||
baseName = node.getAttribute('name');
|
||||
if (baseName === name) {
|
||||
return true;
|
||||
}
|
||||
bId = node.getBaseId();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
OperationControl.prototype.getOperationInputs = function(node) {
|
||||
return this.getOperationData(node, 'Inputs');
|
||||
};
|
||||
|
||||
OperationControl.prototype.getOperationOutputs = function(node) {
|
||||
return this.getOperationData(node, 'Outputs');
|
||||
};
|
||||
|
||||
OperationControl.prototype.getOperationData = function(node, type) {
|
||||
var childrenIds = node.getChildrenIds(),
|
||||
typeId = childrenIds.find(cId => this.hasMetaName(cId, type));
|
||||
|
||||
return typeId ? this._client.getNode(typeId).getChildrenIds() : [];
|
||||
};
|
||||
|
||||
return OperationControl;
|
||||
});
|
||||
@@ -0,0 +1,141 @@
|
||||
/* globals define */
|
||||
// Shared methods for editing pipelines
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/OperationControl',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGControl,
|
||||
OperationControl,
|
||||
AddNodeDialog,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var PipelineControl = function() {
|
||||
};
|
||||
|
||||
_.extend(PipelineControl.prototype, OperationControl.prototype);
|
||||
|
||||
PipelineControl.prototype.DEFAULT_DECORATOR = 'OperationDecorator';
|
||||
|
||||
PipelineControl.prototype._getAllDescendentIds =
|
||||
EasyDAGControl.prototype._getAllDescendentIds;
|
||||
PipelineControl.prototype._getAllValidChildren =
|
||||
EasyDAGControl.prototype._getAllValidChildren;
|
||||
PipelineControl.prototype._getNodeDecorator =
|
||||
EasyDAGControl.prototype._getNodeDecorator;
|
||||
|
||||
PipelineControl.prototype.onCreateInitialNode = function() {
|
||||
var initialNodes = this.getValidInitialNodes(),
|
||||
initialNode = initialNodes[0];
|
||||
|
||||
if (initialNodes.length > 1) {
|
||||
// Create the modal view with all possible subsequent nodes
|
||||
var dialog = new AddNodeDialog();
|
||||
|
||||
dialog.show(null, initialNodes.map(node => {
|
||||
return {node};
|
||||
}));
|
||||
dialog.onSelect = nodeInfo => {
|
||||
if (nodeInfo) {
|
||||
this.createNode(nodeInfo.node.id);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
this.createNode(initialNode.id);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineControl.prototype.getValidInitialNodes = function () {
|
||||
// Get all nodes that have no inputs
|
||||
return this._getAllValidChildren(this._currentNodeId)
|
||||
.map(id => this._client.getNode(id))
|
||||
.filter(node => !node.isAbstract() && !node.isConnection())
|
||||
// Checking the name (below) is simply convenience so we can
|
||||
// still create operation prototypes from Operation (which we
|
||||
// wouldn't be able to do if it was abstract - which it probably
|
||||
// should be)
|
||||
.filter(node => node.getAttribute('name') !== 'Operation')
|
||||
.map(node => this._getObjectDescriptor(node.getId()));
|
||||
};
|
||||
|
||||
PipelineControl.prototype.createNode = function(baseId) {
|
||||
var parentId = this._currentNodeId,
|
||||
newNodeId = this._client.createChild({parentId, baseId});
|
||||
|
||||
return newNodeId;
|
||||
};
|
||||
|
||||
PipelineControl.prototype._getObjectDescriptor = function(id) {
|
||||
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id),
|
||||
node = this._client.getNode(id);
|
||||
|
||||
if (this.hasMetaName(id, 'Operation')) {
|
||||
// Only decorate operations in the currently active node
|
||||
if (this._currentNodeId !== desc.parentId) {
|
||||
return desc;
|
||||
}
|
||||
|
||||
// Add inputs and outputs
|
||||
var childrenIds = node.getChildrenIds(),
|
||||
inputId = childrenIds.find(cId => this.hasMetaName(cId, 'Inputs')),
|
||||
outputId = childrenIds.find(cId => this.hasMetaName(cId, 'Outputs')),
|
||||
inputs,
|
||||
outputs;
|
||||
|
||||
inputs = inputId ? this._client.getNode(inputId).getChildrenIds() : [];
|
||||
outputs = outputId ? this._client.getNode(outputId).getChildrenIds() : [];
|
||||
|
||||
// Add the inputs, outputs in the form:
|
||||
// [ name, baseId ]
|
||||
desc.inputs = inputs.map(id => this.formatIO(id));
|
||||
desc.outputs = outputs.map(id => this.formatIO(id));
|
||||
|
||||
// Remove the 'code' attribute
|
||||
if (desc.attributes.code) {
|
||||
delete desc.attributes.code;
|
||||
}
|
||||
|
||||
} else if (desc.isConnection) {
|
||||
// Set src, dst to siblings and add srcPort, dstPort
|
||||
desc.srcPort = desc.src;
|
||||
desc.dstPort = desc.dst;
|
||||
|
||||
// Get the src/dst that are in the currentNode
|
||||
desc.src = this.getSiblingContaining(desc.src);
|
||||
desc.dst = this.getSiblingContaining(desc.dst);
|
||||
|
||||
if (desc.src === null || desc.dst === null) {
|
||||
this._logger.warn(`Could not get src/dst for ${desc.id}`);
|
||||
}
|
||||
} else if (this.hasMetaName(desc.id, 'Data')) { // port
|
||||
// Add nodeId for container
|
||||
desc.nodeId = this.getSiblingContaining(desc.id);
|
||||
// It is a data port if it has a parentId and the parent is either
|
||||
// 'Inputs' or 'Outputs'
|
||||
desc.isDataPort = desc.parentId &&
|
||||
(this.hasMetaName(desc.parentId, 'Inputs') || this.hasMetaName(desc.parentId, 'Outputs'));
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
PipelineControl.prototype.getSiblingContaining = function(containedId) {
|
||||
var n = this._client.getNode(containedId);
|
||||
while (n && n.getParentId() !== this._currentNodeId) {
|
||||
n = this._client.getNode(n.getParentId());
|
||||
}
|
||||
return n && n.getId();
|
||||
};
|
||||
|
||||
PipelineControl.prototype.formatIO = function(id) {
|
||||
var node = this._client.getNode(id);
|
||||
return {
|
||||
id: id,
|
||||
name: node.getAttribute('name')
|
||||
};
|
||||
};
|
||||
|
||||
return PipelineControl;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
.job-decorator {
|
||||
min-width: 65px;
|
||||
height: 40px;
|
||||
border: 1px solid black;
|
||||
background-color: #dedede;
|
||||
padding: 3px;
|
||||
text-align: center; }
|
||||
.job-decorator .attr-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.job-decorator .name {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-align: center; }
|
||||
.job-decorator .connector {
|
||||
background-color: #fefefe;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
border: 1px solid blue;
|
||||
z-index: 10;
|
||||
margin-left: -6px;
|
||||
left: 50%; }
|
||||
.job-decorator .connector:hover {
|
||||
border-color: rgba(82, 168, 236, 0.8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); }
|
||||
.job-decorator .connector.top {
|
||||
top: -6px; }
|
||||
.job-decorator .connector.bottom {
|
||||
bottom: -6px; }
|
||||
|
||||
.selected .job-decorator {
|
||||
border: 1px solid #52a8ec;
|
||||
background-color: #dbeafc; }
|
||||
@@ -0,0 +1,52 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'css!./JobDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
EllipseDecorator
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var JobDecorator,
|
||||
DECORATOR_ID = 'JobDecorator',
|
||||
COLORS = {
|
||||
pending: '#9e9e9e',
|
||||
running: '#fff59d',
|
||||
success: '#66bb6a',
|
||||
fail: '#e57373'
|
||||
};
|
||||
|
||||
// Job nodes need to be able to...
|
||||
// - show their ports
|
||||
// - highlight ports
|
||||
// - unhighlight ports
|
||||
// - report the location of specific ports
|
||||
JobDecorator = function (options) {
|
||||
EllipseDecorator.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(JobDecorator.prototype, EllipseDecorator.prototype);
|
||||
|
||||
JobDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
|
||||
JobDecorator.prototype.getDisplayName = function() {
|
||||
return this._node.name;
|
||||
};
|
||||
|
||||
JobDecorator.prototype.setAttributes = function() {
|
||||
EllipseDecorator.prototype.setAttributes.call(this);
|
||||
var status = this._attributes.status && this._attributes.status.value;
|
||||
|
||||
// Update the color based on the 'status' attr
|
||||
this.color = COLORS[status] || COLORS.fail;
|
||||
};
|
||||
|
||||
return JobDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Decorators/DecoratorBase',
|
||||
'./EasyDAG/JobDecorator.EasyDAGWidget'
|
||||
], function (
|
||||
DecoratorBase,
|
||||
JobDecoratorEasyDAGWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var JobDecorator,
|
||||
__parent__ = DecoratorBase,
|
||||
__parent_proto__ = DecoratorBase.prototype,
|
||||
DECORATOR_ID = 'JobDecorator';
|
||||
|
||||
JobDecorator = function (params) {
|
||||
var opts = _.extend({loggerName: this.DECORATORID}, params);
|
||||
|
||||
__parent__.apply(this, [opts]);
|
||||
|
||||
this.logger.debug('JobDecorator ctor');
|
||||
};
|
||||
|
||||
_.extend(JobDecorator.prototype, __parent_proto__);
|
||||
JobDecorator.prototype.DECORATORID = DECORATOR_ID;
|
||||
|
||||
/*********************** OVERRIDE DecoratorBase MEMBERS **************************/
|
||||
|
||||
JobDecorator.prototype.initializeSupportedWidgetMap = function () {
|
||||
this.supportedWidgetMap = {
|
||||
EasyDAG: JobDecoratorEasyDAGWidget
|
||||
};
|
||||
};
|
||||
|
||||
return JobDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
.op-int-decorator {
|
||||
min-width: 65px;
|
||||
height: 40px;
|
||||
border: 1px solid black;
|
||||
background-color: #dedede;
|
||||
padding: 3px;
|
||||
text-align: center; }
|
||||
.op-int-decorator .attr-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.op-int-decorator .name {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-align: center; }
|
||||
.op-int-decorator .connector {
|
||||
background-color: #fefefe;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
border: 1px solid blue;
|
||||
z-index: 10;
|
||||
margin-left: -6px;
|
||||
left: 50%; }
|
||||
.op-int-decorator .connector:hover {
|
||||
border-color: rgba(82, 168, 236, 0.8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); }
|
||||
.op-int-decorator .connector.top {
|
||||
top: -6px; }
|
||||
.op-int-decorator .connector.bottom {
|
||||
bottom: -6px; }
|
||||
|
||||
.selected .op-int-decorator {
|
||||
border: 1px solid #52a8ec;
|
||||
background-color: #dbeafc; }
|
||||
@@ -0,0 +1,90 @@
|
||||
/*globals define, $,_*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'css!./OpIntDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
DecoratorBase
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
_.extend(OpIntDecorator.prototype, DecoratorBase.prototype);
|
||||
|
||||
OpIntDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
OpIntDecorator.prototype.initialize = function() {
|
||||
if (this._node.baseName === 'Operation') {
|
||||
this.color = '#2196f3';
|
||||
} else {
|
||||
// On hover, show the type
|
||||
this.enableTooltip(this._node.baseName, 'dark');
|
||||
}
|
||||
DecoratorBase.prototype.initialize.call(this);
|
||||
this.$name.on('dblclick', this.editName.bind(this));
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.editName = function() {
|
||||
var html = this.$name[0][0],
|
||||
position = html.getBoundingClientRect(),
|
||||
|
||||
width = Math.max(position.right-position.left, 15),
|
||||
container = $('<div>'),
|
||||
parentHtml = $('body');
|
||||
|
||||
// foreignObject was not working so we are using a tmp container
|
||||
// instead
|
||||
container.css('top', position.top);
|
||||
container.css('left', position.left);
|
||||
container.css('position', 'absolute');
|
||||
container.css('width', width);
|
||||
container.attr('id', 'CONTAINER-TMP');
|
||||
|
||||
$(parentHtml).append(container);
|
||||
|
||||
container.editInPlace({
|
||||
enableEmpty: true,
|
||||
value: this.name,
|
||||
css: {
|
||||
'z-index': 10000,
|
||||
'id': 'asdf',
|
||||
'width': width,
|
||||
'xmlns': 'http://www.w3.org/1999/xhtml'
|
||||
},
|
||||
onChange: this.onNameChanged.bind(this),
|
||||
onFinish: function () {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.onNameChanged = function(oldVal, newValue) {
|
||||
this.saveAttribute('name', newValue);
|
||||
};
|
||||
|
||||
OpIntDecorator.prototype.getDisplayName = function() {
|
||||
return this._node.name;
|
||||
};
|
||||
|
||||
// clicking on the name should allow the user to edit it in place
|
||||
// TODO
|
||||
|
||||
return OpIntDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Decorators/DecoratorBase',
|
||||
'./EasyDAG/OpIntDecorator.EasyDAGWidget'
|
||||
], function (
|
||||
DecoratorBase,
|
||||
OpIntDecoratorEasyDAGWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OpIntDecorator,
|
||||
__parent__ = DecoratorBase,
|
||||
__parent_proto__ = DecoratorBase.prototype,
|
||||
DECORATOR_ID = 'OpIntDecorator';
|
||||
|
||||
OpIntDecorator = function (params) {
|
||||
var opts = _.extend({loggerName: this.DECORATORID}, params);
|
||||
|
||||
__parent__.apply(this, [opts]);
|
||||
|
||||
this.logger.debug('OpIntDecorator ctor');
|
||||
};
|
||||
|
||||
_.extend(OpIntDecorator.prototype, __parent_proto__);
|
||||
OpIntDecorator.prototype.DECORATORID = DECORATOR_ID;
|
||||
|
||||
/*********************** OVERRIDE DecoratorBase MEMBERS **************************/
|
||||
|
||||
OpIntDecorator.prototype.initializeSupportedWidgetMap = function () {
|
||||
this.supportedWidgetMap = {
|
||||
EasyDAG: OpIntDecoratorEasyDAGWidget
|
||||
};
|
||||
};
|
||||
|
||||
return OpIntDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
.op-int-decorator {
|
||||
min-width: 65px;
|
||||
height: 40px;
|
||||
border: 1px solid black;
|
||||
background-color: #dedede;
|
||||
padding: 3px;
|
||||
text-align: center; }
|
||||
.op-int-decorator .attr-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.op-int-decorator .name {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-align: center; }
|
||||
.op-int-decorator .connector {
|
||||
background-color: #fefefe;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
border: 1px solid blue;
|
||||
z-index: 10;
|
||||
margin-left: -6px;
|
||||
left: 50%; }
|
||||
.op-int-decorator .connector:hover {
|
||||
border-color: rgba(82, 168, 236, 0.8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); }
|
||||
.op-int-decorator .connector.top {
|
||||
top: -6px; }
|
||||
.op-int-decorator .connector.bottom {
|
||||
bottom: -6px; }
|
||||
|
||||
.selected .op-int-decorator {
|
||||
border: 1px solid #52a8ec;
|
||||
background-color: #dbeafc; }
|
||||
@@ -0,0 +1,39 @@
|
||||
/*globals define, $,_*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/OpIntDecorator/EasyDAG/OpIntDecorator.EasyDAGWidget',
|
||||
'css!./OpIntPtrDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
DecoratorBase
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OpIntPtrDecorator,
|
||||
DECORATOR_ID = 'OpIntPtrDecorator';
|
||||
|
||||
// OpInt nodes need to be able to...
|
||||
// - show their ports
|
||||
// - highlight ports
|
||||
// - unhighlight ports
|
||||
// - report the location of specific ports
|
||||
OpIntPtrDecorator = function (options) {
|
||||
this.color = '#80deea';
|
||||
DecoratorBase.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(OpIntPtrDecorator.prototype, DecoratorBase.prototype);
|
||||
|
||||
OpIntPtrDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
|
||||
OpIntPtrDecorator.prototype.onNameChanged = function(old, newValue) {
|
||||
return this.changePtrName(this.name, newValue);
|
||||
};
|
||||
|
||||
return OpIntPtrDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Decorators/DecoratorBase',
|
||||
'./EasyDAG/OpIntPtrDecorator.EasyDAGWidget'
|
||||
], function (
|
||||
DecoratorBase,
|
||||
OpIntPtrDecoratorEasyDAGWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OpIntPtrDecorator,
|
||||
__parent__ = DecoratorBase,
|
||||
__parent_proto__ = DecoratorBase.prototype,
|
||||
DECORATOR_ID = 'OpIntPtrDecorator';
|
||||
|
||||
OpIntPtrDecorator = function (params) {
|
||||
var opts = _.extend({loggerName: this.DECORATORID}, params);
|
||||
|
||||
__parent__.apply(this, [opts]);
|
||||
|
||||
this.logger.debug('OpIntPtrDecorator ctor');
|
||||
};
|
||||
|
||||
_.extend(OpIntPtrDecorator.prototype, __parent_proto__);
|
||||
OpIntPtrDecorator.prototype.DECORATORID = DECORATOR_ID;
|
||||
|
||||
/*********************** OVERRIDE DecoratorBase MEMBERS **************************/
|
||||
|
||||
OpIntPtrDecorator.prototype.initializeSupportedWidgetMap = function () {
|
||||
this.supportedWidgetMap = {
|
||||
EasyDAG: OpIntPtrDecoratorEasyDAGWidget
|
||||
};
|
||||
};
|
||||
|
||||
return OpIntPtrDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
.operation-decorator {
|
||||
min-width: 65px;
|
||||
height: 40px;
|
||||
border: 1px solid black;
|
||||
background-color: #dedede;
|
||||
padding: 3px;
|
||||
text-align: center; }
|
||||
.operation-decorator .attr-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.operation-decorator .name {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-align: center; }
|
||||
.operation-decorator .connector {
|
||||
background-color: #fefefe;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
border: 1px solid blue;
|
||||
z-index: 10;
|
||||
margin-left: -6px;
|
||||
left: 50%; }
|
||||
.operation-decorator .connector:hover {
|
||||
border-color: rgba(82, 168, 236, 0.8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); }
|
||||
.operation-decorator .connector.top {
|
||||
top: -6px; }
|
||||
.operation-decorator .connector.bottom {
|
||||
bottom: -6px; }
|
||||
|
||||
.selected .operation-decorator {
|
||||
border: 1px solid #52a8ec;
|
||||
background-color: #dbeafc; }
|
||||
@@ -0,0 +1,157 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'css!./OperationDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
DecoratorBase
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OperationDecorator,
|
||||
NAME_MARGIN = 25,
|
||||
DECORATOR_ID = 'OperationDecorator';
|
||||
|
||||
// Operation nodes need to be able to...
|
||||
// - show their ports
|
||||
// - highlight ports
|
||||
// - unhighlight ports
|
||||
// - report the location of specific ports
|
||||
OperationDecorator = function (options) {
|
||||
options.color = options.color || '#78909c';
|
||||
DecoratorBase.call(this, options);
|
||||
|
||||
this.id = this._node.id;
|
||||
this.$ports = this.$el.append('g')
|
||||
.attr('id', 'ports');
|
||||
};
|
||||
|
||||
_.extend(OperationDecorator.prototype, DecoratorBase.prototype);
|
||||
|
||||
OperationDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
OperationDecorator.prototype.PORT_COLOR = {
|
||||
OPEN: '#90caf9',
|
||||
OCCUPIED: '#e57373'
|
||||
};
|
||||
|
||||
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(' ');
|
||||
|
||||
|
||||
this.$body
|
||||
.attr('d', path);
|
||||
|
||||
// Clear the attributes
|
||||
this.$attributes.remove();
|
||||
this.$attributes = this.$el.append('g')
|
||||
.attr('fill', '#222222');
|
||||
|
||||
this.height = this.dense.height;
|
||||
this.width = width;
|
||||
|
||||
this.$name.attr('y', this.height/2);
|
||||
|
||||
this.$el
|
||||
.attr('transform', `translate(${this.width/2}, 0)`);
|
||||
this.expanded = false;
|
||||
this.onResize();
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.showPorts = function(ids, areInputs) {
|
||||
var allPorts = areInputs ? this._node.inputs : this._node.outputs,
|
||||
ports = ids ? allPorts.filter(port => ids.indexOf(port.id) > -1) : allPorts,
|
||||
x = -this.width/2,
|
||||
dx = this.width/(ports.length+1),
|
||||
y = areInputs ? 0 : this.height; // (this.height/2);
|
||||
|
||||
ports.forEach(port => {
|
||||
x += dx;
|
||||
this.renderPort(port, x, y, areInputs);
|
||||
});
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.renderPort = function(port, x, y, isInput) {
|
||||
var color = this.PORT_COLOR.OPEN,
|
||||
portIcon = this.$ports.append('g');
|
||||
|
||||
// If the port is incoming and occupied, render it differently
|
||||
if (isInput && port.connection) {
|
||||
color = this.PORT_COLOR.OCCUPIED;
|
||||
}
|
||||
|
||||
portIcon.append('circle')
|
||||
.attr('cx', x)
|
||||
.attr('cy', y)
|
||||
.attr('r', 10)
|
||||
.attr('fill', color);
|
||||
|
||||
portIcon.append('text')
|
||||
.attr('x', x)
|
||||
.attr('y', y)
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dominant-baseline', 'middle')
|
||||
.attr('fill', 'black')
|
||||
.text(port.name[0]);
|
||||
|
||||
portIcon.on('click', this.onPortClick.bind(this, this.id, port.id, !isInput));
|
||||
|
||||
// Add tooltip with whole name
|
||||
// TODO
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.hidePorts = function() {
|
||||
this.logger.info(`hiding ports for ${this.name} (${this.id})`);
|
||||
this.$ports.remove();
|
||||
this.$ports = this.$el.append('g')
|
||||
.attr('id', 'ports');
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.getPortLocation = function(id, isInput) {
|
||||
// Report location of given port
|
||||
var ports = isInput ? this._node.inputs : this._node.outputs,
|
||||
i = ports.length-1,
|
||||
y;
|
||||
|
||||
while (i >= 0 && ports[i].id !== id) {
|
||||
i--;
|
||||
}
|
||||
if (i !== -1) {
|
||||
i += 1;
|
||||
y = (this.height/2);
|
||||
return {
|
||||
x: i * this.width/(ports.length+1),
|
||||
y: isInput ? y * -1 : y
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.onPortClick = function() {
|
||||
// Overridden in the widget
|
||||
};
|
||||
|
||||
OperationDecorator.prototype.getDisplayName = function() {
|
||||
return this._node.name;
|
||||
};
|
||||
|
||||
return OperationDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Decorators/DecoratorBase',
|
||||
'./EasyDAG/OperationDecorator.EasyDAGWidget'
|
||||
], function (
|
||||
DecoratorBase,
|
||||
OperationDecoratorEasyDAGWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OperationDecorator,
|
||||
__parent__ = DecoratorBase,
|
||||
__parent_proto__ = DecoratorBase.prototype,
|
||||
DECORATOR_ID = 'OperationDecorator';
|
||||
|
||||
OperationDecorator = function (params) {
|
||||
var opts = _.extend({loggerName: this.DECORATORID}, params);
|
||||
|
||||
__parent__.apply(this, [opts]);
|
||||
|
||||
this.logger.debug('OperationDecorator ctor');
|
||||
};
|
||||
|
||||
_.extend(OperationDecorator.prototype, __parent_proto__);
|
||||
OperationDecorator.prototype.DECORATORID = DECORATOR_ID;
|
||||
|
||||
/*********************** OVERRIDE DecoratorBase MEMBERS **************************/
|
||||
|
||||
OperationDecorator.prototype.initializeSupportedWidgetMap = function () {
|
||||
this.supportedWidgetMap = {
|
||||
EasyDAG: OperationDecoratorEasyDAGWidget
|
||||
};
|
||||
};
|
||||
|
||||
return OperationDecorator;
|
||||
});
|
||||
@@ -0,0 +1,213 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Mon May 23 2016 14:23:16 GMT-0500 (CDT).
|
||||
* A plugin that inherits from the PluginBase. To see source code documentation about available
|
||||
* properties and methods visit %host%/docs/source/PluginBase.html.
|
||||
*/
|
||||
|
||||
define([
|
||||
'q',
|
||||
'text!./metadata.json',
|
||||
'plugin/PluginBase'
|
||||
], function (
|
||||
Q,
|
||||
pluginMetadata,
|
||||
PluginBase
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of CreateExecution.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin CreateExecution.
|
||||
* @constructor
|
||||
*/
|
||||
var CreateExecution = 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}
|
||||
*/
|
||||
CreateExecution.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
CreateExecution.prototype = Object.create(PluginBase.prototype);
|
||||
CreateExecution.prototype.constructor = CreateExecution;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
CreateExecution.prototype.main = function (callback) {
|
||||
// Verify that the node is a pipeline
|
||||
if (!this.core.isTypeOf(this.activeNode, this.META.Pipeline)) {
|
||||
return callback('Current node is not a Pipeline!', this.result);
|
||||
}
|
||||
|
||||
return this.createExecution(this.activeNode)
|
||||
.then(() => {
|
||||
this.result.setSuccess(true);
|
||||
callback(null, this.result);
|
||||
})
|
||||
.catch(err => callback(err, this.result));
|
||||
};
|
||||
|
||||
CreateExecution.prototype.getExecutionDir = function () {
|
||||
return this.core.loadChildren(this.rootNode)
|
||||
.then(children => {
|
||||
var execPath = this.core.getPath(this.META.Execution);
|
||||
|
||||
// Find a node in the root that can contain only executions
|
||||
return children.find(child => {
|
||||
var metarule = this.core.getChildrenMeta(child);
|
||||
return metarule && metarule[execPath];
|
||||
}) || this.rootNode; // default to rootNode
|
||||
});
|
||||
};
|
||||
|
||||
CreateExecution.prototype.createExecution = function (node) {
|
||||
var name = this.core.getAttribute(node, 'name');
|
||||
|
||||
// Given a pipeline, copy all the operations to a custom job
|
||||
// - Copy the operations
|
||||
// - Wrap the operations in "Job" boxes which contain running info
|
||||
// - eg,
|
||||
// - 'debug' the given run (download all execution files)
|
||||
// - 'console' show console output (future feature)
|
||||
// - Update the references
|
||||
var tgtNode,
|
||||
copies,
|
||||
opTuples, // [[op, index], [op, index], ...]
|
||||
dataMapping = {};
|
||||
|
||||
return this.getExecutionDir()
|
||||
.then(execDir => {
|
||||
tgtNode = this.core.createNode({
|
||||
base: this.META.Execution,
|
||||
parent: execDir
|
||||
});
|
||||
this.core.setAttribute(tgtNode, 'name', `${name} Execution`);
|
||||
return this.core.loadChildren(node);
|
||||
})
|
||||
.then(children => {
|
||||
if (!children.length) {
|
||||
this.logger.warn(`No children in pipeline. Will proceed anyway`);
|
||||
}
|
||||
|
||||
copies = children.length ? this.core.copyNodes(children, tgtNode) : [];
|
||||
opTuples = copies
|
||||
.map((copy, i) => [copy, i]) // zip w/ index
|
||||
.filter(pair => this.core.isTypeOf(pair[0], this.META.Operation));
|
||||
|
||||
// Create a mapping of old names to new names
|
||||
return Q.all(opTuples.map(pair =>
|
||||
// Add the input/output mappings to the dataMapping
|
||||
this.addDataToMap(children[pair[1]], pair[0], dataMapping)
|
||||
)
|
||||
);
|
||||
})
|
||||
.then(() => { // datamapping is set!
|
||||
this.updateReferences(copies, dataMapping);
|
||||
this.boxOperations(opTuples.map(o => o[0]), tgtNode);
|
||||
return this.save(`Created execution of ${name}`);
|
||||
})
|
||||
.then(() => tgtNode); // return tgtNode
|
||||
};
|
||||
|
||||
CreateExecution.prototype.getExecutionsDir = function () {
|
||||
return this.rootNode;
|
||||
};
|
||||
|
||||
CreateExecution.prototype.addDataToMap = function (srcOp, dstOp, map) {
|
||||
return Q.all(
|
||||
[srcOp, dstOp]
|
||||
.map(op => {
|
||||
// Get the inputs and outputs for both
|
||||
return this.core.loadChildren(op)
|
||||
.then(containers => {
|
||||
var names = containers.map(c => this.core.getAttribute(c, 'name')),
|
||||
inputs = containers
|
||||
.find((c, i) => names[i] === 'Inputs'),
|
||||
outputs = containers
|
||||
.find((c, i) => names[i] === 'Outputs');
|
||||
|
||||
return Q.all(
|
||||
[inputs, outputs].map(c => c ? this.core.loadChildren(c) : [])
|
||||
);
|
||||
});
|
||||
})
|
||||
)
|
||||
.then(ios => {
|
||||
var srcIO,
|
||||
dstIO;
|
||||
|
||||
srcIO = ios[0].map(c => this.sortIOByName(c));
|
||||
dstIO = ios[1].map(c => this.sortIOByName(c));
|
||||
|
||||
// match the nodes by same name!
|
||||
srcIO.forEach((srcContainer, c) => srcContainer.forEach((node, n) =>
|
||||
map[this.core.getPath(node)] = dstIO[c][n] // old id -> new node
|
||||
)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
CreateExecution.prototype.sortIOByName = function (container) {
|
||||
return container.sort((a, b) =>
|
||||
// sort by name
|
||||
this.core.getAttribute(a, 'name') < this.core.getAttribute(b, 'name') ? 1 : -1
|
||||
);
|
||||
};
|
||||
|
||||
// Wrap each Operation with a Job 'box'
|
||||
CreateExecution.prototype.boxOperations = function (operations, container) {
|
||||
operations.forEach(copy => {
|
||||
var name = this.core.getAttribute(copy, 'name'),
|
||||
job;
|
||||
|
||||
// Create job
|
||||
job = this.core.createNode({
|
||||
base: this.META.Job,
|
||||
parent: container
|
||||
});
|
||||
this.core.setAttribute(job, 'name', name);
|
||||
|
||||
// Move the given copy into the Job node
|
||||
this.core.moveNode(copy, job);
|
||||
});
|
||||
};
|
||||
|
||||
CreateExecution.prototype.updateReferences = function (nodes, map) {
|
||||
// For each new node, update the references (other than base)
|
||||
// to the correct nodeId
|
||||
nodes.forEach(copy => {
|
||||
this.core.getPointerNames(copy)
|
||||
.filter(name => name !== 'base')
|
||||
.forEach(name => {
|
||||
var tgt = this.core.getPointerPath(copy, name);
|
||||
if (map[tgt]) {
|
||||
this.logger.info(`Updating ptr ${name}`);
|
||||
this.core.setPointer(copy, name, map[tgt]);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return CreateExecution;
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "CreateExecution",
|
||||
"name": "CreateExecution",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": false,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": []
|
||||
}
|
||||
@@ -51,8 +51,7 @@ define([
|
||||
CreateTorchMeta.prototype.main = function (callback) {
|
||||
// Use self to access core, project, result, logger etc from PluginBase.
|
||||
// These are all instantiated at this point.
|
||||
var self = this,
|
||||
nodeObject;
|
||||
var self = this;
|
||||
|
||||
if (!this.META.Language) {
|
||||
callback('"Language" container required to run plugin', this.result);
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
/*globals define*/
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint node:true, browser:true, esversion: 6*/
|
||||
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Tue May 03 2016 16:52:39 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'plugin/CreateExecution/CreateExecution/CreateExecution',
|
||||
'common/core/constants',
|
||||
'q',
|
||||
'text!./metadata.json',
|
||||
'plugin/PluginBase',
|
||||
'./Templates',
|
||||
'./Templates/index',
|
||||
'./LocalExecutor',
|
||||
'executor/ExecutorClient',
|
||||
'jszip'
|
||||
'jszip',
|
||||
'underscore'
|
||||
], function (
|
||||
CreateExecution,
|
||||
CONSTANTS,
|
||||
Q,
|
||||
pluginMetadata,
|
||||
PluginBase,
|
||||
Templates,
|
||||
LocalExecutor, // DeepForge operation primitives
|
||||
ExecutorClient,
|
||||
JsZip
|
||||
JsZip,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
@@ -26,18 +28,23 @@ define([
|
||||
/**
|
||||
* Initializes a new instance of ExecutePipeline.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @augments {CreateExecution}
|
||||
* @classdesc This class represents the plugin ExecutePipeline.
|
||||
* @constructor
|
||||
*/
|
||||
var ExecutePipeline = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
CreateExecution.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
|
||||
// Cache
|
||||
this.nodes = {};
|
||||
|
||||
// Record keeping for running operations
|
||||
this.opFor = {};
|
||||
this.incomingCounts = {};
|
||||
this.outputsOf = {};
|
||||
this.nodes = {};
|
||||
this.inputPortsFor = {};
|
||||
this.inputs = {};
|
||||
|
||||
this.finished = {};
|
||||
@@ -53,8 +60,8 @@ define([
|
||||
ExecutePipeline.metadata = pluginMetadata;
|
||||
ExecutePipeline.UPDATE_INTERVAL = 1500;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
ExecutePipeline.prototype = Object.create(PluginBase.prototype);
|
||||
// Prototypical inheritance from CreateExecution.
|
||||
ExecutePipeline.prototype = Object.create(CreateExecution.prototype);
|
||||
ExecutePipeline.prototype.constructor = ExecutePipeline;
|
||||
|
||||
/**
|
||||
@@ -70,51 +77,76 @@ define([
|
||||
// This will probably need to execute the operations, too, because the
|
||||
// inputs for the next operation cannot be created until the inputs have
|
||||
// been generated
|
||||
|
||||
var startPromise;
|
||||
if (this.core.isTypeOf(this.activeNode, this.META.Pipeline)) {
|
||||
// If starting with a pipeline, we will create an Execution first
|
||||
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);
|
||||
} else {
|
||||
return callback('Current node is not a Pipeline or Execution!', this.result);
|
||||
}
|
||||
|
||||
// Set debug and the final callback
|
||||
this.debug = true; // this.getCurrentConfig().debug;
|
||||
this._callback = callback;
|
||||
this.core.loadChildren(this.activeNode)
|
||||
.then(children => {
|
||||
// For each child, we need to organize them by the number of incoming connections
|
||||
// AND the corresponding incoming connections. When a connection is given data,
|
||||
// all the operations using that data can be decremented. If the remaining
|
||||
// incoming connection count is zero, execute the given operation
|
||||
//
|
||||
|
||||
// Get a node
|
||||
var child = children.filter(c =>
|
||||
this.core.getAttribute(c, 'name') === 'SGD'
|
||||
).shift();
|
||||
startPromise.then(subtree => {
|
||||
var children = subtree
|
||||
.filter(n => this.core.getParent(n) === this.activeNode);
|
||||
|
||||
this.parsePipeline(children);
|
||||
this.buildCache(subtree);
|
||||
this.parsePipeline(children); // record deps, etc
|
||||
|
||||
if (this.getCurrentConfig().reset) {
|
||||
// Clear the pipeline's results
|
||||
this.logger.info('Clearing all intermediate pipeline results');
|
||||
Object.keys(this.nodes).map(nodeId => this.nodes[nodeId])
|
||||
.filter(node => // get all connections
|
||||
!(this.core.getPointerPath(node, 'src') && this.core.getPointerPath(node, 'dst'))
|
||||
)
|
||||
.forEach(conn => this.core.delAttribute(conn, 'data'));
|
||||
}
|
||||
//if (this.getCurrentConfig().reset) {
|
||||
this.clearResults();
|
||||
//}
|
||||
|
||||
// Execute the operations in the proper order
|
||||
this.executePipeline();
|
||||
})
|
||||
.fail(e => console.error(e));
|
||||
// Execute the operations in the proper order
|
||||
this.executePipeline();
|
||||
})
|
||||
.fail(e => this.logger.error(e));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.clearResults = function () {
|
||||
var nodes = Object.keys(this.nodes).map(id => this.nodes[id]);
|
||||
// Clear the pipeline's results
|
||||
this.logger.info('Clearing all intermediate execution results');
|
||||
|
||||
nodes.filter(node => this.core.isTypeOf(node, this.META.Data))
|
||||
.forEach(conn => this.core.delAttribute(conn, 'data'));
|
||||
|
||||
// Set the status for each job to 'pending'
|
||||
nodes.filter(node => this.core.isTypeOf(node, this.META.Job))
|
||||
.forEach(node => this.core.setAttribute(node, 'status', 'pending'));
|
||||
};
|
||||
|
||||
//////////////////////////// Operation Preparation/Execution ////////////////////////////
|
||||
// Organize the operations by input data and output data (and count)
|
||||
ExecutePipeline.prototype.buildCache = function (nodes) {
|
||||
// Cache all nodes
|
||||
// Do I need to cache the data inputs? TODO
|
||||
// Probably not - I should be able to look them up as needed
|
||||
nodes.forEach(node => this.nodes[this.core.getPath(node)] = node);
|
||||
};
|
||||
|
||||
// For each child, we need to organize them by the number of incoming connections
|
||||
// AND the corresponding incoming connections. When a connection's src is
|
||||
// given data, all the operations using that data can be decremented.
|
||||
// If the remaining incoming connection count is zero for an operation,
|
||||
// execute the given operation
|
||||
ExecutePipeline.prototype.parsePipeline = function (nodes) {
|
||||
var operations,
|
||||
conns,
|
||||
connId,
|
||||
var conns,
|
||||
nodeId,
|
||||
srcPortId,
|
||||
dstPortId,
|
||||
i;
|
||||
|
||||
this.completedCount = 0;
|
||||
// Cache all nodes
|
||||
nodes.forEach(node => this.nodes[this.core.getPath(node)] = node);
|
||||
|
||||
// Get all connections
|
||||
conns = nodes.filter(node =>
|
||||
@@ -134,31 +166,51 @@ define([
|
||||
});
|
||||
|
||||
// Store the operations by their...
|
||||
// - incoming conns (connId => [ops]) (for updating which nodes come next)
|
||||
// - incoming conns (srcPortId => [ops]) (for updating which nodes come next)
|
||||
for (i = conns.length; i--;) {
|
||||
connId = this.core.getPath(conns[i]);
|
||||
nodeId = this.core.getPointerPath(conns[i], 'dst');
|
||||
this.opFor[connId] = nodeId;
|
||||
dstPortId = this.core.getPointerPath(conns[i], 'dst');
|
||||
nodeId = this.getSiblingIdContaining(dstPortId);
|
||||
|
||||
srcPortId = this.core.getPointerPath(conns[i], 'src');
|
||||
if (!this.opFor[srcPortId]) {
|
||||
this.opFor[srcPortId] = [nodeId];
|
||||
} else {
|
||||
this.opFor[srcPortId].push(nodeId);
|
||||
}
|
||||
|
||||
// - incoming counts
|
||||
this.incomingCounts[nodeId]++;
|
||||
this.inputs[nodeId].push(connId);
|
||||
this.inputs[nodeId].push(srcPortId);
|
||||
if (!this.inputPortsFor[dstPortId]) {
|
||||
this.inputPortsFor[dstPortId] = [srcPortId];
|
||||
} else {
|
||||
this.inputPortsFor[dstPortId].push(srcPortId);
|
||||
}
|
||||
}
|
||||
|
||||
// - output conns
|
||||
for (i = conns.length; i--;) {
|
||||
connId = this.core.getPath(conns[i]);
|
||||
nodeId = this.core.getPointerPath(conns[i], 'src');
|
||||
srcPortId = this.core.getPointerPath(conns[i], 'src');
|
||||
nodeId = this.getSiblingIdContaining(srcPortId);
|
||||
|
||||
dstPortId = this.core.getPointerPath(conns[i], 'dst');
|
||||
if (!this.outputsOf[nodeId]) {
|
||||
this.outputsOf[nodeId] = [connId];
|
||||
this.outputsOf[nodeId] = [dstPortId];
|
||||
} else {
|
||||
this.outputsOf[nodeId].push(connId);
|
||||
this.outputsOf[nodeId].push(dstPortId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getSiblingIdContaining = function (nodeId) {
|
||||
var parentId = this.core.getPath(this.activeNode) + CONSTANTS.PATH_SEP,
|
||||
relid = nodeId.replace(parentId, '');
|
||||
|
||||
return parentId + relid.split(CONSTANTS.PATH_SEP).shift();
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executePipeline = function() {
|
||||
this.logger.debug(`starting pipeline`);
|
||||
this.logger.debug('starting pipeline');
|
||||
this.executeReadyOperations();
|
||||
};
|
||||
|
||||
@@ -169,9 +221,9 @@ define([
|
||||
this.save('Pipeline execution finished')
|
||||
.then(() => {
|
||||
this.result.setSuccess(!err);
|
||||
this._callback(null, this.result);
|
||||
this._callback(err || null, this.result);
|
||||
})
|
||||
.fail(e => console.error(e));
|
||||
.fail(e => this.logger.error(e));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executeReadyOperations = function () {
|
||||
@@ -181,20 +233,29 @@ define([
|
||||
|
||||
this.logger.info(`About to execute ${readyOps.length} operations`);
|
||||
// Execute all ready operations
|
||||
readyOps.forEach(opId => {
|
||||
delete this.incomingCounts[opId];
|
||||
this.executeOperation(opId);
|
||||
readyOps.forEach(jobId => {
|
||||
delete this.incomingCounts[jobId];
|
||||
this.executeOperation(jobId);
|
||||
});
|
||||
return readyOps.length;
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executeOperation = function (opId) {
|
||||
var node = this.nodes[opId],
|
||||
ExecutePipeline.prototype.getOperation = function (jobId) {
|
||||
var node = this.nodes[jobId],
|
||||
children = this.core.getChildrenPaths(node).map(id => this.nodes[id]);
|
||||
|
||||
// Currently, jobs
|
||||
return children.find(child => this.isMetaTypeOf(child, this.META.Operation));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executeOperation = function (jobId) {
|
||||
var node = this.getOperation(jobId),
|
||||
name = this.core.getAttribute(node, 'name'),
|
||||
localTypeId = this.getLocalOpType(node),
|
||||
artifact,
|
||||
artifactName,
|
||||
files,
|
||||
data = {},
|
||||
inputs;
|
||||
|
||||
// Execute any special operation types here - not on an executor
|
||||
@@ -204,7 +265,7 @@ define([
|
||||
// Generate all execution files
|
||||
this.createOperationFiles(node).then(results => {
|
||||
files = results;
|
||||
artifactName = name + '-execution-files';
|
||||
artifactName = `${name}_${jobId.replace(/\//g, '_')}-execution-files`;
|
||||
artifact = this.blobClient.createArtifact(artifactName);
|
||||
|
||||
// Add the input assets
|
||||
@@ -223,12 +284,7 @@ define([
|
||||
})
|
||||
.then(mds => {
|
||||
// get (input, filename) tuples
|
||||
var data = {},
|
||||
tuples,
|
||||
outputs,
|
||||
config;
|
||||
|
||||
tuples = mds.forEach((metadata, i) => {
|
||||
mds.forEach((metadata, i) => {
|
||||
// add the hashes for each input
|
||||
var input = inputs[i],
|
||||
name = metadata.name,
|
||||
@@ -246,25 +302,33 @@ define([
|
||||
delete files.ptrAssets;
|
||||
|
||||
// Add the executor config
|
||||
outputs = this._parseArgs(this.core.getAttribute(node, 'outputs'))
|
||||
.map(pair => pair[0])
|
||||
return this.getOutputs(node);
|
||||
})
|
||||
.then(outputArgs => {
|
||||
var config,
|
||||
args = ['init.lua'],
|
||||
outputs;
|
||||
|
||||
outputs = outputArgs.map(pair => pair[0])
|
||||
.map(name => {
|
||||
return {
|
||||
name: name,
|
||||
resultPatterns: [`outputs/${name}/**`]
|
||||
resultPatterns: [`outputs/${name}`]
|
||||
};
|
||||
});
|
||||
var debugging = [
|
||||
{
|
||||
|
||||
if (this.debug) {
|
||||
args.push('#' + Date.now());
|
||||
outputs.push({
|
||||
name: name + '-all-files',
|
||||
resultPatterns: []
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
config = {
|
||||
cmd: 'th',
|
||||
args: ['init.lua'],
|
||||
resultArtifacts: outputs.concat(debugging)
|
||||
args: args,
|
||||
resultArtifacts: outputs
|
||||
};
|
||||
files['executor_config.json'] = JSON.stringify(config, null, 4);
|
||||
|
||||
@@ -282,17 +346,18 @@ define([
|
||||
.then(hash => {
|
||||
this.logger.info(`Saved execution files "${artifactName}"`);
|
||||
this.result.addArtifact(hash); // Probably only need this for debugging...
|
||||
this.executeDistOperation(node, hash);
|
||||
this.executeDistOperation(jobId, node, hash);
|
||||
})
|
||||
.fail(e => {
|
||||
this.logger.error(`Distributed operation "${name}" failed ${e}`);
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'fail');
|
||||
this.onPipelineComplete(`Distributed operation "${name}" failed ${e}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executeDistOperation = function (node, hash) {
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
nodeId = this.core.getPath(node),
|
||||
ExecutePipeline.prototype.executeDistOperation = function (jobId, opNode, hash) {
|
||||
var name = this.core.getAttribute(opNode, 'name'),
|
||||
opId = this.core.getPath(opNode),
|
||||
executor = new ExecutorClient({
|
||||
logger: this.logger,
|
||||
serverPort: this.gmeConfig.server.port
|
||||
@@ -300,127 +365,111 @@ define([
|
||||
|
||||
this.logger.info(`Executing operation "${name}"`);
|
||||
|
||||
// Set the job status to 'running'
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'running');
|
||||
|
||||
// Run the operation on an executor
|
||||
executor.createJob({hash})
|
||||
.then(() => this.watchOperation(executor, hash, nodeId))
|
||||
.then(() => this.watchOperation(executor, hash, opId, jobId))
|
||||
.catch(err => this.logger.error(`Could not execute "${name}": ${err}`));
|
||||
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.watchOperation = function (executor, hash, nodeId) {
|
||||
ExecutePipeline.prototype.watchOperation = function (executor, hash, opId, jobId) {
|
||||
var name;
|
||||
|
||||
return executor.getInfo(hash)
|
||||
.then(info => {
|
||||
if (info.status === 'CREATED' || info.status === 'RUNNING') {
|
||||
setTimeout(
|
||||
this.watchOperation.bind(this, executor, hash, nodeId),
|
||||
this.watchOperation.bind(this, executor, hash, opId, jobId),
|
||||
ExecutePipeline.UPDATE_INTERVAL
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.status !== 'SUCCESS') {
|
||||
var name = this.core.getAttribute(this.nodes[nodeId], 'name');
|
||||
this.logger.error(`Operation "${nodeId}" failed! ${JSON.stringify(info)}`);
|
||||
name = this.core.getAttribute(this.nodes[opId], 'name');
|
||||
// Download all files
|
||||
this.result.addArtifact(info.resultHashes[name + '-all-files']);
|
||||
this.onPipelineComplete(`Operation "${nodeId}" failed! ${info}`); // Failed
|
||||
// Set the job to failed! Store the error
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'fail');
|
||||
this.onPipelineComplete(`Operation "${opId}" failed! ${JSON.stringify(info)}`); // Failed
|
||||
} else {
|
||||
var name = this.core.getAttribute(this.nodes[nodeId], 'name');
|
||||
if (this.getCurrentConfig().debug) {
|
||||
name = this.core.getAttribute(this.nodes[opId], 'name');
|
||||
if (this.debug) {
|
||||
this.result.addArtifact(info.resultHashes[name + '-all-files']);
|
||||
}
|
||||
this.onDistOperationComplete(nodeId, info);
|
||||
}
|
||||
this.onDistOperationComplete(opId, info);
|
||||
}
|
||||
})
|
||||
.catch(err => this.logger.error(`Could not get op info for ${nodeId}: ${err}`));
|
||||
.catch(err => this.logger.error(`Could not get op info for ${opId}: ${err}`));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onDistOperationComplete = function (nodeId, result) {
|
||||
var outputIds = this.outputsOf[nodeId] || [],
|
||||
nodes = outputIds.map(id => this.nodes[id]),
|
||||
node = this.nodes[nodeId],
|
||||
var node = this.nodes[nodeId],
|
||||
outputMap = {},
|
||||
outputs;
|
||||
|
||||
// Match the output names to the actual nodes
|
||||
// Create an array of [name, node]
|
||||
// For now, just match by type. Later we may use ports for input/outputas
|
||||
// TODO
|
||||
outputs = this._parseArgs(this.core.getAttribute(node, 'outputs'))
|
||||
.map(pair => {
|
||||
var name = pair[0],
|
||||
type = pair[1];
|
||||
// For now, just match by type. Later we may use ports for input/outputs
|
||||
// Store the results in the outgoing ports
|
||||
this.getOutputs(node)
|
||||
.then(outputPorts => {
|
||||
outputs = outputPorts.map(tuple => [tuple[0], tuple[2]]);
|
||||
outputs.forEach(output => outputMap[output[0]] = output[1]);
|
||||
|
||||
// Find a node with the given base type
|
||||
for (var i = nodes.length; i--;) {
|
||||
if (this.isMetaTypeOf(nodes[i], this.META[type])) {
|
||||
return [name, nodes[i]];
|
||||
}
|
||||
}
|
||||
throw `Multiple outputs w/ same type not fully supported ${nodeId}`;
|
||||
});
|
||||
|
||||
|
||||
// Store the results in the outgoing connections
|
||||
var artifactPs = outputs.map(pair => {
|
||||
var name = pair[0],
|
||||
node = pair[1],
|
||||
hash;
|
||||
|
||||
// FIXME: this should not be in directories -> flatten the data!
|
||||
// Ideally, this would be performed on the worker -> not on DeepForge
|
||||
// get the files from the hash
|
||||
return this.blobClient.getObject(result.resultHashes[name]);
|
||||
});
|
||||
Q.all(artifactPs)
|
||||
.then(objects => {
|
||||
this.logger.info(`preparing outputs -> retrieved ${objects.length} objects`);
|
||||
return Q.all(
|
||||
objects.map((object, index) => {
|
||||
var output = new JsZip();
|
||||
|
||||
return output.load(object);
|
||||
})
|
||||
);
|
||||
// this should not be in directories -> flatten the data!
|
||||
return Q.all(outputs.map(tuple => // [ name, node ]
|
||||
this.blobClient.getArtifact(result.resultHashes[tuple[0]])
|
||||
));
|
||||
})
|
||||
.then(zipfiles => {
|
||||
return Q.all(
|
||||
zipfiles.map((zip, index) => {
|
||||
var pair = outputs[index],
|
||||
name = pair[0],
|
||||
connNode = pair[1],
|
||||
artifact = this.blobClient.createArtifact(name),
|
||||
files = {};
|
||||
.then(artifacts => {
|
||||
this.logger.info(`preparing outputs -> retrieved ${artifacts.length} objects`);
|
||||
// Create new metadata for each
|
||||
artifacts.forEach((artifact, i) => {
|
||||
var name = outputs[i][0],
|
||||
hash = artifact.descriptor.content[`outputs/${name}`].content;
|
||||
|
||||
// move the files from /outputs/<name> to /
|
||||
Object.keys(zip.files)
|
||||
.forEach(filename => {
|
||||
var newName = filename.replace('outputs/' + name + '/', '');
|
||||
files[newName] = zip.files[filename].asArrayBuffer();
|
||||
});
|
||||
this.core.setAttribute(outputMap[name], 'data', hash);
|
||||
});
|
||||
|
||||
// save artifact and get the new hash
|
||||
return artifact.addFiles(files)
|
||||
.then(() => artifact.save())
|
||||
.then(hash => {
|
||||
// store the new hash in the connection
|
||||
this.core.setAttribute(connNode, 'data', hash);
|
||||
});
|
||||
})
|
||||
);
|
||||
return this.onOperationComplete(node);
|
||||
})
|
||||
.then(() => this.onOperationComplete(node))
|
||||
.fail(e => this.onPipelineComplete(`Operation ${nodeId} failed: ${e}`));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onOperationComplete = function (node) {
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
nodeId = this.core.getPath(node),
|
||||
outputs = this.outputsOf[nodeId] || [],
|
||||
ExecutePipeline.prototype.onOperationComplete = function (opNode) {
|
||||
var name = this.core.getAttribute(opNode, 'name'),
|
||||
nextPortIds = this.getOperationOutputIds(opNode),
|
||||
jNode = this.core.getParent(opNode),
|
||||
resultPorts,
|
||||
hasReadyOps;
|
||||
|
||||
// Set the operation to 'success'!
|
||||
this.core.setAttribute(jNode, 'status', 'success');
|
||||
|
||||
// For all the outputs, decrement the corresponding operation's incoming counts
|
||||
hasReadyOps = outputs.map(id => this.opFor[id])
|
||||
// Transport the data from the outputs to any connected inputs
|
||||
// - Get all the connections from each outputId
|
||||
// - Get the corresponding dst outputs
|
||||
// - Use these new ids for checking 'hasReadyOps'
|
||||
resultPorts = nextPortIds.map(id => this.inputPortsFor[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), []);
|
||||
|
||||
resultPorts.map((id, i) => [this.nodes[id], this.nodes[nextPortIds[i]]])
|
||||
.forEach(pair => { // [ resultPort, nextPort ]
|
||||
var result = pair[0],
|
||||
next = pair[1],
|
||||
hash = this.core.getAttribute(result, 'data');
|
||||
|
||||
this.logger.info(`forwarding data (${hash}) from ${this.core.getPath(result)} ` +
|
||||
`to ${this.core.getPath(next)}`);
|
||||
this.core.setAttribute(next, 'data', hash);
|
||||
});
|
||||
|
||||
// For all the nextPortIds, decrement the corresponding operation's incoming counts
|
||||
hasReadyOps = resultPorts.map(id => this.opFor[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), [])
|
||||
|
||||
// decrement the incoming counts for each operation id
|
||||
@@ -437,6 +486,16 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getOperationOutputIds = function(node) {
|
||||
var jobId = this.getSiblingIdContaining(this.core.getPath(node));
|
||||
|
||||
return this.outputsOf[jobId] || [];
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getOperationOutputs = function(node) {
|
||||
return this.getOperationOutputIds(node).map(id => this.nodes[id]);
|
||||
};
|
||||
|
||||
//////////////////////////// Operation File/Dir Creators ////////////////////////////
|
||||
ExecutePipeline.prototype.createOperationFiles = function (node) {
|
||||
var files = {};
|
||||
@@ -451,48 +510,55 @@ define([
|
||||
// <name>.lua (entry point -> calls main operation code)
|
||||
|
||||
// add the given files
|
||||
this.createEntryFile(node, files);
|
||||
this.createInputs(node, files);
|
||||
this.createOutputs(node, files);
|
||||
this.createMainFile(node, files);
|
||||
this.createAttributeFile(node, files);
|
||||
return Q.ninvoke(this, 'createPointers', node, files);
|
||||
return this.createEntryFile(node, files)
|
||||
.then(() => this.createInputs(node, files))
|
||||
.then(() => this.createOutputs(node, files))
|
||||
.then(() => this.createMainFile(node, files))
|
||||
.then(() => {
|
||||
this.createAttributeFile(node, files);
|
||||
return Q.ninvoke(this, 'createPointers', node, files);
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createInputs = function (node, files) {
|
||||
var nodeId = this.core.getPath(node),
|
||||
inputIds = this.inputs[nodeId],
|
||||
inputs = this._parseArgs(this.core.getAttribute(node, 'inputs'));
|
||||
var tplContents;
|
||||
return this.getInputs(node)
|
||||
.then(inputs => {
|
||||
// For each input, match the connection with the input name
|
||||
// [ name, type ] => [ name, type, node ]
|
||||
if (inputs.length > 1) {
|
||||
this.logger.warn('multiple inputs not yet fully supported!');
|
||||
}
|
||||
|
||||
// For each input, match the connection with the input name
|
||||
// [ name, type ] => [ name, type, node ]
|
||||
if (inputIds.length > 1) {
|
||||
this.logger.warn(`multiple inputs not yet supported!`);
|
||||
}
|
||||
inputs[0].push(this.nodes[inputIds[0]]);
|
||||
// For each input,
|
||||
// - create the deserializer
|
||||
// - put it in inputs/<name>/init.lua
|
||||
// - copy the data asset to /inputs/<name>/init.lua
|
||||
files.inputAssets = {}; // data assets
|
||||
tplContents = inputs.map(pair => {
|
||||
var name = pair[0],
|
||||
node = pair[2];
|
||||
|
||||
// For each input,
|
||||
// - create the deserializer
|
||||
// - put it in inputs/<name>/init.lua
|
||||
// - copy the data asset to /inputs/<name>/init.lua
|
||||
files.inputAssets = {}; // data assets
|
||||
inputs.forEach(pair => {
|
||||
var name = pair[0],
|
||||
type = pair[1],
|
||||
node = pair[2],
|
||||
content;
|
||||
|
||||
// Create the deserializer
|
||||
content = {
|
||||
name: name,
|
||||
code: this.core.getAttribute(this.META[type], 'deserialize')
|
||||
};
|
||||
files['inputs/' + name + '/init.lua'] = _.template(Templates.DESERIALIZE)(content);
|
||||
|
||||
// copy the data asset to /inputs/<name>/
|
||||
// storing the hash for now...
|
||||
files.inputAssets[name] = this.core.getAttribute(node, 'data');
|
||||
});
|
||||
return {
|
||||
name: name,
|
||||
code: this.core.getAttribute(node, 'deserialize')
|
||||
};
|
||||
});
|
||||
var hashes = inputs.map(pair =>
|
||||
// storing the hash for now...
|
||||
files.inputAssets[pair[0]] = this.core.getAttribute(pair[2], 'data')
|
||||
);
|
||||
return Q.all(hashes.map(h => this.blobClient.getMetadata(h)));
|
||||
})
|
||||
.then(metadatas => {
|
||||
// Create the deserializer
|
||||
tplContents.forEach((ctnt, i) => {
|
||||
// Get the name of the given asset
|
||||
ctnt.filename = metadatas[i].name;
|
||||
files['inputs/' + ctnt.name + '/init.lua'] = _.template(Templates.DESERIALIZE)(ctnt);
|
||||
});
|
||||
return files;
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createPointers = function (node, files, cb) {
|
||||
@@ -505,74 +571,51 @@ define([
|
||||
)
|
||||
.then(nodes => {
|
||||
|
||||
var len = nodes.length,
|
||||
executePlugin = function(pluginName, config, callback) {
|
||||
// Call the Interpreter manager in a Q.ninvoke friendly way
|
||||
// FIXME: I need to create a custom context for the given plugin:
|
||||
// - Set the activeNode to the given referenced node
|
||||
// - If the activeNode is namespaced, set META to the given namespace
|
||||
//
|
||||
WebGMEGlobal.InterpreterManager.run(pluginName, config, result => {
|
||||
if (!result.success) {
|
||||
return callback(result.getError());
|
||||
}
|
||||
console.log('Finished calling ' + pluginName);
|
||||
callback(null, result.artifacts);
|
||||
});
|
||||
};
|
||||
var executePlugin = (pluginId, config, callback) => {
|
||||
// Call the Interpreter manager in a Q.ninvoke friendly way
|
||||
// I need to create a custom context for the given plugin:
|
||||
// - Set the activeNode to the given referenced node
|
||||
// - If the activeNode is namespaced, set META to the given namespace
|
||||
//
|
||||
// FIXME: Check if it is running in the browser or on the server
|
||||
WebGMEGlobal.Client.runBrowserPlugin(pluginId, config, (err, result) => {
|
||||
if (!result.success) {
|
||||
return callback(result.getError());
|
||||
}
|
||||
this.logger.info('Finished calling ' + pluginId);
|
||||
callback(null, result.artifacts);
|
||||
});
|
||||
};
|
||||
|
||||
return Q.all(
|
||||
nodes.map(ptrNode => {
|
||||
// Look up the plugin to use
|
||||
var pluginName = this.core.getRegistry(ptrNode, 'validPlugins').split(' ').shift();
|
||||
console.log(`generating code for ${this.core.getAttribute(ptrNode, 'name')} using ${pluginName}`);
|
||||
var metanode = this.core.getMetaType(ptrNode),
|
||||
pluginId;
|
||||
|
||||
// Add plugin config?
|
||||
// TODO
|
||||
var pluginConfig = {
|
||||
activeNode: this.core.getPath(ptrNode)
|
||||
};
|
||||
pluginId = this.core.getRegistry(ptrNode, 'validPlugins').split(' ').shift();
|
||||
this.logger.info(`generating code for ${this.core.getAttribute(ptrNode, 'name')} using ${pluginId}`);
|
||||
|
||||
var context = WebGMEGlobal.Client.getCurrentPluginContext(pluginId);
|
||||
|
||||
context.managerConfig.namespace = this.core.getNamespace(metanode);
|
||||
context.managerConfig.activeNode = this.core.getPath(ptrNode);
|
||||
|
||||
// Load and run the plugin
|
||||
return Q.nfcall(executePlugin, pluginName, pluginConfig);
|
||||
return Q.nfcall(executePlugin, pluginId, context);
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(resultHashes => {
|
||||
var name = this.core.getAttribute(node, 'name');
|
||||
console.log(`Pointer generation for ${name} FINISHED!`);
|
||||
this.logger.info(`Pointer generation for ${name} FINISHED!`);
|
||||
resultHashes.forEach((hashes, index) => {
|
||||
// Grab the first asset for now
|
||||
// FIXME
|
||||
files.ptrAssets[`pointers/${pointers[index]}/init.lua`] = hashes[0];
|
||||
});
|
||||
return cb(null, files);
|
||||
|
||||
// For each hash:
|
||||
// - retrieve the zip archive
|
||||
// - get the generated files for the plugin
|
||||
// - if only one file, rename it to `init.lua`
|
||||
//return Q.all(
|
||||
//resultHashes.map(hash => this.blobClient.getObjectAsString(hash))
|
||||
//);
|
||||
})
|
||||
// Add support for zip files
|
||||
// TODO
|
||||
//.then(objects =>
|
||||
//Q.all(objects.map(object => {
|
||||
//var output = new JsZip();
|
||||
|
||||
//return output.load(object);
|
||||
//})
|
||||
//)
|
||||
//)
|
||||
//.then(zipfiles => { // TODO
|
||||
//// If it generates one artifact, rename it to `init.lua`. Otherwise, expect
|
||||
//// an `init.lua` file
|
||||
//// TODO
|
||||
//console.log('zipfiles:', zipfiles);
|
||||
//cb(null, files);
|
||||
//})
|
||||
.fail(e => {
|
||||
this.logger.error(`Could not generate pointer files for ${this.core.getAttribute(node, 'name')}: ${JSON.stringify(e)}`);
|
||||
return cb(e);
|
||||
@@ -582,64 +625,85 @@ define([
|
||||
ExecutePipeline.prototype.createOutputs = function (node, files) {
|
||||
// For each of the output types, grab their serialization functions and
|
||||
// create the `outputs/init.lua` file
|
||||
var outputTypes,
|
||||
code;
|
||||
return this.getOutputs(node)
|
||||
.then(outputs => {
|
||||
var outputTypes = outputs
|
||||
// Get the serialize functions for each
|
||||
.map(tuple => [tuple[1], this.core.getAttribute(tuple[2], 'serialize')]);
|
||||
|
||||
outputTypes = this._parseArgs(this.core.getAttribute(node, 'outputs'))
|
||||
.map(pair => pair[1])
|
||||
// Get the serialize functions for each
|
||||
.map(type => [type, this.core.getAttribute(this.META[type], 'serialize')]);
|
||||
// Remove duplicates
|
||||
// TODO
|
||||
|
||||
// Remove duplicates
|
||||
// TODO
|
||||
|
||||
files['outputs/init.lua'] = _.template(Templates.SERIALIZE)({types: outputTypes});
|
||||
files['outputs/init.lua'] = _.template(Templates.SERIALIZE)({types: outputTypes});
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype._parseArgs = function (args) {
|
||||
// parse arguments are in the form 'arg: Type1, arg2: Type2'
|
||||
// and return [[arg1, Type1], [arg2, Type2]]
|
||||
return args.split(',')
|
||||
.map(pair => pair.split(':').map(w => w.replace(/\s+/g, '')));
|
||||
ExecutePipeline.prototype.getOutputs = function (node) {
|
||||
return this.getOperationData(node, this.META.Outputs);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getInputs = function (node) {
|
||||
return this.getOperationData(node, this.META.Inputs);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getOperationData = function (node, metaType) {
|
||||
// Load the children and the output's children
|
||||
return this.core.loadChildren(node)
|
||||
.then(containers => {
|
||||
var outputs = containers.find(c => this.core.isTypeOf(c, metaType));
|
||||
return outputs ? this.core.loadChildren(outputs) : [];
|
||||
})
|
||||
.then(outputs => {
|
||||
var bases = outputs.map(node => this.core.getMetaType(node));
|
||||
// return [[arg1, Type1, node1], [arg2, Type2, node2]]
|
||||
return outputs.map((node, i) => [
|
||||
this.core.getAttribute(node, 'name'),
|
||||
this.core.getAttribute(bases[i], 'name'),
|
||||
node
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createEntryFile = function (node, files) {
|
||||
var outputs = this._parseArgs(this.core.getAttribute(node, 'outputs')),
|
||||
name = this.core.getAttribute(node, 'name'),
|
||||
content = {};
|
||||
return this.getOutputs(node)
|
||||
.then(outputs => {
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
content = {};
|
||||
|
||||
// sort the outputs by the return values?
|
||||
if (outputs.length > 1) {
|
||||
console.error('Multiple outputs not yet supported!');
|
||||
}
|
||||
// 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;
|
||||
// inputs and outputs
|
||||
content.name = name;
|
||||
content.outputs = outputs;
|
||||
|
||||
files['init.lua'] = _.template(Templates.ENTRY)(content);
|
||||
files['init.lua'] = _.template(Templates.ENTRY)(content);
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createMainFile = function (node, files) {
|
||||
var inputs = this._parseArgs(this.core.getAttribute(node, 'inputs')),
|
||||
name = this.core.getAttribute(node, 'name'),
|
||||
code = this.core.getAttribute(node, 'code'),
|
||||
pointers = this.core.getPointerNames(node).filter(ptr => ptr !== 'base'),
|
||||
content = {
|
||||
name: name
|
||||
};
|
||||
return this.getInputs(node)
|
||||
.then(inputs => {
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
code = this.core.getAttribute(node, 'code'),
|
||||
pointers = this.core.getPointerNames(node).filter(ptr => ptr !== 'base'),
|
||||
content = {
|
||||
name: name
|
||||
};
|
||||
|
||||
// Get input data arguments
|
||||
content.inputs = inputs;
|
||||
// Get input data arguments
|
||||
content.inputs = inputs;
|
||||
|
||||
// Defined variables for each pointers
|
||||
content.pointers = pointers;
|
||||
// Defined variables for each pointers
|
||||
content.pointers = pointers;
|
||||
|
||||
// Add remaining code
|
||||
content.code = code;
|
||||
// Add remaining code
|
||||
content.code = code;
|
||||
|
||||
files['main.lua'] = _.template(Templates.MAIN)(content);
|
||||
files['main.lua'] = _.template(Templates.MAIN)(content);
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createAttributeFile = function (node, files) {
|
||||
@@ -656,15 +720,14 @@ define([
|
||||
};
|
||||
|
||||
//////////////////////////// Special Operations ////////////////////////////
|
||||
ExecutePipeline.LOCAL_OPS = [
|
||||
'BlobLoader',
|
||||
'Save'
|
||||
];
|
||||
|
||||
ExecutePipeline.prototype.getLocalOpType = function (node) {
|
||||
var type;
|
||||
for (var i = ExecutePipeline.LOCAL_OPS.length; i--;) {
|
||||
type = ExecutePipeline.LOCAL_OPS[i];
|
||||
for (var i = LocalExecutor.TYPES.length; i--;) {
|
||||
type = LocalExecutor.TYPES[i];
|
||||
if (!this.META[type]) {
|
||||
this.logger.warn(`Missing local operation: ${type}`);
|
||||
continue;
|
||||
}
|
||||
if (this.isMetaTypeOf(node, this.META[type])) {
|
||||
return type;
|
||||
}
|
||||
@@ -682,56 +745,7 @@ define([
|
||||
return this[type](node);
|
||||
};
|
||||
|
||||
// Should these be in lua?
|
||||
ExecutePipeline.prototype.BlobLoader = function(node) {
|
||||
var nodeId = this.core.getPath(node),
|
||||
hash = this.core.getAttribute(node, 'data'),
|
||||
outputs = this.outputsOf[nodeId].map(id => this.nodes[id]);
|
||||
|
||||
this.logger.info(`Running BlobLoader for ${nodeId}`);
|
||||
|
||||
// Get the 'data' hash and store it in the output connections
|
||||
outputs.forEach(output => this.core.setAttribute(output, 'data', hash));
|
||||
|
||||
// Set the metadata as appropriate
|
||||
// TODO
|
||||
this.onOperationComplete(node);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.Save = function(node) {
|
||||
var nodeId = this.core.getPath(node),
|
||||
dstName = this.core.getAttribute(node, 'dst'),
|
||||
parentId = this.core.getPointerPath(node, 'target');
|
||||
|
||||
// Overwrite existing node w/ this name?
|
||||
// TODO
|
||||
|
||||
if (this.inputs[nodeId].length > 1) {
|
||||
this.logger.error(`multiple inputs not yet supported!`);
|
||||
}
|
||||
|
||||
// Load the new parent node
|
||||
this.core.loadByPath(this.rootNode, parentId)
|
||||
.then(parent => {
|
||||
var newNode,
|
||||
inputId = this.inputs[nodeId][0],
|
||||
base = this.core.getBase(this.nodes[inputId]),
|
||||
input;
|
||||
|
||||
newNode = this.core.createNode({
|
||||
base,
|
||||
parent
|
||||
});
|
||||
|
||||
this.core.setAttribute(newNode, 'name', dstName);
|
||||
this.logger.info(`Saving result as ${dstName} in ${this.core.getAttribute(parent, 'name')}`);
|
||||
// Attach the data
|
||||
input = this.core.getAttribute(this.nodes[inputId], 'data');
|
||||
this.core.setAttribute(newNode, 'data', input);
|
||||
|
||||
this.onOperationComplete(node);
|
||||
});
|
||||
};
|
||||
_.extend(ExecutePipeline.prototype, LocalExecutor.prototype);
|
||||
|
||||
return ExecutePipeline;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/* globals define*/
|
||||
// This is an 'executor' containing the implementations of all local operations
|
||||
// These are all primitives in DeepForge
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
'use strict';
|
||||
var LocalExecutor = function() {
|
||||
};
|
||||
|
||||
// Should these be in lua?
|
||||
LocalExecutor.prototype.BlobLoader = function(node) {
|
||||
var hash = this.core.getAttribute(node, 'data');
|
||||
return this.getOutputs(node)
|
||||
.then(outputTuples => {
|
||||
var outputs = outputTuples.map(tuple => tuple[2]),
|
||||
paths;
|
||||
|
||||
paths = outputs.map(output => this.core.getPath(output));
|
||||
// Get the 'data' hash and store it in the output data ports
|
||||
this.logger.info(`Loading blob data (${hash}) to ${paths.map(p => `"${p}"`)}`);
|
||||
outputs.forEach(output => this.core.setAttribute(output, 'data', hash));
|
||||
|
||||
// Set the metadata as appropriate
|
||||
// TODO
|
||||
this.onOperationComplete(node);
|
||||
});
|
||||
};
|
||||
|
||||
LocalExecutor.prototype._getSaveDir = function () {
|
||||
return this.core.loadChildren(this.rootNode)
|
||||
.then(children => {
|
||||
var execPath = this.core.getPath(this.META.Data),
|
||||
containers,
|
||||
saveDir;
|
||||
|
||||
// Find a node in the root that can contain only executions
|
||||
containers = children.filter(child => {
|
||||
var metarule = this.core.getChildrenMeta(child);
|
||||
return metarule && metarule[execPath];
|
||||
});
|
||||
|
||||
if (containers.length > 1) {
|
||||
saveDir = containers.find(c =>
|
||||
this.core.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
|
||||
) || containers[0];
|
||||
}
|
||||
|
||||
return saveDir || this.rootNode; // default to rootNode
|
||||
});
|
||||
};
|
||||
|
||||
LocalExecutor.prototype.Save = function(node) {
|
||||
var nodeId = this.core.getPath(node),
|
||||
parentNode;
|
||||
|
||||
// Get the input node
|
||||
this.logger.info('Calling save operation!');
|
||||
return this._getSaveDir()
|
||||
.then(_saveDir => {
|
||||
parentNode = _saveDir;
|
||||
return this.getInputs(node);
|
||||
})
|
||||
.then(inputs => {
|
||||
var ids = inputs.map(i => this.core.getPath(i[2])),
|
||||
dataNodes;
|
||||
|
||||
dataNodes = Object.keys(this.nodes)
|
||||
.map(id => this.nodes[id])
|
||||
.filter(node => this.isMetaTypeOf(node, this.META.Transporter))
|
||||
.filter(node =>
|
||||
ids.indexOf(this.core.getPointerPath(node, 'dst')) > -1
|
||||
)
|
||||
.map(node => this.core.getPointerPath(node, 'src'))
|
||||
.map(id => this.nodes[id]);
|
||||
|
||||
// get the input node
|
||||
if (dataNodes.length === 0) {
|
||||
this.logger.error(`Could not find data to save! ${nodeId}`);
|
||||
} else {
|
||||
var newNodes = this.core.copyNodes(dataNodes, parentNode),
|
||||
newName = this.core.getOwnAttribute(node, 'saveName');
|
||||
if (newName) {
|
||||
newNodes.forEach(node =>
|
||||
this.core.setAttribute(node, 'name', newName)
|
||||
);
|
||||
}
|
||||
}
|
||||
var hashes = dataNodes.map(n => this.core.getAttribute(n, 'data'));
|
||||
this.logger.info(`saving hashes: ${hashes.map(h => `"${h}"`)}`);
|
||||
this.onOperationComplete(node);
|
||||
});
|
||||
|
||||
// Overwrite existing node w/ this name?
|
||||
// TODO
|
||||
};
|
||||
|
||||
LocalExecutor.TYPES = Object.keys(LocalExecutor.prototype)
|
||||
.filter(name => name.indexOf('_') !== 0);
|
||||
|
||||
return LocalExecutor;
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
require 'paths'
|
||||
local dir = paths.concat('inputs', '<%= name %>')
|
||||
<%= code %>
|
||||
@@ -1,12 +0,0 @@
|
||||
-- run the <%= name %> and serialize the results
|
||||
<%= outputs.map(p => p[0])[0] %> = require './main'
|
||||
print('<%= name %> operation complete!')
|
||||
|
||||
-- serialize by type
|
||||
outputs = require './outputs'
|
||||
<% outputs.forEach(pair => {
|
||||
var name = pair[0],
|
||||
type = pair[1];
|
||||
%>
|
||||
outputs.<%= type %>('<%= name %>', <%= name %>)
|
||||
<% }); %>
|
||||
@@ -17,14 +17,6 @@
|
||||
"value": false,
|
||||
"valueType": "boolean",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"name": "reset",
|
||||
"displayName": "Reset",
|
||||
"description": "Clear existing results",
|
||||
"value": false,
|
||||
"valueType": "boolean",
|
||||
"readOnly": false
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
require 'paths'
|
||||
local path = 'inputs/<%= name %>/<%= filename %>'
|
||||
local abs_path = paths.concat('inputs', '<%= name %>', '<%= filename %>')
|
||||
<%= code %>
|
||||
@@ -0,0 +1,13 @@
|
||||
-- run the <%= name %> and serialize the results
|
||||
print('\n############### Running "<%= name %>" Operation ############### ')
|
||||
results = require './main'
|
||||
print('############### "<%= name %>" Operation Complete! ###############')
|
||||
|
||||
-- serialize by type
|
||||
outputs = require './outputs'
|
||||
<% outputs.forEach(pair => {
|
||||
var name = pair[0],
|
||||
type = pair[1];
|
||||
%>
|
||||
outputs.<%= type %>('<%= name %>', results.<%= name %>)
|
||||
<% }); %>
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'text!./entry.ejs',
|
||||
'text!./main.ejs',
|
||||
+3
-4
@@ -1,15 +1,14 @@
|
||||
-- Serialization functions for:<%= types.map(function(type) {return type[0];}).join('\n-- ') %>
|
||||
-- Serialization functions for: <%= types.map(function(type) {return type[0];}).join('\n-- ') %>
|
||||
require 'paths'
|
||||
|
||||
local serializer = {}
|
||||
|
||||
<% types.forEach(function(pair) {
|
||||
var type = pair[0],
|
||||
fn = pair[1];
|
||||
%>
|
||||
function serializer.<%= type %> (name, data)
|
||||
local dir = paths.concat('outputs', name)
|
||||
os.execute('mkdir ' .. dir)
|
||||
local path = 'outputs/' .. name
|
||||
local abs_path = paths.concat('outputs', name)
|
||||
<%= fn.replace('\n', '\n ') %>
|
||||
end
|
||||
<% }); %>
|
||||
@@ -65,7 +65,7 @@ define([
|
||||
for (var i = 0; i < layers.length; i++) {
|
||||
if (layers[i][Constants.NEXT].length > 1) {
|
||||
// no support for
|
||||
console.error('No support for parallel layers... yet');
|
||||
this.logger.error('No support for parallel layers... yet');
|
||||
break;
|
||||
} else {
|
||||
// args
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* globals define */
|
||||
define([
|
||||
'SimpleNodes/Constants',
|
||||
'deepforge/lua'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* globals define */
|
||||
// This is the searcher for the mock library
|
||||
define([
|
||||
'deepforge/layer-args',
|
||||
@@ -10,10 +11,10 @@ define([
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var nop = function() {};
|
||||
var createSearcher = function(plugin) {
|
||||
var core = plugin.core,
|
||||
META = plugin.META,
|
||||
logger = plugin.logger.fork('nn'),
|
||||
parent = plugin.tgtNode,
|
||||
LayerDict = createLayerDict(core, META);
|
||||
|
||||
@@ -41,8 +42,7 @@ define([
|
||||
};
|
||||
|
||||
Layer.prototype._node = function() {
|
||||
var attrs = this._attrs,
|
||||
name,
|
||||
var name,
|
||||
node,
|
||||
value;
|
||||
|
||||
@@ -83,11 +83,11 @@ define([
|
||||
this._outputs = [];
|
||||
};
|
||||
|
||||
Container.prototype.add = function(self, tlayer) {
|
||||
console.error('Add is not overridden!');
|
||||
Container.prototype.add = function() {
|
||||
logger.error('Add is not overridden!');
|
||||
};
|
||||
|
||||
var Sequential = function(attrs, args) {
|
||||
var Sequential = function(/*attrs, args*/) {
|
||||
Container.call(this);
|
||||
};
|
||||
|
||||
@@ -95,8 +95,7 @@ define([
|
||||
|
||||
Sequential.prototype.add = function(self, tlayer) {
|
||||
var layer = tlayer.get('_node'),
|
||||
nodes = layer._inputs,
|
||||
conn;
|
||||
nodes = layer._inputs;
|
||||
|
||||
// If this._inputs is empty, add the layer to the inputs list
|
||||
if (this._inputs.length === 0) { // first node
|
||||
@@ -146,15 +145,12 @@ define([
|
||||
var CreateLayer = function(type) {
|
||||
var res = luajs.newContext()._G,
|
||||
attrs = [].slice.call(arguments, 1),
|
||||
proto,
|
||||
node;
|
||||
|
||||
if (LAYERS[type]) {
|
||||
node = new LAYERS[type](LayerDict[type] || [], attrs);
|
||||
proto = LAYERS[type].prototype;
|
||||
} else { // Call generic Layer with type name
|
||||
node = new Layer(type, LayerDict[type] || [], attrs);
|
||||
proto = Layer.prototype;
|
||||
}
|
||||
|
||||
res.set('_node', node);
|
||||
|
||||
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.
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcb09f0e67a5840a0579fa44353602b20a4203452c00b59796ce9bc2026666d2
|
||||
size 343292
|
||||
@@ -28,5 +28,59 @@
|
||||
"title": "OperationEditor",
|
||||
"panel": "panels/OperationEditor/OperationEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "PipelineEditor",
|
||||
"title": "PipelineEditor",
|
||||
"panel": "panels/PipelineEditor/PipelineEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "ExecutionView",
|
||||
"title": "ExecutionView",
|
||||
"panel": "panels/ExecutionView/ExecutionViewPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "DataTypeEditor",
|
||||
"title": "DataTypeEditor",
|
||||
"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
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 17 2016 11:25:46 GMT-0400 (EDT).
|
||||
@@ -7,23 +7,44 @@
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'js/NodePropertyNames',
|
||||
'js/Utils/ComponentSettings',
|
||||
'underscore'
|
||||
], function (
|
||||
EasyDAGControl,
|
||||
nodePropertyNames,
|
||||
ComponentSettings,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var ArchEditorControl;
|
||||
var ArchEditorControl,
|
||||
DEFAULT_CONFIG = {
|
||||
DefaultColor: '#ffb74d',
|
||||
LayerColors: {
|
||||
Containers: '#ffb74d',
|
||||
Module: '#ba68c8',
|
||||
ConvLayer: '#2196f3',
|
||||
SimpleLayer: '#ff9100',
|
||||
TransferLayer: '#80deea',
|
||||
MiscLayers: '#ce93d8',
|
||||
Criterion: '#7e57c2'
|
||||
}
|
||||
};
|
||||
|
||||
ArchEditorControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
this._config = DEFAULT_CONFIG;
|
||||
ComponentSettings.resolveWithWebGMEGlobal(this._config, this.getComponentId());
|
||||
};
|
||||
|
||||
_.extend(ArchEditorControl.prototype, EasyDAGControl.prototype);
|
||||
|
||||
ArchEditorControl.prototype.TERRITORY_RULE = {children: 1};
|
||||
ArchEditorControl.prototype.getComponentId = function() {
|
||||
return 'ArchEditor';
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._getObjectDescriptor = function(id) {
|
||||
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id);
|
||||
|
||||
@@ -42,32 +63,41 @@ define([
|
||||
}
|
||||
|
||||
// Add layer type (base class's base class)
|
||||
desc.layerType = null;
|
||||
if (desc.baseName) {
|
||||
var node = this._client.getNode(id),
|
||||
base = this._client.getNode(node.getMetaTypeId()),
|
||||
layerType = this._client.getNode(base.getBaseId());
|
||||
|
||||
if (layerType) {
|
||||
desc.layerType = layerType.getAttribute(nodePropertyNames.Attributes.name);
|
||||
}
|
||||
}
|
||||
desc.layerType = null;
|
||||
if (desc.baseName) {
|
||||
var node = this._client.getNode(id),
|
||||
base = this._client.getNode(node.getMetaTypeId()),
|
||||
layerType = this._client.getNode(base.getBaseId()),
|
||||
color;
|
||||
|
||||
desc.baseName = base.getAttribute(nodePropertyNames.Attributes.name);
|
||||
if (layerType) {
|
||||
desc.layerType = layerType.getAttribute(nodePropertyNames.Attributes.name);
|
||||
|
||||
color = this._config.LayerColors[desc.layerType];
|
||||
if (!color) {
|
||||
this._logger.warn(`No color found for ${desc.layerType}`);
|
||||
color = this._config.DefaultColor;
|
||||
}
|
||||
desc.color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._getValidInitialNodes = function() {
|
||||
return this._client.getChildrenMeta(this._currentNodeId).items
|
||||
// For now, anything is possible!
|
||||
// FIXME
|
||||
.map(info => this._getAllDescendentIds(info.id))
|
||||
.reduce((prev, curr) => prev.concat(curr))
|
||||
// Filter all abstract nodes
|
||||
.filter(nodeId => {
|
||||
return !this._client.getNode(nodeId).isAbstract();
|
||||
})
|
||||
.map(id => this._getObjectDescriptor(id))
|
||||
.filter(obj => !obj.isConnection && obj.name !== 'Connection');
|
||||
// For now, anything is possible!
|
||||
// FIXME
|
||||
.map(info => this._getAllDescendentIds(info.id))
|
||||
.reduce((prev, curr) => prev.concat(curr))
|
||||
// Filter all abstract nodes
|
||||
.filter(nodeId => {
|
||||
return !this._client.getNode(nodeId).isAbstract();
|
||||
})
|
||||
.map(id => this._getObjectDescriptor(id))
|
||||
.filter(obj => !obj.isConnection && obj.name !== 'Connection');
|
||||
};
|
||||
|
||||
return ArchEditorControl;
|
||||
|
||||
@@ -29,6 +29,7 @@ define([
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
@@ -55,6 +56,7 @@ define([
|
||||
this.control = new ArchEditorControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
embedded: this._embedded,
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/TilingViz/TilingVizPanel',
|
||||
'panels/SerializeEditor/SerializeEditorPanel',
|
||||
'panels/DeserializeEditor/DeserializeEditorPanel',
|
||||
'underscore'
|
||||
], function (
|
||||
TilingViz,
|
||||
SerializeEditor,
|
||||
DeserializeEditor,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var DataTypeEditorPanel;
|
||||
|
||||
DataTypeEditorPanel = function (layoutManager, params) {
|
||||
TilingViz.call(this, layoutManager, params);
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(DataTypeEditorPanel.prototype, TilingViz.prototype);
|
||||
|
||||
DataTypeEditorPanel.prototype.getPanels = function () {
|
||||
return [SerializeEditor, DeserializeEditor];
|
||||
};
|
||||
|
||||
return DataTypeEditorPanel;
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'underscore'
|
||||
], function (
|
||||
TextEditorControl,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var DeserializeEditorControl;
|
||||
|
||||
DeserializeEditorControl = function (options) {
|
||||
options.attributeName = 'deserialize';
|
||||
TextEditorControl.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
DeserializeEditorControl.prototype,
|
||||
TextEditorControl.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;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed Jun 01 2016 14:45:18 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/DeserializeEditor/DeserializeEditorWidget',
|
||||
'./DeserializeEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
DeserializeEditorWidget,
|
||||
DeserializeEditorControl) {
|
||||
'use strict';
|
||||
|
||||
var DeserializeEditorPanel;
|
||||
|
||||
DeserializeEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'DeserializeEditorPanel';
|
||||
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(DeserializeEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(DeserializeEditorPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
DeserializeEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new DeserializeEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new DeserializeEditorControl({
|
||||
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 */
|
||||
DeserializeEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
DeserializeEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
DeserializeEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
DeserializeEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
DeserializeEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return DeserializeEditorPanel;
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 24 2016 10:15:19 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'underscore'
|
||||
], function (
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var ExecutionViewControl;
|
||||
|
||||
ExecutionViewControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
this.addedNodes = {};
|
||||
};
|
||||
|
||||
_.extend(
|
||||
ExecutionViewControl.prototype,
|
||||
EasyDAGControl.prototype,
|
||||
PipelineControl.prototype
|
||||
);
|
||||
|
||||
/* * * * * * * * Visualizer content update callbacks * * * * * * * */
|
||||
ExecutionViewControl.prototype.TERRITORY_RULE = {children: 4};
|
||||
ExecutionViewControl.prototype.DEFAULT_DECORATOR = 'JobDecorator';
|
||||
|
||||
ExecutionViewControl.prototype._onLoad = function(id) {
|
||||
var desc = this._getObjectDescriptor(id);
|
||||
if (desc.parentId === this._currentNodeId) {
|
||||
this.addedNodes[id] = true;
|
||||
EasyDAGControl.prototype._onLoad.call(this, id);
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionViewControl.prototype._onUnload = function(id) {
|
||||
if (this.addedNodes[id] === true) {
|
||||
EasyDAGControl.prototype._onUnload.call(this, id);
|
||||
delete this.addedNodes[id];
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionViewControl.prototype._onUpdate = function(id) {
|
||||
if (this.addedNodes[id] === true) {
|
||||
EasyDAGControl.prototype._onUpdate.call(this, id);
|
||||
}
|
||||
};
|
||||
|
||||
// Add the connection detection
|
||||
return ExecutionViewControl;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 24 2016 10:15:19 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/ExecutionView/ExecutionViewWidget',
|
||||
'./ExecutionViewControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
ExecutionViewWidget,
|
||||
ExecutionViewControl) {
|
||||
'use strict';
|
||||
|
||||
var ExecutionViewPanel;
|
||||
|
||||
ExecutionViewPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'ExecutionViewPanel';
|
||||
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(ExecutionViewPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(ExecutionViewPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
ExecutionViewPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new ExecutionViewWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new ExecutionViewControl({
|
||||
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 */
|
||||
ExecutionViewPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
ExecutionViewPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
ExecutionViewPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
ExecutionViewPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
ExecutionViewPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return ExecutionViewPanel;
|
||||
});
|
||||
@@ -1,35 +1,124 @@
|
||||
/*globals WebGMEGlobal*/
|
||||
/*globals define, WebGMEGlobal*/
|
||||
// These are actions defined for specific meta types. They are evaluated from
|
||||
// the context of the ForgeActionButton
|
||||
define([], function() {
|
||||
var ROOT_ID = '',
|
||||
CREATE_MODEL_TXT = 'Create new model';
|
||||
define([
|
||||
'js/RegistryKeys',
|
||||
'js/Panels/MetaEditor/MetaEditorConstants',
|
||||
'js/Constants'
|
||||
], function(
|
||||
REGISTRY_KEYS,
|
||||
META_CONSTANTS,
|
||||
CONSTANTS
|
||||
) {
|
||||
var instances = [
|
||||
'Architecture',
|
||||
'Pipeline'
|
||||
],
|
||||
metaNodes = [
|
||||
'Operation',
|
||||
'Data'
|
||||
],
|
||||
create = {};
|
||||
|
||||
var createNewArchitecture = function(type) {
|
||||
return createNew.call(this, 'Architecture');
|
||||
var getUniqueName = function(parentId, basename) {
|
||||
var pNode = this.client.getNode(parentId),
|
||||
children = pNode.getChildrenIds().map(id => this.client.getNode(id)),
|
||||
name = basename,
|
||||
exists = {},
|
||||
i = 2;
|
||||
|
||||
children.forEach(child => exists[child.getAttribute('name')] = true);
|
||||
|
||||
while (exists[name]) {
|
||||
name = basename + '_' + i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
var createNewPipeline = function(type) {
|
||||
return createNew.call(this, 'Pipeline');
|
||||
};
|
||||
|
||||
var createNew = function(type) {
|
||||
var createNew = function(type, metasheetName) {
|
||||
// Create CNN node in the current dir
|
||||
// Get CNN node type
|
||||
var parentId = this._currentNodeId,
|
||||
baseId = this.client.getAllMetaNodes()
|
||||
newId,
|
||||
baseId;
|
||||
|
||||
baseId = this.client.getAllMetaNodes()
|
||||
.find(node => node.getAttribute('name') === type)
|
||||
.getId();
|
||||
|
||||
this.client.createChild({parentId, baseId});
|
||||
this.client.startTransaction('Created new operation prototype');
|
||||
newId = this.client.createChild({parentId, baseId});
|
||||
|
||||
// Name the new node
|
||||
var basename = 'New' + this.client.getNode(baseId).getAttribute('name'),
|
||||
newName = getUniqueName.call(this, parentId, basename);
|
||||
|
||||
// If instance, make the first char lowercase
|
||||
if (!metasheetName) {
|
||||
newName = newName.substring(0, 1).toLowerCase() + newName.substring(1);
|
||||
}
|
||||
|
||||
this.client.setAttributes(newId, 'name', newName);
|
||||
if (metasheetName) { // Add to metasheet
|
||||
var root = this.client.getNode(CONSTANTS.PROJECT_ROOT_ID),
|
||||
metatabs = root.getRegistry(REGISTRY_KEYS.META_SHEETS),
|
||||
metatab = metatabs.find(tab => tab.title === metasheetName) || metatabs[0],
|
||||
metatabId = metatab.SetID;
|
||||
|
||||
// Add to the general meta
|
||||
this.client.addMember(
|
||||
CONSTANTS.PROJECT_ROOT_ID,
|
||||
newId,
|
||||
META_CONSTANTS.META_ASPECT_SET_NAME
|
||||
);
|
||||
this.client.setMemberRegistry(
|
||||
CONSTANTS.PROJECT_ROOT_ID,
|
||||
newId,
|
||||
META_CONSTANTS.META_ASPECT_SET_NAME,
|
||||
REGISTRY_KEYS.POSITION,
|
||||
{
|
||||
x: 100,
|
||||
y: 100
|
||||
}
|
||||
);
|
||||
|
||||
// Add to the specific sheet
|
||||
this.client.addMember(CONSTANTS.PROJECT_ROOT_ID, newId, metatabId);
|
||||
this.client.setMemberRegistry(
|
||||
CONSTANTS.PROJECT_ROOT_ID,
|
||||
newId,
|
||||
metatabId,
|
||||
REGISTRY_KEYS.POSITION,
|
||||
{
|
||||
x: 100,
|
||||
y: 100
|
||||
}
|
||||
);
|
||||
}
|
||||
this.client.completeTransaction();
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
};
|
||||
|
||||
instances.forEach(type => {
|
||||
create[type] = function() {
|
||||
return createNew.call(this, type);
|
||||
};
|
||||
});
|
||||
|
||||
metaNodes.forEach(type => {
|
||||
create[type] = function() {
|
||||
return createNew.call(this, type, type);
|
||||
};
|
||||
});
|
||||
|
||||
// Add download model button
|
||||
var downloadButton = function() {
|
||||
var id = this._currentNodeId,
|
||||
node = this.client.getNode(id),
|
||||
hash = node.getAttribute('data'),
|
||||
url;
|
||||
hash = node.getAttribute('data');
|
||||
|
||||
if (hash) {
|
||||
return '/rest/blob/download/' + hash;
|
||||
@@ -46,18 +135,42 @@ define([], function() {
|
||||
}
|
||||
],
|
||||
|
||||
Pipelines: [
|
||||
MyPipelines_META: [
|
||||
{
|
||||
name: 'Create new pipeline',
|
||||
icon: 'queue',
|
||||
action: createNewPipeline
|
||||
action: create.Pipeline
|
||||
}
|
||||
],
|
||||
Architectures: [
|
||||
MyArchitectures_META: [
|
||||
{
|
||||
name: 'Create new architecture',
|
||||
icon: 'queue',
|
||||
action: createNewArchitecture
|
||||
action: create.Architecture
|
||||
}
|
||||
],
|
||||
MyDataTypes_META: [
|
||||
{
|
||||
name: 'Create new data type',
|
||||
icon: 'queue',
|
||||
action: create.Data
|
||||
}
|
||||
],
|
||||
MyOperations_META: [
|
||||
{
|
||||
name: 'Create new operation',
|
||||
icon: 'queue',
|
||||
action: create.Operation
|
||||
}
|
||||
],
|
||||
Pipeline: [
|
||||
{
|
||||
name: 'Create new node',
|
||||
icon: 'queue',
|
||||
priority: 2,
|
||||
action: function() {
|
||||
this.onCreateInitialNode();
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*globals define, _ */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'panel/FloatingActionButton/FloatingActionButton',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'./Actions',
|
||||
'text!./PluginConfig.json'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
PluginButton,
|
||||
PipelineControl,
|
||||
ACTIONS,
|
||||
PluginConfig
|
||||
) {
|
||||
@@ -17,27 +19,42 @@ define([
|
||||
var ForgeActionButton= function (layoutManager, params) {
|
||||
PluginButton.call(this, layoutManager, params);
|
||||
this._pluginConfig = JSON.parse(PluginConfig);
|
||||
this._client = this.client;
|
||||
this._actions = [];
|
||||
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
|
||||
this.addActionsForObject, this);
|
||||
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
// inherit from PanelBaseWithHeader
|
||||
_.extend(ForgeActionButton.prototype, PluginButton.prototype);
|
||||
_.extend(
|
||||
ForgeActionButton.prototype,
|
||||
PluginButton.prototype,
|
||||
PipelineControl.prototype
|
||||
);
|
||||
|
||||
ForgeActionButton.prototype.addActionsForObject = function(models, nodeId) {
|
||||
var baseName,
|
||||
node = this.client.getNode(nodeId),
|
||||
ForgeActionButton.prototype.findActionsFor = function(nodeId) {
|
||||
var node = this.client.getNode(nodeId),
|
||||
base = this.client.getNode(node.getMetaTypeId()),
|
||||
base,
|
||||
actions,
|
||||
i;
|
||||
isMeta = base && base.getId() === node.getId(),
|
||||
suffix = isMeta ? '_META' : '',
|
||||
basename;
|
||||
|
||||
// Get node baseName and look up actions
|
||||
baseName = base ? base.getAttribute('name') : 'ROOT';
|
||||
while (base && !ACTIONS[basename]) {
|
||||
basename = base.getAttribute('name') + suffix;
|
||||
base = this.client.getNode(base.getBaseId());
|
||||
}
|
||||
|
||||
return ACTIONS[basename] || [];
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.onNodeLoad = function(nodeId) {
|
||||
PluginButton.prototype.onNodeLoad.call(this, nodeId);
|
||||
this.addActionsForObject(nodeId);
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.addActionsForObject = function(nodeId) {
|
||||
var actions = this.findActionsFor(nodeId),
|
||||
i;
|
||||
|
||||
// Remove old actions
|
||||
for (i = this._actions.length; i--;) {
|
||||
@@ -45,7 +62,6 @@ define([
|
||||
}
|
||||
|
||||
// Get node name and look up actions
|
||||
actions = ACTIONS[baseName] || [];
|
||||
for (i = actions.length; i--;) {
|
||||
this.buttons[actions[i].name] = actions[i];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'deepforge/viz/OperationControl',
|
||||
'underscore'
|
||||
], function (
|
||||
TextEditorControl,
|
||||
OperationControl,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OperationCodeEditorControl;
|
||||
|
||||
OperationCodeEditorControl = function (options) {
|
||||
options.attributeName = 'code';
|
||||
TextEditorControl.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
OperationCodeEditorControl.prototype,
|
||||
OperationControl.prototype,
|
||||
TextEditorControl.prototype
|
||||
);
|
||||
|
||||
// Override ObjectDescriptor
|
||||
OperationCodeEditorControl.prototype.TERRITORY_RULE = {children: 3};
|
||||
OperationCodeEditorControl.prototype._getObjectDescriptor = function (id) {
|
||||
var desc = TextEditorControl.prototype._getObjectDescriptor.call(this, id),
|
||||
node = this._client.getNode(id);
|
||||
|
||||
// Add the inputs, outputs, references, and attributes
|
||||
desc.inputs = this.getOperationInputs(node).map(id => this.formatIO(id));
|
||||
desc.outputs = this.getOperationOutputs(node).map(id => this.formatIO(id));
|
||||
desc.references = node.getPointerNames().filter(name => name !== 'base');
|
||||
return desc;
|
||||
};
|
||||
|
||||
// This will be changed when the input/output reps are updated (soon)
|
||||
OperationCodeEditorControl.prototype.formatIO = function (id) {
|
||||
// parse arguments are in the form 'arg: Type1, arg2: Type2'
|
||||
// and return [[arg1, Type1], [arg2, Type2]]
|
||||
var node = this._client.getNode(id),
|
||||
mNode = this._client.getNode(node.getMetaTypeId());
|
||||
|
||||
return [node, mNode].map(n => n.getAttribute('name'));
|
||||
};
|
||||
|
||||
// input/output updates are actually activeNode updates
|
||||
OperationCodeEditorControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId || this.hasMetaName(id, 'Data')) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, this._currentNodeId);
|
||||
}
|
||||
};
|
||||
|
||||
return OperationCodeEditorControl;
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/OperationCodeEditor/OperationCodeEditorWidget',
|
||||
'./OperationCodeEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
OperationCodeEditorWidget,
|
||||
OperationCodeEditorControl) {
|
||||
'use strict';
|
||||
|
||||
var OperationCodeEditorPanel;
|
||||
|
||||
OperationCodeEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'OperationCodeEditorPanel';
|
||||
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(OperationCodeEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(OperationCodeEditorPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
OperationCodeEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new OperationCodeEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new OperationCodeEditorControl({
|
||||
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 */
|
||||
OperationCodeEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
OperationCodeEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
OperationCodeEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationCodeEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationCodeEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return OperationCodeEditorPanel;
|
||||
});
|
||||
@@ -1,47 +0,0 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'underscore'
|
||||
], function (
|
||||
TextEditorControl,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var OperationEditorControl;
|
||||
|
||||
OperationEditorControl = function (options) {
|
||||
options.attributeName = 'code';
|
||||
TextEditorControl.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(OperationEditorControl.prototype, TextEditorControl.prototype);
|
||||
|
||||
// Override ObjectDescriptor
|
||||
OperationEditorControl.prototype._getObjectDescriptor = function (id) {
|
||||
var desc = TextEditorControl.prototype._getObjectDescriptor.call(this, id),
|
||||
node = this._client.getNode(id);
|
||||
// Add the inputs, outputs, references, and attributes
|
||||
desc.inputs = this._parseArgs(node.getAttribute('inputs'));
|
||||
desc.outputs = this._parseArgs(node.getAttribute('outputs'));
|
||||
desc.references = node.getPointerNames().filter(name => name !== 'base');
|
||||
return desc;
|
||||
};
|
||||
|
||||
// This will be changed when the input/output reps are updated (soon)
|
||||
OperationEditorControl.prototype._parseArgs = function (args) {
|
||||
// parse arguments are in the form 'arg: Type1, arg2: Type2'
|
||||
// and return [[arg1, Type1], [arg2, Type2]]
|
||||
return args ? args.split(',')
|
||||
.map(pair => pair.split(':').map(w => w.replace(/\s+/g, ''))) : [];
|
||||
|
||||
};
|
||||
|
||||
return OperationEditorControl;
|
||||
});
|
||||
@@ -1,98 +1,30 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*globals define, */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/OperationEditor/OperationEditorWidget',
|
||||
'./OperationEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
OperationEditorWidget,
|
||||
OperationEditorControl) {
|
||||
define([
|
||||
'panels/TilingViz/TilingVizPanel',
|
||||
'panels/OperationCodeEditor/OperationCodeEditorPanel',
|
||||
'panels/OperationInterfaceEditor/OperationInterfaceEditorPanel',
|
||||
'underscore'
|
||||
], function (
|
||||
TilingViz,
|
||||
CodeEditor,
|
||||
InterfaceEditor,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var OperationEditorPanel;
|
||||
|
||||
OperationEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'OperationEditorPanel';
|
||||
options[PanelBaseWithHeader.OPTIONS.FLOATING_TITLE] = true;
|
||||
|
||||
//call parent's constructor
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
|
||||
this.logger.debug('ctor finished');
|
||||
TilingViz.call(this, layoutManager, params);
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(OperationEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(OperationEditorPanel.prototype, IActivePanel.prototype);
|
||||
//inherit from TilingViz
|
||||
_.extend(OperationEditorPanel.prototype, TilingViz.prototype);
|
||||
|
||||
OperationEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new OperationEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new OperationEditorControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
OperationEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
OperationEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
OperationEditorPanel.prototype.getPanels = function () {
|
||||
return [CodeEditor, InterfaceEditor];
|
||||
};
|
||||
|
||||
return OperationEditorPanel;
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
'use strict';
|
||||
var OperationInterfaceEditorEvents = function() {
|
||||
this._widget.allDataTypeIds = this.allDataTypeIds.bind(this);
|
||||
this._widget.allValidReferences = this.allValidReferences.bind(this);
|
||||
this._widget.addRefTo = this.addRefTo.bind(this);
|
||||
this._widget.changePtrName = this.changePtrName.bind(this);
|
||||
this._widget.removePtr = this.removePtr.bind(this);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allValidReferences = function() {
|
||||
// Get all meta nodes that...
|
||||
// - are not data, pipeline or operation (or fco!)
|
||||
// - have a plugin defined?
|
||||
// Currently you can't reference operations or pipelines.
|
||||
var notTypes = ['Data', 'Operation', 'Pipeline'];
|
||||
return this._client.getAllMetaNodes()
|
||||
.filter(node => {
|
||||
var plugins = node.getRegistry('validPlugins');
|
||||
// Convention is enforced; if the plugin generates lua artifacts,
|
||||
// it should be called `Generate`.. (something)
|
||||
return plugins && plugins.indexOf('Generate') !== -1;
|
||||
})
|
||||
.filter(node => notTypes.reduce((valid, name) =>
|
||||
valid && !this.hasMetaName(node.getId(), name), true))
|
||||
.filter(node => node.getAttribute('name') !== 'FCO')
|
||||
.map(node => {
|
||||
return {
|
||||
node: this._getObjectDescriptor(node.getId())
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypeIds = function() {
|
||||
return this.allDataTypes().map(node => node.getId());
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.allDataTypes = function() {
|
||||
return this._client.getAllMetaNodes()
|
||||
.filter(node => this.hasMetaName(node.getId(), 'Data'));
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype._getValidSuccessorNodes = function(nodeId) {
|
||||
// Return all data types in the meta
|
||||
if (nodeId !== this._currentNodeId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.allDataTypeIds().map(id => {
|
||||
return {
|
||||
node: this._getObjectDescriptor(id)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype._getDataName = function(cntrId, typeId) {
|
||||
var otherIds = this._client.getNode(cntrId).getChildrenIds(),
|
||||
otherNames = otherIds.map(id => this._client.getNode(id).getAttribute('name')),
|
||||
baseName = this._client.getNode(typeId).getAttribute('name').toLowerCase(),
|
||||
name = baseName,
|
||||
i = 1;
|
||||
|
||||
while (otherNames.indexOf(name) !== -1) {
|
||||
i++;
|
||||
name = baseName + '_' + i;
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.getRefName = function(node, basename) {
|
||||
// Get a dict of all invalid ptr names for the given node
|
||||
var invalid = {},
|
||||
name,
|
||||
i = 2;
|
||||
|
||||
name = basename;
|
||||
node.getSetNames().concat(node.getPointerNames())
|
||||
.forEach(ptr => invalid[ptr] = true);
|
||||
|
||||
while (invalid[name]) {
|
||||
name = basename + '_' + i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.addRefTo = function(targetId) {
|
||||
// Create a reference from the current node to the given type
|
||||
var opNode = this._client.getNode(this._currentNodeId),
|
||||
target = this._client.getNode(targetId),
|
||||
desiredName = target.getAttribute('name').toLowerCase(),
|
||||
ptrName = this.getRefName(opNode, desiredName),
|
||||
msg = `Adding ref "${ptrName}" to operation "${opNode.getAttribute('name')}"`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setPointerMeta(this._currentNodeId, ptrName, {
|
||||
min: 1,
|
||||
max: 1,
|
||||
items: [
|
||||
{
|
||||
id: targetId,
|
||||
max: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
this._client.makePointer(this._currentNodeId, ptrName, null);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.changePtrName = function(from, to) {
|
||||
var opNode = this._client.getNode(this._currentNodeId),
|
||||
name = opNode.getAttribute('name'),
|
||||
msg = `Renaming ref from "${from}" to "${to}" for ${name}`,
|
||||
meta = this._client.getPointerMeta(this._currentNodeId, from),
|
||||
ptrName;
|
||||
|
||||
ptrName = this.getRefName(opNode, to);
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
|
||||
// Currently, this will not update children already using old name...
|
||||
this._client.deleteMetaPointer(this._currentNodeId, from);
|
||||
this._client.delPointer(this._currentNodeId, from);
|
||||
this._client.setPointerMeta(this._currentNodeId, ptrName, meta);
|
||||
this._client.makePointer(this._currentNodeId, ptrName, null);
|
||||
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.removePtr = function(name) {
|
||||
var opName = this._client.getNode(this._currentNodeId).getAttribute('name'),
|
||||
msg = `Removing ref "${name}" from "${opName}" operation`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
// Currently, this will not update children already using old name...
|
||||
this._client.deleteMetaPointer(this._currentNodeId, name);
|
||||
this._client.delPointer(this._currentNodeId, name);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype._createConnectedNode = function(typeId, isInput) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
name = node.getAttribute('name'),
|
||||
cntrs = node.getChildrenIds(),
|
||||
cntrType = isInput ? 'Inputs' : 'Outputs',
|
||||
cntrId = cntrs.find(id => this.hasMetaName(id, cntrType)),
|
||||
dataName = this._getDataName(cntrId, typeId),
|
||||
msg;
|
||||
|
||||
msg = `Adding ${isInput ? 'input' : 'output'} "${dataName}" to ${name} interface`;
|
||||
this._client.startTransaction(msg);
|
||||
var id = this._client.createChild({
|
||||
parentId: cntrId,
|
||||
baseId: typeId
|
||||
});
|
||||
|
||||
// Set the name of the new input
|
||||
this._client.setAttributes(id, 'name', dataName);
|
||||
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorEvents;
|
||||
});
|
||||
@@ -0,0 +1,286 @@
|
||||
/*globals define, */
|
||||
/*jshint browser: true*/
|
||||
// OpInterface visualizes the interface of the given operation and allows the
|
||||
// user to edit the meta definition of the given operation. That is, it will
|
||||
// show the operation's input data nodes as incoming connections; outputs as
|
||||
// outgoing connections and the defined attributes/ptrs in the expanded view
|
||||
// of the node.
|
||||
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'js/Constants',
|
||||
'deepforge/viz/OperationControl',
|
||||
'./OperationInterfaceEditorControl.EventHandlers',
|
||||
'underscore'
|
||||
], function (
|
||||
EasyDAGControl,
|
||||
CONSTANTS,
|
||||
OperationControl,
|
||||
OperationInterfaceEditorControlEvents,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var CONN_ID = 0,
|
||||
OperationInterfaceEditorControl;
|
||||
|
||||
OperationInterfaceEditorControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
OperationInterfaceEditorControlEvents.call(this);
|
||||
this._connections = {};
|
||||
this._pointers = {};
|
||||
};
|
||||
|
||||
_.extend(
|
||||
OperationInterfaceEditorControl.prototype,
|
||||
EasyDAGControl.prototype,
|
||||
OperationControl.prototype,
|
||||
OperationInterfaceEditorControlEvents.prototype
|
||||
);
|
||||
|
||||
OperationInterfaceEditorControl.prototype.TERRITORY_RULE = {children: 3};
|
||||
OperationInterfaceEditorControl.prototype.DEFAULT_DECORATOR = 'OpIntDecorator';
|
||||
OperationInterfaceEditorControl.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;
|
||||
this._currentNodeParentId = undefined;
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
var node = this._client.getNode(nodeId),
|
||||
name = node.getAttribute('name'),
|
||||
parentId = node.getParentId();
|
||||
|
||||
this._widget.setTitle(name.toUpperCase());
|
||||
|
||||
if (typeof parentId === 'string') {
|
||||
this.$btnModelHierarchyUp.show();
|
||||
} else {
|
||||
this.$btnModelHierarchyUp.hide();
|
||||
}
|
||||
|
||||
this._currentNodeParentId = parentId;
|
||||
|
||||
// Put new node's info into territory rules
|
||||
this.updateTerritory();
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._eventCallback = function (events) {
|
||||
var event;
|
||||
|
||||
// Remove any events about the current node
|
||||
this._logger.debug('_eventCallback \'' + i + '\' items');
|
||||
|
||||
for (var i = 0; i < events.length; 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');
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.updateTerritory = function() {
|
||||
var nodeId = this._currentNodeId;
|
||||
|
||||
// activeNode rules
|
||||
this._territories = {};
|
||||
|
||||
this._territoryId = this._client.addUI(this, events => {
|
||||
this._eventCallback(events);
|
||||
});
|
||||
|
||||
this._territories[nodeId] = {children: 0}; // Territory "rule"
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
this._logger.debug(`OpIntEditor current territory id is ${this._territoryId}`);
|
||||
|
||||
this._territories[nodeId] = this.TERRITORY_RULE;
|
||||
|
||||
// Add the operation definitions to the territory
|
||||
var metanodes = this._client.getAllMetaNodes(),
|
||||
operation = metanodes.find(n => n.getAttribute('name') === 'Data');
|
||||
|
||||
// Get all the meta nodes that are instances of Data
|
||||
metanodes.map(n => n.getId())
|
||||
.filter(nId => this._client.isTypeOf(nId, operation.getId()))
|
||||
// Add a rule for them
|
||||
.forEach(opId => this._territories[opId] = {children: 0});
|
||||
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._getObjectDescriptor = function(gmeId) {
|
||||
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, gmeId);
|
||||
// Check if it is...
|
||||
// - input data
|
||||
// - output data
|
||||
// - operation node
|
||||
if (desc.id !== this._currentNodeId && this.containedInCurrent(gmeId)) {
|
||||
var cntrType = this._client.getNode(desc.parentId).getMetaTypeId();
|
||||
var cntr = this._client.getNode(cntrType).getAttribute('name');
|
||||
|
||||
desc.container = cntr.toLowerCase();
|
||||
desc.attributes = {};
|
||||
} else if (desc.id === this._currentNodeId) {
|
||||
delete desc.attributes.code;
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onUnload = function(gmeId) {
|
||||
EasyDAGControl.prototype._onUnload.call(this, gmeId);
|
||||
var conn = this._connections[gmeId];
|
||||
if (conn) {
|
||||
this._widget.removeNode(conn.id);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onLoad = function(gmeId) {
|
||||
var desc;
|
||||
if (this._currentNodeId === gmeId) {
|
||||
desc = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(desc);
|
||||
|
||||
// Create nodes for the valid pointers
|
||||
this.updatePtrs();
|
||||
|
||||
} else if (this.hasMetaName(gmeId, 'Data') && this.containedInCurrent(gmeId)) {
|
||||
desc = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(desc);
|
||||
this.createConnection(desc);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype._onUpdate = function(gmeId) {
|
||||
if (gmeId === this._currentNodeId) {
|
||||
EasyDAGControl.prototype._onUpdate.call(this, gmeId);
|
||||
|
||||
// Update the valid pointers
|
||||
this.updatePtrs();
|
||||
|
||||
} else if (this.containedInCurrent(gmeId) && this.hasMetaName(gmeId, 'Data')) {
|
||||
EasyDAGControl.prototype._onUpdate.call(this, gmeId);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.loadMeta = function() {
|
||||
// Load the metamodel. This is kinda a hack to make sure
|
||||
// the meta nodes are accessible with `this._client.getNode`
|
||||
return this._client.getAllMetaNodes();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.getPtrDescriptor = function(name) {
|
||||
var targetId = this._client.getPointerMeta(this._currentNodeId, name)
|
||||
.items[0].id,
|
||||
target = this._client.getNode(targetId),
|
||||
decManager = this._client.decoratorManager,
|
||||
Decorator = decManager.getDecoratorForWidget('OpIntPtrDecorator', 'EasyDAG');
|
||||
|
||||
return {
|
||||
id: 'ptr_'+name,
|
||||
isPointer: true,
|
||||
baseName: target.getAttribute('name'),
|
||||
Decorator: Decorator,
|
||||
attributes: {},
|
||||
name: name,
|
||||
parentId: this._currentNodeId
|
||||
};
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.updatePtrs = function() {
|
||||
// Update the pointer nodes for the current node
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
rmPtrs,
|
||||
updatePtrs = [],
|
||||
newPtrs,
|
||||
newPtrDict = {},
|
||||
ptr;
|
||||
|
||||
// Get the pointers that should exist [name, target]
|
||||
this.loadMeta();
|
||||
newPtrs = node.getPointerNames()
|
||||
.filter(name => name !== CONSTANTS.POINTER_BASE)
|
||||
.map(name => this.getPtrDescriptor(name));
|
||||
|
||||
// Compare them to the existing...
|
||||
for (var i = newPtrs.length; i--;) {
|
||||
ptr = newPtrs[i];
|
||||
if (this._pointers[ptr.id]) { // Check for update
|
||||
updatePtrs.push(ptr);
|
||||
newPtrs.splice(i, 1);
|
||||
newPtrDict[ptr.id] = ptr;
|
||||
delete this._pointers[ptr.id];
|
||||
}
|
||||
}
|
||||
|
||||
rmPtrs = Object.keys(this._pointers);
|
||||
|
||||
// Remove ones that should no longer exist
|
||||
rmPtrs.forEach(id => this.rmPtr(id));
|
||||
|
||||
// Add ones that should
|
||||
this._pointers = newPtrDict;
|
||||
newPtrs.forEach(desc => this.addPtr(desc));
|
||||
updatePtrs.forEach(desc => this.updatePtr(desc));
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.addPtr = function(desc) {
|
||||
this._widget.addNode(desc);
|
||||
this._pointers[desc.id] = desc;
|
||||
this.createConnection(desc);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.updatePtr = function(desc) {
|
||||
this._widget.updateNode(desc);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.rmPtr = function(id) {
|
||||
// Remove the pointer's node
|
||||
this._widget.removeNode(id);
|
||||
// and connection
|
||||
var conn = this._connections[id];
|
||||
this._widget.removeNode(conn.id);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.containedInCurrent = function(id) {
|
||||
return id.indexOf(this._currentNodeId) === 0;
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.createConnection = function(desc) {
|
||||
var conn = {};
|
||||
conn.id = `CONN_${++CONN_ID}`;
|
||||
|
||||
if (desc.container === 'outputs') {
|
||||
conn.src = this._currentNodeId;
|
||||
conn.dst = desc.id;
|
||||
} else {
|
||||
conn.src = desc.id;
|
||||
conn.dst = this._currentNodeId;
|
||||
}
|
||||
// Create a connection either to or from desc & the currentNode
|
||||
this._widget.addConnection(conn);
|
||||
this._connections[desc.id] = conn;
|
||||
|
||||
return conn;
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorControl;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 31 2016 09:16:24 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/OperationInterfaceEditor/OperationInterfaceEditorWidget',
|
||||
'./OperationInterfaceEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
OperationInterfaceEditorWidget,
|
||||
OperationInterfaceEditorControl) {
|
||||
'use strict';
|
||||
|
||||
var OperationInterfaceEditorPanel;
|
||||
|
||||
OperationInterfaceEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'OperationInterfaceEditorPanel';
|
||||
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(OperationInterfaceEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(OperationInterfaceEditorPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
OperationInterfaceEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new OperationInterfaceEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new OperationInterfaceEditorControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
widget: this.widget,
|
||||
embedded: this._embedded
|
||||
});
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
OperationInterfaceEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
OperationInterfaceEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
OperationInterfaceEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorPanel;
|
||||
});
|
||||
@@ -0,0 +1,422 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'common/core/coreQ',
|
||||
'common/storage/constants',
|
||||
'q',
|
||||
'underscore'
|
||||
], function (
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
Core,
|
||||
STORAGE_CONSTANTS,
|
||||
Q,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var PipelineEditorControl,
|
||||
CONN = {
|
||||
SRC: 'src',
|
||||
DST: 'dst'
|
||||
};
|
||||
|
||||
PipelineEditorControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
this.addedIds = {};
|
||||
};
|
||||
|
||||
_.extend(
|
||||
PipelineEditorControl.prototype,
|
||||
EasyDAGControl.prototype,
|
||||
PipelineControl.prototype
|
||||
);
|
||||
|
||||
PipelineEditorControl.prototype._getValidInitialNodes =
|
||||
PipelineControl.prototype.getValidInitialNodes;
|
||||
|
||||
PipelineEditorControl.prototype.TERRITORY_RULE = {children: 3};
|
||||
PipelineEditorControl.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;
|
||||
this._currentNodeParentId = undefined;
|
||||
|
||||
if (typeof this._currentNodeId === 'string') {
|
||||
var desc = this._getObjectDescriptor(nodeId);
|
||||
this._widget.setTitle(desc.name.toUpperCase());
|
||||
|
||||
if (typeof desc.parentId === 'string') {
|
||||
this.$btnModelHierarchyUp.show();
|
||||
} else {
|
||||
this.$btnModelHierarchyUp.hide();
|
||||
}
|
||||
|
||||
this._currentNodeParentId = desc.parentId;
|
||||
|
||||
// Put new node's info into territory rules
|
||||
this.updateTerritory();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.updateTerritory = function() {
|
||||
var nodeId = this._currentNodeId;
|
||||
|
||||
// activeNode rules
|
||||
this._territories = {};
|
||||
|
||||
this._territoryId = this._client.addUI(this, events => {
|
||||
this._eventCallback(events);
|
||||
});
|
||||
this._logger.debug(`PipelineEditor territory id is ${this._territoryId}`);
|
||||
|
||||
this._territories[nodeId] = {children: 0}; // Territory "rule"
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
|
||||
this._territories[nodeId] = this.TERRITORY_RULE;
|
||||
|
||||
// Add the operation definitions to the territory
|
||||
var metanodes = this._client.getAllMetaNodes(),
|
||||
operation = metanodes.find(n => n.getAttribute('name') === 'Operation');
|
||||
|
||||
// Get all the meta nodes that are instances of Operations
|
||||
metanodes.map(n => n.getId())
|
||||
.filter(nId => this._client.isTypeOf(nId, operation.getId()))
|
||||
// Add a rule for them
|
||||
.forEach(opId => this._territories[opId] = this.TERRITORY_RULE);
|
||||
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._initWidgetEventHandlers = function () {
|
||||
EasyDAGControl.prototype._initWidgetEventHandlers.call(this);
|
||||
this._widget.getExistingPortMatches = this.getExistingPortMatches.bind(this);
|
||||
this._widget.createConnection = this.createConnection.bind(this);
|
||||
this._widget.removeConnection = this.removeConnection.bind(this);
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.isContainedInActive = function (gmeId) {
|
||||
// Check if the given id is contained in the active node
|
||||
return gmeId.indexOf(this._currentNodeId) === 0;
|
||||
};
|
||||
|
||||
////////////////////// Node Load/Update/Unload Overrides //////////////////////
|
||||
// Filter out the child nodes (bc of the larger territory)
|
||||
PipelineEditorControl.prototype._onLoad = function (gmeId) {
|
||||
var desc = this._getObjectDescriptor(gmeId);
|
||||
if (desc.parentId === this._currentNodeId) {
|
||||
this.addedIds[desc.id] = true;
|
||||
return EasyDAGControl.prototype._onLoad.call(this, gmeId);
|
||||
} else if (this.isContainedInActive(desc.parentId) && desc.isDataPort) {
|
||||
// port added!
|
||||
this.addedIds[desc.id] = true;
|
||||
this._widget.addPort(desc);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._onUnload = function (gmeId) {
|
||||
// Check if it has been added
|
||||
if(this.addedIds[gmeId]) {
|
||||
delete this.addedIds[gmeId];
|
||||
return EasyDAGControl.prototype._onUnload.call(this, gmeId);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._onUpdate = function (gmeId) {
|
||||
var desc = this._getObjectDescriptor(gmeId);
|
||||
if (desc.isDataPort && this.isContainedInActive(desc.parentId)) { // port added!
|
||||
this._widget.updatePort(desc);
|
||||
} else if (desc.isConnection) {
|
||||
this._widget.updateConnection(desc);
|
||||
} else if (desc.parentId === this._currentNodeId) {
|
||||
this._widget.updateNode(desc);
|
||||
} // Ignore any other updates - ie, Inputs/Outputs containers
|
||||
};
|
||||
|
||||
// Override the getSuccessors method to look up successors by operations
|
||||
// with input nodes of the selected node's output type (prioritize the
|
||||
// valid nodes that are using an unused output type, if one exists, ow
|
||||
// prioritize based on current outgoing connections count).
|
||||
// TODO
|
||||
|
||||
PipelineEditorControl.prototype.hasValidOutputs = function (inputId, outputs) {
|
||||
return this.getValidOutputs(inputId, outputs);
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.getValidOutputs = function (inputId, outputs) {
|
||||
// Valid input if one of the isTypeOf(<output>, inputId)
|
||||
// for at least one output
|
||||
var inputType = this._client.getNode(inputId).getMetaTypeId();
|
||||
return outputs.filter(type => this._client.isTypeOf(type, inputType)).length;
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._getValidSuccessorNodes = function (nodeId) {
|
||||
// Get all valid children
|
||||
var node = this._client.getNode(nodeId),
|
||||
children,
|
||||
outputs;
|
||||
|
||||
children = this._getAllValidChildren(node.getParentId())
|
||||
.map(id => this._client.getNode(id));
|
||||
|
||||
// Get all valid data output types of 'nodeId'
|
||||
outputs = this.getOperationOutputs(node)
|
||||
.map(id => this._client.getNode(id).getMetaTypeId());
|
||||
|
||||
// For all valid children, return all that have at least one
|
||||
// (unoccupied) input that is a superclass (or same class) as
|
||||
// one of the outputs
|
||||
return children
|
||||
.filter(node => this.getOperationInputs(node)
|
||||
.filter(id => this.hasValidOutputs(id, outputs)).length)
|
||||
.map(node => {
|
||||
return {
|
||||
node: this._getObjectDescriptor(node.getId())
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.removeConnection = function (id) {
|
||||
var conn = this._client.getNode(id),
|
||||
names,
|
||||
msg;
|
||||
|
||||
names = ['src', 'dst'] // srcPort, srcOp, dstPort, dstOp
|
||||
.map(type => conn.getPointer(type).to)
|
||||
.map(portId => [portId, this.getSiblingContaining(portId)])
|
||||
.reduce((l1, l2) => l1.concat(l2))
|
||||
.map(id => this._client.getNode(id));
|
||||
|
||||
msg = `Disconnecting ${names[0]} of ${names[1]} from ${names[2]} of ${names[3]}`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.getExistingPortMatches = function (portId, isOutput) {
|
||||
// Get the children nodeIds
|
||||
var srcOpId = this.getSiblingContaining(portId),
|
||||
childrenIds,
|
||||
skipIds, // Either ancestors or predecessors -> no cycles allowed!
|
||||
skipType = isOutput ? 'Predecessors' : 'Successors',
|
||||
method = 'get' + skipType,
|
||||
matches;
|
||||
|
||||
childrenIds = this._client.getNode(this._currentNodeId).getChildrenIds();
|
||||
|
||||
// Remove either ancestors or descendents
|
||||
skipIds = this[method](childrenIds.map(id => this._client.getNode(id)), srcOpId);
|
||||
childrenIds = _.difference(childrenIds, skipIds);
|
||||
|
||||
matches = this._getPortMatchFor(portId, childrenIds, isOutput);
|
||||
|
||||
// Get the port matches in the children
|
||||
return matches.map(tuple => {
|
||||
return {
|
||||
nodeId: tuple[0],
|
||||
portIds: tuple[1]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._getPortMatchFor = function (portId, opIds, isOutput) {
|
||||
//opIds = opIds || this._getAllValidChildren(node.getParentId());
|
||||
var opNodes = opIds.map(id => this._client.getNode(id)),
|
||||
portType = this._client.getNode(portId).getMetaTypeId(),
|
||||
getNodes = node => {
|
||||
var searchType = isOutput ? 'Inputs' : 'Outputs',
|
||||
searchFn = 'getOperation' + searchType,
|
||||
dstPorts = this[searchFn](node);
|
||||
|
||||
return [
|
||||
node.getId(),
|
||||
dstPorts.filter(id => {
|
||||
var typeId = this._client.getNode(id).getMetaTypeId();
|
||||
return isOutput ?
|
||||
this._client.isTypeOf(portType, typeId) :
|
||||
this._client.isTypeOf(typeId, portType);
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
return opNodes
|
||||
.map(getNodes) // Get all valid src/dst ports
|
||||
.filter(tuple => tuple[1].length);
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.createConnection = function (srcId, dstId) {
|
||||
var connId,
|
||||
names,
|
||||
msg;
|
||||
|
||||
names = [srcId, dstId] // srcPort, srcOp, dstPort, dstOp
|
||||
.map(id => [id, this.getSiblingContaining(srcId)])
|
||||
.reduce((l1, l2) => l1.concat(l2))
|
||||
.map(id => this._client.getNode(id));
|
||||
|
||||
msg = `Connecting ${names[0]} of ${names[1]} to ${names[2]} of ${names[4]}`;
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
|
||||
connId = this._client.createChild({
|
||||
parentId: this._currentNodeId,
|
||||
baseId: this.getConnectionId()
|
||||
});
|
||||
this._client.makePointer(connId, CONN.SRC, srcId);
|
||||
this._client.makePointer(connId, CONN.DST, dstId);
|
||||
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._getPortPairs = function (outputs, inputs) {
|
||||
// Given a set of outputs and (potential) inputs, return valid pairs
|
||||
// <outputId, inputId> where `outputId` is the id of an outgoing port
|
||||
// in the src operation and `inputId` is the id of an incoming port in
|
||||
// the dst operation
|
||||
var result = [],
|
||||
ipairs = inputs.map(id => [id, this._client.getNode(id).getMetaTypeId()]),
|
||||
oType;
|
||||
|
||||
// For each output, get all possible (valid) input destinations
|
||||
outputs.forEach(outputId => {
|
||||
oType = this._client.getNode(outputId).getMetaTypeId();
|
||||
result = result.concat(ipairs.filter(pair =>
|
||||
// output type should be valid input type
|
||||
this._client.isTypeOf(oType, pair[1])
|
||||
)
|
||||
.map(pair => [outputId, pair[0]]) // Get the input data id
|
||||
);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.getConnectionId = function () {
|
||||
return this._client.getAllMetaNodes()
|
||||
.find(node => node.getAttribute('name') === 'Transporter')
|
||||
.getId();
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._createConnectedNode = function (nodeId, typeId) {
|
||||
// Create a node of type "typeId" after "nodeId"
|
||||
// Figure out which ports need to be connected
|
||||
var parentId = this._currentNodeId,
|
||||
outputs = this.getOperationOutputs(this._client.getNode(nodeId)),
|
||||
inputs = this.getOperationInputs(this._client.getNode(typeId)),
|
||||
pairs = this._getPortPairs(outputs, inputs),
|
||||
srcOpName = this._client.getNode(nodeId).getAttribute('name');
|
||||
|
||||
this._logger.info(`Valid ports for ${nodeId} -> ${typeId} are ${pairs}`);
|
||||
|
||||
// If none, => error!
|
||||
// For now, I am assuming that they used '_getValidSuccessorNodes' to
|
||||
// get the pairs. ie, it is valid.
|
||||
// TODO
|
||||
|
||||
if (pairs.length === 1) { // If one, continue
|
||||
var pair = pairs[0],
|
||||
srcPortId = pair[0],
|
||||
srcPort,
|
||||
dstPortBaseId = pair[1],
|
||||
dstPortBase,
|
||||
rootGuid = this._client.getActiveRootHash(),
|
||||
branchName = this._client.getActiveBranchName(),
|
||||
startCommit = this._client.getActiveCommitHash(),
|
||||
connTypeId = this.getConnectionId(),
|
||||
project = this._client.getProjectObject(),
|
||||
conn,
|
||||
connBase,
|
||||
parentNode,
|
||||
commitMsg,
|
||||
root;
|
||||
|
||||
// This next portion uses the core bc it requires async loading and batching
|
||||
// into a single commit
|
||||
var core = new Core(project, {
|
||||
globConf: WebGMEGlobal.gmeConfig,
|
||||
logger: this._logger.fork('core')
|
||||
});
|
||||
// Load the first node/commit...
|
||||
core.loadRoot(rootGuid)
|
||||
.then(_root => {
|
||||
root = _root;
|
||||
return Q.all(
|
||||
[parentId, typeId, connTypeId, dstPortBaseId, srcPortId].map(id => core.loadByPath(root, id))
|
||||
);
|
||||
})
|
||||
.then(nodes => {
|
||||
// Create the given dst operation
|
||||
var opBase = nodes[1],
|
||||
dstOp;
|
||||
|
||||
parentNode = nodes[0];
|
||||
connBase = nodes[2];
|
||||
dstPortBase = nodes[3];
|
||||
srcPort = nodes[4];
|
||||
// Create the given dst operation
|
||||
dstOp = core.createNode({
|
||||
parent: parentNode,
|
||||
base: opBase
|
||||
});
|
||||
commitMsg = `Adding ${core.getAttribute(dstOp, 'name')} after ${srcOpName}`;
|
||||
return core.loadChildren(dstOp);
|
||||
})
|
||||
.then(containers => {
|
||||
var inputContainer;
|
||||
|
||||
// Get the operation inputs (can't use the earlier fn - different node types)
|
||||
inputContainer = containers
|
||||
.find(cntr => core.isInstanceOf(cntr, 'Inputs'));
|
||||
|
||||
return core.loadChildren(inputContainer);
|
||||
})
|
||||
.then(inputDataPorts => {
|
||||
// Get the matching input node
|
||||
var dstPort = inputDataPorts.find(port => core.isTypeOf(port, dstPortBase));
|
||||
// Create the connection
|
||||
conn = core.createNode({
|
||||
parent: parentNode,
|
||||
base: connBase
|
||||
});
|
||||
|
||||
// Connect srcPortId and the node from above
|
||||
core.setPointer(conn, 'src', srcPort);
|
||||
core.setPointer(conn, 'dst', dstPort);
|
||||
var persisted = core.persist(root);
|
||||
return project.makeCommit(
|
||||
branchName,
|
||||
[ startCommit ],
|
||||
persisted.rootHash,
|
||||
persisted.objects,
|
||||
commitMsg
|
||||
);
|
||||
})
|
||||
.then(result => {
|
||||
if (result.status === STORAGE_CONSTANTS.SYNCED) {
|
||||
// Throw out the changes... warn the user?
|
||||
this._logger.info('SYNCED!');
|
||||
} else {
|
||||
// Throw out the changes... warn the user?
|
||||
this._logger.warn(`Could not create operation after ${srcOpName}`);
|
||||
}
|
||||
})
|
||||
.fail(err => this._logger.error(`Could not create operation after ${srcOpName}: ${err}`));
|
||||
|
||||
} else if (pairs.length > 1) {
|
||||
// Else, prompt!
|
||||
// TODO
|
||||
this._logger.error('multiple port combinations... This is currently unsupported');
|
||||
}
|
||||
};
|
||||
|
||||
return PipelineEditorControl;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Thu May 19 2016 14:04:47 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/PipelineEditor/PipelineEditorWidget',
|
||||
'./PipelineEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
PipelineEditorWidget,
|
||||
PipelineEditorControl) {
|
||||
'use strict';
|
||||
|
||||
var PipelineEditorPanel;
|
||||
|
||||
PipelineEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'PipelineEditorPanel';
|
||||
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(PipelineEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(PipelineEditorPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
PipelineEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new PipelineEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new PipelineEditorControl({
|
||||
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 */
|
||||
PipelineEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
PipelineEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
PipelineEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
PipelineEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
PipelineEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return PipelineEditorPanel;
|
||||
});
|
||||
@@ -0,0 +1,242 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 0.1.0 from webgme on Wed Dec 23 2015 11:31:06 GMT-0600 (CST).
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'js/Utils/GMEConcepts',
|
||||
'js/NodePropertyNames'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
GMEConcepts,
|
||||
nodePropertyNames
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var RootVizControl;
|
||||
|
||||
RootVizControl = function (options) {
|
||||
|
||||
this._logger = options.logger.fork('Control');
|
||||
|
||||
this._client = options.client;
|
||||
this._embedded = options.embedded;
|
||||
|
||||
// Initialize core collections and variables
|
||||
this._widget = options.widget;
|
||||
|
||||
this._currentNodeId = null;
|
||||
this._currentNodeParentId = undefined;
|
||||
|
||||
this._initWidgetEventHandlers();
|
||||
|
||||
this._logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
RootVizControl.prototype._initWidgetEventHandlers = function () {
|
||||
this._widget.onNodeClick = function (id) {
|
||||
// Change the current active object
|
||||
WebGMEGlobal.State.registerActiveObject(id);
|
||||
};
|
||||
};
|
||||
|
||||
/* * * * * * * * 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).
|
||||
RootVizControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
var desc = this._getObjectDescriptor(nodeId),
|
||||
self = this;
|
||||
|
||||
self._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
// Remove current territory patterns
|
||||
if (self._currentNodeId) {
|
||||
self._client.removeUI(self._territoryId);
|
||||
}
|
||||
|
||||
self._currentNodeId = nodeId;
|
||||
self._currentNodeParentId = undefined;
|
||||
|
||||
if (self._currentNodeId || self._currentNodeId === CONSTANTS.PROJECT_ROOT_ID) {
|
||||
// Put new node's info into territory rules
|
||||
self._selfPatterns = {};
|
||||
self._selfPatterns[nodeId] = {children: 0}; // Territory "rule"
|
||||
|
||||
if (desc.parentId || desc.parentId === CONSTANTS.PROJECT_ROOT_ID) {
|
||||
self.$btnModelHierarchyUp.show();
|
||||
} else {
|
||||
self.$btnModelHierarchyUp.hide();
|
||||
}
|
||||
|
||||
self._currentNodeParentId = desc.parentId;
|
||||
|
||||
self._territoryId = self._client.addUI(self, function (events) {
|
||||
self._eventCallback(events);
|
||||
});
|
||||
self._logger.debug(`RootViz territory id is ${this._territoryId}`);
|
||||
|
||||
// Update the territory
|
||||
self._client.updateTerritory(self._territoryId, self._selfPatterns);
|
||||
|
||||
self._selfPatterns[nodeId] = {children: 1};
|
||||
self._client.updateTerritory(self._territoryId, self._selfPatterns);
|
||||
}
|
||||
};
|
||||
|
||||
// This next function retrieves the relevant node information for the widget
|
||||
RootVizControl.prototype._getObjectDescriptor = function (nodeId) {
|
||||
var nodeObj = this._client.getNode(nodeId),
|
||||
objDescriptor;
|
||||
|
||||
if (nodeObj) {
|
||||
objDescriptor = {
|
||||
'id': undefined,
|
||||
'name': undefined,
|
||||
'childrenIds': undefined,
|
||||
'parentId': undefined,
|
||||
'isConnection': false
|
||||
};
|
||||
|
||||
objDescriptor.id = nodeObj.getId();
|
||||
objDescriptor.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
|
||||
objDescriptor.childrenIds = nodeObj.getChildrenIds();
|
||||
objDescriptor.childrenNum = objDescriptor.childrenIds.length;
|
||||
objDescriptor.parentId = nodeObj.getParentId();
|
||||
objDescriptor.isConnection = GMEConcepts.isConnection(nodeId); // GMEConcepts can be helpful
|
||||
}
|
||||
|
||||
return objDescriptor;
|
||||
};
|
||||
|
||||
/* * * * * * * * Node Event Handling * * * * * * * */
|
||||
RootVizControl.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');
|
||||
};
|
||||
|
||||
RootVizControl.prototype._onLoad = function (gmeId) {
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(description);
|
||||
};
|
||||
|
||||
RootVizControl.prototype._onUpdate = function (gmeId) {
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.updateNode(description);
|
||||
};
|
||||
|
||||
RootVizControl.prototype._onUnload = function (gmeId) {
|
||||
this._widget.removeNode(gmeId);
|
||||
};
|
||||
|
||||
RootVizControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
|
||||
this.selectedObjectChanged(activeObjectId);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
RootVizControl.prototype.destroy = function () {
|
||||
this._detachClientEventListeners();
|
||||
this._removeToolbarItems();
|
||||
};
|
||||
|
||||
RootVizControl.prototype._attachClientEventListeners = function () {
|
||||
if (!this._embedded) {
|
||||
this._detachClientEventListeners();
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this);
|
||||
}
|
||||
};
|
||||
|
||||
RootVizControl.prototype._detachClientEventListeners = function () {
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged);
|
||||
}
|
||||
};
|
||||
|
||||
RootVizControl.prototype.onActivate = function () {
|
||||
this._attachClientEventListeners();
|
||||
this._displayToolbarItems();
|
||||
};
|
||||
|
||||
RootVizControl.prototype.onDeactivate = function () {
|
||||
this._detachClientEventListeners();
|
||||
this._hideToolbarItems();
|
||||
};
|
||||
|
||||
/* * * * * * * * * * Updating the toolbar * * * * * * * * * */
|
||||
RootVizControl.prototype._displayToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].show();
|
||||
}
|
||||
} else {
|
||||
this._initializeToolbar();
|
||||
}
|
||||
};
|
||||
|
||||
RootVizControl.prototype._hideToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RootVizControl.prototype._removeToolbarItems = function () {
|
||||
|
||||
if (this._toolbarInitialized === true) {
|
||||
for (var i = this._toolbarItems.length; i--;) {
|
||||
this._toolbarItems[i].destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RootVizControl.prototype._initializeToolbar = function () {
|
||||
var self = this,
|
||||
toolBar = WebGMEGlobal.Toolbar;
|
||||
|
||||
this._toolbarItems = [];
|
||||
|
||||
this._toolbarItems.push(toolBar.addSeparator());
|
||||
|
||||
/************** Go to hierarchical parent button ****************/
|
||||
this.$btnModelHierarchyUp = toolBar.addButton({
|
||||
title: 'Go to parent',
|
||||
icon: 'glyphicon glyphicon-circle-arrow-up',
|
||||
clickFn: function (/*data*/) {
|
||||
WebGMEGlobal.State.registerActiveObject(self._currentNodeParentId);
|
||||
}
|
||||
});
|
||||
this._toolbarItems.push(this.$btnModelHierarchyUp);
|
||||
this.$btnModelHierarchyUp.hide();
|
||||
|
||||
this._toolbarInitialized = true;
|
||||
};
|
||||
|
||||
return RootVizControl;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 0.1.0 from webgme on Wed Dec 23 2015 11:31:06 GMT-0600 (CST).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/RootViz/RootVizWidget',
|
||||
'./RootVizControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
RootVizWidget,
|
||||
RootVizControl) {
|
||||
'use strict';
|
||||
|
||||
var RootVizPanel;
|
||||
|
||||
RootVizPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'RootVizPanel';
|
||||
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(RootVizPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(RootVizPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
RootVizPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new RootVizWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new RootVizControl({
|
||||
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 */
|
||||
RootVizPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
RootVizPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
RootVizPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
RootVizPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
RootVizPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return RootVizPanel;
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'underscore'
|
||||
], function (
|
||||
TextEditorControl,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var SerializeEditorControl;
|
||||
|
||||
SerializeEditorControl = function (options) {
|
||||
options.attributeName = 'serialize';
|
||||
TextEditorControl.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
SerializeEditorControl.prototype,
|
||||
TextEditorControl.prototype
|
||||
);
|
||||
|
||||
// input/output updates are actually activeNode updates
|
||||
SerializeEditorControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, this._currentNodeId);
|
||||
}
|
||||
};
|
||||
|
||||
return SerializeEditorControl;
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/*globals define, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed Jun 01 2016 14:44:21 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/SerializeEditor/SerializeEditorWidget',
|
||||
'./SerializeEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
SerializeEditorWidget,
|
||||
SerializeEditorControl) {
|
||||
'use strict';
|
||||
|
||||
var SerializeEditorPanel;
|
||||
|
||||
SerializeEditorPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'SerializeEditorPanel';
|
||||
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(SerializeEditorPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(SerializeEditorPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
SerializeEditorPanel.prototype._initialize = function () {
|
||||
var self = this;
|
||||
|
||||
//set Widget title
|
||||
this.setTitle('');
|
||||
|
||||
this.widget = new SerializeEditorWidget(this.logger, this.$el);
|
||||
|
||||
this.widget.setTitle = function (title) {
|
||||
self.setTitle(title);
|
||||
};
|
||||
|
||||
this.control = new SerializeEditorControl({
|
||||
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 */
|
||||
SerializeEditorPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
|
||||
};
|
||||
|
||||
SerializeEditorPanel.prototype.onResize = function (width, height) {
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this.widget.onWidgetContainerResize(width, height);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
SerializeEditorPanel.prototype.destroy = function () {
|
||||
this.control.destroy();
|
||||
this.widget.destroy();
|
||||
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
SerializeEditorPanel.prototype.onActivate = function () {
|
||||
this.widget.onActivate();
|
||||
this.control.onActivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(this.widget);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
SerializeEditorPanel.prototype.onDeactivate = function () {
|
||||
this.widget.onDeactivate();
|
||||
this.control.onDeactivate();
|
||||
WebGMEGlobal.KeyboardManager.setListener(undefined);
|
||||
WebGMEGlobal.Toolbar.refresh();
|
||||
};
|
||||
|
||||
return SerializeEditorPanel;
|
||||
});
|
||||
@@ -27,8 +27,11 @@ define([
|
||||
// Initialize core collections and variables
|
||||
this._widget = options.widget;
|
||||
this.ATTRIBUTE_NAME = options.attributeName || 'code'; // TODO: load from config
|
||||
|
||||
this._currentNodeId = null;
|
||||
this._currentNodeParentId = undefined;
|
||||
this._currentNodeHasAttr = false;
|
||||
this._embedded = options.embedded;
|
||||
|
||||
this._initWidgetEventHandlers();
|
||||
|
||||
@@ -38,7 +41,12 @@ define([
|
||||
TextEditorControl.prototype._initWidgetEventHandlers = function () {
|
||||
// TODO: Add a way to navigate out of the current widget...
|
||||
this._widget.saveTextFor = (id, text) => {
|
||||
this._client.setAttributes(id, this.ATTRIBUTE_NAME, text);
|
||||
if (this._currentNodeHasAttr) {
|
||||
this._client.setAttributes(id, this.ATTRIBUTE_NAME, text);
|
||||
} else {
|
||||
this._logger.warn(`Cannot save attribute ${this.ATTRIBUTE_NAME} ` +
|
||||
`for ${id} - node doesn't have the given attribute!`);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -46,9 +54,9 @@ define([
|
||||
// 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).
|
||||
TextEditorControl.prototype.TERRITORY_RULE = {children: 0};
|
||||
TextEditorControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
var desc = this._getObjectDescriptor(nodeId),
|
||||
self = this;
|
||||
var self = this;
|
||||
|
||||
self._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
@@ -59,34 +67,39 @@ define([
|
||||
|
||||
self._currentNodeId = nodeId;
|
||||
self._currentNodeParentId = undefined;
|
||||
self._currentNodeHasAttr = (typeof self._client.getNode(self._currentNodeId)
|
||||
.getAttribute(self.ATTRIBUTE_NAME)) === 'string';
|
||||
|
||||
if (typeof self._currentNodeId === 'string') {
|
||||
var parentId = this._getParentId(nodeId);
|
||||
// Put new node's info into territory rules
|
||||
self._selfPatterns = {};
|
||||
self._selfPatterns[nodeId] = {children: 0}; // Territory "rule"
|
||||
|
||||
//self._widget.setTitle(desc.name.toUpperCase());
|
||||
|
||||
if (typeof desc.parentId === 'string') {
|
||||
if (typeof parentId === 'string') {
|
||||
self.$btnModelHierarchyUp.show();
|
||||
} else {
|
||||
self.$btnModelHierarchyUp.hide();
|
||||
}
|
||||
|
||||
self._currentNodeParentId = desc.parentId;
|
||||
self._currentNodeParentId = parentId;
|
||||
|
||||
self._territoryId = self._client.addUI(self, function (events) {
|
||||
self._eventCallback(events);
|
||||
});
|
||||
self._logger.debug(`TextEditor territory id is ${this._territoryId}`);
|
||||
|
||||
// Update the territory
|
||||
self._client.updateTerritory(self._territoryId, self._selfPatterns);
|
||||
|
||||
self._selfPatterns[nodeId] = {children: 1};
|
||||
self._selfPatterns[nodeId] = this.TERRITORY_RULE;
|
||||
self._client.updateTerritory(self._territoryId, self._selfPatterns);
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._getParentId = function (nodeId) {
|
||||
var node = this._client.getNode(nodeId);
|
||||
return node ? node.getParentId() : null;
|
||||
};
|
||||
|
||||
// This next function retrieves the relevant node information for the widget
|
||||
TextEditorControl.prototype._getObjectDescriptor = function (nodeId) {
|
||||
var nodeObj = this._client.getNode(nodeId),
|
||||
@@ -96,8 +109,8 @@ define([
|
||||
desc = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
parentId: undefined,
|
||||
text: ''
|
||||
parentId: undefined,
|
||||
text: ''
|
||||
};
|
||||
|
||||
desc.id = nodeObj.getId();
|
||||
@@ -119,17 +132,18 @@ define([
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +151,10 @@ define([
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._onLoad = function (gmeId) {
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(description);
|
||||
if (this._currentNodeId === gmeId) { // Only load the text for the current node
|
||||
var description = this._getObjectDescriptor(gmeId);
|
||||
this._widget.addNode(description);
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._onUpdate = function (gmeId) {
|
||||
@@ -165,12 +181,16 @@ define([
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._attachClientEventListeners = function () {
|
||||
this._detachClientEventListeners();
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this);
|
||||
if (!this._embedded) {
|
||||
this._detachClientEventListeners();
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this);
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype._detachClientEventListeners = function () {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged);
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged);
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.onActivate = function () {
|
||||
@@ -186,6 +206,7 @@ define([
|
||||
|
||||
TextEditorControl.prototype.onDeactivate = function () {
|
||||
this._detachClientEventListeners();
|
||||
// TODO: Destroy the ace instance!
|
||||
this._hideToolbarItems();
|
||||
};
|
||||
|
||||
@@ -240,15 +261,6 @@ define([
|
||||
|
||||
/************** Checkbox example *******************/
|
||||
|
||||
this.$cbShowConnection = toolBar.addCheckBox({
|
||||
title: 'toggle checkbox',
|
||||
icon: 'gme icon-gme_diagonal-arrow',
|
||||
checkChangedFn: function (data, checked) {
|
||||
self._logger.debug('Checkbox has been clicked!');
|
||||
}
|
||||
});
|
||||
this._toolbarItems.push(this.$cbShowConnection);
|
||||
|
||||
this._toolbarInitialized = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ define(['js/PanelBase/PanelBaseWithHeader',
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
@@ -52,6 +53,7 @@ define(['js/PanelBase/PanelBaseWithHeader',
|
||||
this.control = new TextEditorControl({
|
||||
logger: this.logger,
|
||||
client: this._client,
|
||||
embedded: this._embedded,
|
||||
widget: this.widget
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*globals define, _, $, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
// This panel is essentially it's own layout manager. It is
|
||||
// given a static list of visualizers and tiles them allowing
|
||||
// the user to view the current node in a number of different
|
||||
// ways at once (w/o toggling between visualizers)
|
||||
//
|
||||
// For now, it is just split screen
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/Constants',
|
||||
'js/PanelManager/IActivePanel'
|
||||
], function (
|
||||
PanelBaseWithHeader,
|
||||
CONSTANTS,
|
||||
IActivePanel
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var TilingVizPanel;
|
||||
|
||||
TilingVizPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = 'TilingVizPanel';
|
||||
options[PanelBaseWithHeader.OPTIONS.FLOATING_TITLE] = true;
|
||||
|
||||
//call parent's constructor
|
||||
PanelBaseWithHeader.apply(this, [options, layoutManager]);
|
||||
|
||||
this._layoutManager = layoutManager;
|
||||
this._params = params;
|
||||
this._client = params.client;
|
||||
this._embedded = params.embedded;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(TilingVizPanel.prototype, PanelBaseWithHeader.prototype);
|
||||
_.extend(TilingVizPanel.prototype, IActivePanel.prototype);
|
||||
|
||||
TilingVizPanel.prototype.getPanels = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
TilingVizPanel.prototype._initialize = function () {
|
||||
var panels = this.getPanels();
|
||||
|
||||
// Trigger active object
|
||||
if (!this._embedded) {
|
||||
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
|
||||
(model, nodeId) => this.selectedObjectChanged(nodeId)
|
||||
);
|
||||
}
|
||||
|
||||
if (panels.length !== 2) {
|
||||
this.logger.error(`Unsupported number of panels (${panels.length})`);
|
||||
}
|
||||
|
||||
// Create the panels and containers
|
||||
this._panels = panels.map(Panel => new Panel(this._layoutManager, this._params));
|
||||
this._containers = this._panels.map((p, i) => $('<div>', {id: `panel ${i}`}));
|
||||
this._containers.forEach(c => this.$el.append(c));
|
||||
this._activePanel = this._panels[0];
|
||||
|
||||
// Add each panel to the respective container and deactivate
|
||||
this._panels.forEach((panel, i) =>
|
||||
this._containers[i].append(panel.$el) && panel.onDeactivate()
|
||||
);
|
||||
|
||||
this.control = { // For use in dev mode
|
||||
selectedObjectChanged: this.selectedObjectChanged.bind(this)
|
||||
};
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
TilingVizPanel.prototype.selectedObjectChanged = function (nodeId) {
|
||||
this._currentNodeId = nodeId;
|
||||
this._panels.forEach(p => p.control.selectedObjectChanged(this._currentNodeId));
|
||||
};
|
||||
|
||||
/* OVERRIDE FROM WIDGET-WITH-HEADER */
|
||||
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
|
||||
TilingVizPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
|
||||
//apply parent's onReadOnlyChanged
|
||||
PanelBaseWithHeader.prototype.onReadOnlyChanged.call(this, isReadOnly);
|
||||
};
|
||||
|
||||
TilingVizPanel.prototype.onResize = function (width, height) {
|
||||
var pwidth = width/2;
|
||||
|
||||
this._containers.forEach((c, i) => c.css({
|
||||
width: pwidth,
|
||||
height: height,
|
||||
left: pwidth*i,
|
||||
position: 'absolute'
|
||||
}));
|
||||
// Call onResize for each of the tiles
|
||||
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
|
||||
this._panels.forEach(p => p.onResize(pwidth, height));
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
TilingVizPanel.prototype.destroy = function () {
|
||||
this._panels.forEach(p => p.destroy());
|
||||
PanelBaseWithHeader.prototype.destroy.call(this);
|
||||
};
|
||||
|
||||
TilingVizPanel.prototype.onActivate = function () {
|
||||
// Activate the first panel by default
|
||||
this._activePanel = this._panels[0];
|
||||
//WebGMEGlobal.PanelManager.setActivePanel(this._activePanel);
|
||||
this._activePanel.onActivate();
|
||||
};
|
||||
|
||||
TilingVizPanel.prototype.onDeactivate = function () {
|
||||
this._activePanel.onDeactivate();
|
||||
};
|
||||
|
||||
return TilingVizPanel;
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*globals define*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
@@ -17,47 +17,16 @@ define([
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var ArchEditorWidget,
|
||||
WIDGET_CLASS = 'arch-editor',
|
||||
DEFAULT_COLOR = '#ffb74d',
|
||||
LAYER_COLORS = {
|
||||
Containers: '#ffb74d',
|
||||
Module: '#ba68c8',
|
||||
ConvLayer: '#2196f3',
|
||||
SimpleLayer: '#ff9100',
|
||||
TransferLayer: '#80deea',
|
||||
MiscLayers: '#ce93d8',
|
||||
Criterion: '#7e57c2'
|
||||
};
|
||||
var ArchEditorWidget;
|
||||
// WIDGET_CLASS = 'arch-editor',
|
||||
|
||||
ArchEditorWidget = function (logger, container) {
|
||||
EasyDAGWidget.call(this, logger, container);
|
||||
this.LAYER_COLORS = _.extend(LAYER_COLORS, this._config.LayerColors);
|
||||
this.DEFAULT_COLOR = this._config.DefaultColor || DEFAULT_COLOR;
|
||||
};
|
||||
|
||||
_.extend(ArchEditorWidget.prototype, EasyDAGWidget.prototype);
|
||||
|
||||
ArchEditorWidget.prototype.ItemClass = Layer;
|
||||
ArchEditorWidget.prototype.getComponentId = function() {
|
||||
return 'ArchEditor';
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype.addNode = function(desc) {
|
||||
// Assign a color!
|
||||
desc.color = this.getColor(desc) || null;
|
||||
return EasyDAGWidget.prototype.addNode.call(this, desc);
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype.getColor = function(desc) {
|
||||
// Assign by the layerType
|
||||
var color = this.LAYER_COLORS[desc.layerType];
|
||||
if (!color) {
|
||||
this._logger.warn(`No color found for ${desc.layerType}`);
|
||||
color = this.DEFAULT_COLOR;
|
||||
}
|
||||
return color;
|
||||
};
|
||||
|
||||
return ArchEditorWidget;
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'widgets/EasyDAG/DAGItem'
|
||||
'widgets/EasyDAG/DAGItem',
|
||||
'underscore'
|
||||
], function(
|
||||
DAGItem
|
||||
DAGItem,
|
||||
_
|
||||
) {
|
||||
var Layer = function(parentEl, desc) {
|
||||
this.id = desc.id;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed Jun 01 2016 14:45:18 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/TextEditor/TextEditorWidget',
|
||||
'underscore',
|
||||
'css!./styles/DeserializeEditorWidget.css'
|
||||
], function (
|
||||
TextEditorWidget,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var DeserializeEditorWidget;
|
||||
//WIDGET_CLASS = 'deserialize-editor';
|
||||
|
||||
DeserializeEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(DeserializeEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
|
||||
DeserializeEditorWidget.prototype.getHeader = function(desc) {
|
||||
return [
|
||||
`-- The deserialization function for ${desc.name}`,
|
||||
'-- Globals:',
|
||||
'-- `path` - target filename to load',
|
||||
'--',
|
||||
`-- return the loaded ${desc.name}`
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
DeserializeEditorWidget.prototype.updateNode = function() {
|
||||
// nop
|
||||
};
|
||||
|
||||
return DeserializeEditorWidget;
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* This file is for any css that you may want for this visualizer.
|
||||
*
|
||||
* Ideally, you would use the scss file also provided in this directory
|
||||
* and then generate this file automatically from that. However, you can
|
||||
* simply write css if you prefer
|
||||
*/
|
||||
|
||||
.deserialize-editor {
|
||||
outline: none; }
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file is for any scss that you may want for this visualizer.
|
||||
*/
|
||||
|
||||
.deserialize-editor {
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*globals define*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 24 2016 10:15:19 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'./SelectionManager',
|
||||
'underscore',
|
||||
'css!./styles/ExecutionViewWidget.css'
|
||||
], function (
|
||||
EasyDAGWidget,
|
||||
SelectionManager,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var ExecutionViewWidget;
|
||||
|
||||
ExecutionViewWidget = function (logger, container) {
|
||||
EasyDAGWidget.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(ExecutionViewWidget.prototype, EasyDAGWidget.prototype);
|
||||
|
||||
ExecutionViewWidget.prototype.SelectionManager = SelectionManager;
|
||||
|
||||
return ExecutionViewWidget;
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/*globals define*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var SelectionManager = function(widget) {
|
||||
EasyDAGSelectionManager.call(this, widget);
|
||||
};
|
||||
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(/*width, height*/) {
|
||||
// Add restart btn, etc
|
||||
// TODO
|
||||
};
|
||||
|
||||
return SelectionManager;
|
||||
});
|
||||
+1
-1
@@ -6,5 +6,5 @@
|
||||
* simply write css if you prefer
|
||||
*/
|
||||
|
||||
.operation-editor {
|
||||
.execution-view {
|
||||
outline: none; }
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
* This file is for any scss that you may want for this visualizer.
|
||||
*/
|
||||
|
||||
.operation-editor {
|
||||
.execution-view {
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*globals define */
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/TextEditor/TextEditorWidget',
|
||||
'underscore',
|
||||
'css!./styles/OperationCodeEditorWidget.css'
|
||||
], function (
|
||||
TextEditorWidget,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var OperationCodeEditorWidget;
|
||||
//WIDGET_CLASS = 'operation-editor';
|
||||
|
||||
OperationCodeEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(OperationCodeEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
|
||||
OperationCodeEditorWidget.prototype.getHeader = function (desc) {
|
||||
// Add comment about the inputs, attributes and references
|
||||
var inputs = desc.inputs.map(pair => `-- ${pair[0]} (${pair[1]})`).join('\n'),
|
||||
refs = desc.references.map(name => `-- ${name}`).join('\n'),
|
||||
outputs,
|
||||
header = [
|
||||
`-- Editing "${desc.name}"`,
|
||||
'-- '
|
||||
];
|
||||
|
||||
if (inputs.length) {
|
||||
header.push('-- Defined variables:');
|
||||
header.push(inputs);
|
||||
}
|
||||
if (refs) {
|
||||
header.push(refs);
|
||||
}
|
||||
header.push('--');
|
||||
|
||||
// Add info about outputs
|
||||
outputs = desc.outputs.map(pair => `-- ${pair[0]} = <some ${pair[1]}>`)
|
||||
.join('\n');
|
||||
|
||||
if (outputs.length) {
|
||||
header.push('-- Returning something like:');
|
||||
header.push('-- {');
|
||||
header.push(outputs);
|
||||
header.push('-- }');
|
||||
}
|
||||
|
||||
return header.join('\n');
|
||||
};
|
||||
|
||||
return OperationCodeEditorWidget;
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* This file is for any css that you may want for this visualizer.
|
||||
*
|
||||
* Ideally, you would use the scss file also provided in this directory
|
||||
* and then generate this file automatically from that. However, you can
|
||||
* simply write css if you prefer
|
||||
*/
|
||||
|
||||
.operation-code-editor {
|
||||
outline: none; }
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file is for any scss that you may want for this visualizer.
|
||||
*/
|
||||
|
||||
.operation-code-editor {
|
||||
outline: none;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Wed May 18 2016 12:00:46 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/TextEditor/TextEditorWidget',
|
||||
'underscore',
|
||||
'css!./styles/OperationEditorWidget.css'
|
||||
], function (
|
||||
TextEditorWidget,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var OperationEditorWidget,
|
||||
WIDGET_CLASS = 'operation-editor';
|
||||
|
||||
OperationEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(OperationEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
|
||||
OperationEditorWidget.prototype.getHeader = function (desc) {
|
||||
// Add comment about the inputs, attributes and references
|
||||
var inputs = desc.inputs.map(pair => `-- ${pair[0]} (${pair[1]})`).join('\n'),
|
||||
refs = desc.references.map(name => `-- ${name}`).join('\n'),
|
||||
header = [
|
||||
`-- Editing "${desc.name}"`,
|
||||
`-- `,
|
||||
`-- Defined variables:`
|
||||
];
|
||||
|
||||
if (inputs) {
|
||||
header.push(inputs);
|
||||
}
|
||||
if (refs) {
|
||||
header.push(refs);
|
||||
}
|
||||
header.push(`--`);
|
||||
return header.join('\n');
|
||||
};
|
||||
|
||||
return OperationEditorWidget;
|
||||
});
|
||||
@@ -0,0 +1,122 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGButtons,
|
||||
_
|
||||
) {
|
||||
|
||||
var AddOutput = function(params) {
|
||||
EasyDAGButtons.Add.call(this, params);
|
||||
};
|
||||
|
||||
_.extend(AddOutput.prototype, EasyDAGButtons.Add.prototype);
|
||||
|
||||
AddOutput.prototype._render = function() {
|
||||
var lineRadius = EasyDAGButtons.Add.SIZE - EasyDAGButtons.Add.BORDER,
|
||||
btnColor = '#90caf9',
|
||||
lineColor = '#7986cb';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
.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);
|
||||
|
||||
};
|
||||
|
||||
var AddInput = function(params) {
|
||||
EasyDAGButtons.Add.call(this, params);
|
||||
};
|
||||
_.extend(AddInput.prototype, AddOutput.prototype);
|
||||
|
||||
AddInput.prototype._onClick = function(item) {
|
||||
this.onAddButtonClicked(item, true);
|
||||
};
|
||||
|
||||
// References
|
||||
var AddRef = function(params) {
|
||||
EasyDAGButtons.Add.call(this, params);
|
||||
};
|
||||
|
||||
_.extend(AddRef.prototype, EasyDAGButtons.Add.prototype);
|
||||
|
||||
AddRef.prototype._onClick = function() {
|
||||
this.onAddRefClicked();
|
||||
};
|
||||
|
||||
AddRef.prototype._render = function() {
|
||||
var lineRadius = EasyDAGButtons.Add.SIZE - EasyDAGButtons.Add.BORDER,
|
||||
btnColor = '#81c784',
|
||||
lineColor = '#7986cb';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
.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);
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
AddOutput: AddOutput,
|
||||
AddInput: AddInput,
|
||||
AddRef: AddRef,
|
||||
Delete: EasyDAGButtons.Delete
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'widgets/EasyDAG/DAGItem',
|
||||
'underscore'
|
||||
], function(
|
||||
DAGItem,
|
||||
_
|
||||
) {
|
||||
|
||||
var Item = function(parentEl, desc) {
|
||||
DAGItem.call(this, parentEl, desc);
|
||||
};
|
||||
|
||||
_.extend(Item.prototype, DAGItem.prototype);
|
||||
|
||||
Item.prototype.setupDecoratorCallbacks = function() {
|
||||
DAGItem.prototype.setupDecoratorCallbacks.call(this);
|
||||
// Add ptr name change
|
||||
this.decorator.changePtrName = this.changePtrName.bind(this);
|
||||
};
|
||||
|
||||
return Item;
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
/*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([
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'./SelectionManager',
|
||||
'./Item',
|
||||
'underscore',
|
||||
'css!./styles/OperationInterfaceEditorWidget.css'
|
||||
], function (
|
||||
EasyDAG,
|
||||
AddNodeDialog,
|
||||
SelectionManager,
|
||||
Item,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var OperationInterfaceEditorWidget,
|
||||
WIDGET_CLASS = 'operation-interface-editor';
|
||||
|
||||
OperationInterfaceEditorWidget = function (logger, container) {
|
||||
EasyDAG.call(this, logger, container);
|
||||
};
|
||||
|
||||
_.extend(OperationInterfaceEditorWidget.prototype, EasyDAG.prototype);
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.SelectionManager = SelectionManager;
|
||||
OperationInterfaceEditorWidget.prototype.ItemClass = Item;
|
||||
OperationInterfaceEditorWidget.prototype.setupItemCallbacks = function() {
|
||||
EasyDAG.prototype.setupItemCallbacks.call(this);
|
||||
// Add ptr rename callback
|
||||
this.ItemClass.prototype.changePtrName = (from, to) => this.changePtrName(from, to);
|
||||
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddItemSelected = function(selected, isInput) {
|
||||
this.createConnectedNode(selected.node.id, isInput);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddButtonClicked = function(item, isInput) {
|
||||
var successorPairs = this.getValidSuccessorNodes(item.id),
|
||||
successor = successorPairs[0];
|
||||
|
||||
if (successorPairs.length > 1) {
|
||||
// Create the modal view with all possible subsequent nodes
|
||||
var dialog = new AddNodeDialog(),
|
||||
title = this._getAddSuccessorTitle(item);
|
||||
|
||||
dialog.show(title, successorPairs);
|
||||
dialog.onSelect = pair => {
|
||||
if (pair) {
|
||||
this.onAddItemSelected(pair, isInput);
|
||||
}
|
||||
};
|
||||
} else if (successor) {
|
||||
this.onAddItemSelected(successor, isInput);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onDeactivate = function() {
|
||||
EasyDAG.prototype.onDeactivate.call(this);
|
||||
this.active = true; // keep refreshing the screen -> it is always visible
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddRefClicked = function() {
|
||||
var refs = this.allValidReferences();
|
||||
|
||||
// Get all valid references
|
||||
if (refs.length > 1) {
|
||||
// Create the modal view with all possible subsequent nodes
|
||||
var dialog = new AddNodeDialog();
|
||||
|
||||
dialog.show(null, refs);
|
||||
dialog.onSelect = selected => {
|
||||
if (selected) {
|
||||
this.onAddRefSelected(selected);
|
||||
}
|
||||
};
|
||||
} else if (refs[0]) {
|
||||
this.onAddRefSelected(refs[0]);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddRefSelected = function(target) {
|
||||
this.addRefTo(target.node.id);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.removeItem = function(item) {
|
||||
if (item.desc.isPointer) {
|
||||
this.removePtr(item.name);
|
||||
} else {
|
||||
this.removeSubtreeAt(item.id);
|
||||
}
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorWidget;
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
/*globals define*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'./Buttons',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
Buttons,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var SelectionManager = function(widget) {
|
||||
EasyDAGSelectionManager.call(this, widget);
|
||||
};
|
||||
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(width, height) {
|
||||
var selectedType = this.selectedItem.desc.baseName,
|
||||
dataNodes,
|
||||
refNodes,
|
||||
cx = width/2;
|
||||
|
||||
if (selectedType === 'Operation') {
|
||||
dataNodes = this._widget.allDataTypeIds();
|
||||
refNodes = this._widget.allValidReferences();
|
||||
|
||||
new Buttons.AddOutput({ // Add output data
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: cx,
|
||||
y: height,
|
||||
disabled: dataNodes.length === 0
|
||||
});
|
||||
|
||||
new Buttons.AddInput({ // Add input data
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
disabled: dataNodes.length === 0,
|
||||
x: width/3,
|
||||
y: 0
|
||||
});
|
||||
|
||||
new Buttons.AddRef({ // Add reference
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
disabled: refNodes.length === 0,
|
||||
x: 2*width/3,
|
||||
y: 0
|
||||
});
|
||||
} else { // Data...
|
||||
new Buttons.Delete({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: cx,
|
||||
y: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return SelectionManager;
|
||||
});
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* This file is for any css that you may want for this visualizer.
|
||||
*
|
||||
* Ideally, you would use the scss file also provided in this directory
|
||||
* and then generate this file automatically from that. However, you can
|
||||
* simply write css if you prefer
|
||||
*/
|
||||
|
||||
.operation-interface-editor {
|
||||
outline: none; }
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file is for any scss that you may want for this visualizer.
|
||||
*/
|
||||
|
||||
.operation-interface-editor {
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* globals define */
|
||||
// Connection with port support
|
||||
define([
|
||||
'widgets/EasyDAG/Connection',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGConn,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var Connection = function() {
|
||||
EasyDAGConn.apply(this, arguments);
|
||||
this.srcPort = this.desc.srcPort;
|
||||
this.dstPort = this.desc.dstPort;
|
||||
};
|
||||
|
||||
_.extend(Connection.prototype, EasyDAGConn.prototype);
|
||||
|
||||
Connection.prototype.setStartPoint = function(point) {
|
||||
// Update 'this.points' to start at the given point
|
||||
this.points[0] = point;
|
||||
};
|
||||
|
||||
Connection.prototype.setEndPoint = function(point) {
|
||||
// Update 'this.points' to end at the given point
|
||||
var last = this.points.length-1;
|
||||
this.points[last] = point;
|
||||
};
|
||||
|
||||
return Connection;
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
/*globals define */
|
||||
define([
|
||||
'widgets/EasyDAG/DAGItem',
|
||||
'underscore'
|
||||
], function(
|
||||
DAGItem,
|
||||
_
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
var OperationNode = function(parentEl, desc) {
|
||||
DAGItem.call(this, parentEl, desc);
|
||||
this.inputs = desc.inputs;
|
||||
this.outputs = desc.outputs;
|
||||
this._visiblePorts = null;
|
||||
};
|
||||
|
||||
_.extend(OperationNode.prototype, DAGItem.prototype);
|
||||
|
||||
OperationNode.prototype.setupDecoratorCallbacks = function() {
|
||||
DAGItem.prototype.setupDecoratorCallbacks.call(this);
|
||||
this.decorator.onPortClick = (id, portId, isSrc) => {
|
||||
var srcPort = this.inputs.find(port => port.id === portId);
|
||||
if (srcPort && srcPort.connection) {
|
||||
this.disconnectPort(portId, srcPort.connection);
|
||||
} else {
|
||||
this.connectPort(id, portId, isSrc);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// TODO: Change showPorts to just toggle the ports and show them on render
|
||||
OperationNode.prototype.showPorts = function(ids, areInputs) {
|
||||
this.decorator.hidePorts();
|
||||
this.decorator.showPorts(ids, areInputs);
|
||||
|
||||
if (arguments.length === 0) { // Show all
|
||||
this.decorator.showPorts(ids, !areInputs);
|
||||
}
|
||||
|
||||
this._visiblePorts = arguments;
|
||||
};
|
||||
|
||||
OperationNode.prototype.refreshPorts = function() {
|
||||
if (this._visiblePorts) {
|
||||
this.showPorts.apply(this, this._visiblePorts);
|
||||
}
|
||||
};
|
||||
|
||||
OperationNode.prototype.getPortLocation = function(id, isInput) {
|
||||
var relpos = this.decorator.getPortLocation(id, isInput);
|
||||
return {
|
||||
x: relpos.x + this.x - this.width/2,
|
||||
y: relpos.y + this.y
|
||||
};
|
||||
};
|
||||
|
||||
OperationNode.prototype.hidePorts = function() {
|
||||
this.decorator.hidePorts();
|
||||
this._visiblePorts = null;
|
||||
};
|
||||
|
||||
OperationNode.prototype.updatePort = function(/*desc*/) {
|
||||
// TODO
|
||||
};
|
||||
|
||||
OperationNode.prototype.addPort = function(/*desc*/) {
|
||||
// TODO
|
||||
};
|
||||
|
||||
OperationNode.prototype.onSelect = function() {
|
||||
this.decorator.onSelect();
|
||||
this.showPorts();
|
||||
};
|
||||
|
||||
OperationNode.prototype.onDeselect = function() {
|
||||
this.decorator.onDeselect();
|
||||
this.hidePorts();
|
||||
};
|
||||
|
||||
return OperationNode;
|
||||
});
|
||||
@@ -0,0 +1,239 @@
|
||||
/*globals define*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Thu May 19 2016 14:04:47 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'./OperationNode',
|
||||
'./Connection',
|
||||
'./SelectionManager',
|
||||
'underscore',
|
||||
'css!./styles/PipelineEditorWidget.css'
|
||||
], function (
|
||||
EasyDAGWidget,
|
||||
PipelineControl,
|
||||
OperationNode,
|
||||
Connection,
|
||||
SelectionManager,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var PipelineEditorWidget,
|
||||
WIDGET_CLASS = 'pipeline-editor',
|
||||
STATE = {
|
||||
DEFAULT: 'default',
|
||||
CONNECTING: 'connecting'
|
||||
};
|
||||
|
||||
PipelineEditorWidget = function (logger, container) {
|
||||
EasyDAGWidget.call(this, logger, container);
|
||||
this.$el.addClass(WIDGET_CLASS);
|
||||
this.portIdToNode = {};
|
||||
this.PORT_STATE = STATE.DEFAULT;
|
||||
this._connForPort = {};
|
||||
this._itemsShowingPorts = [];
|
||||
};
|
||||
|
||||
_.extend(PipelineEditorWidget.prototype, EasyDAGWidget.prototype);
|
||||
PipelineEditorWidget.prototype.ItemClass = OperationNode;
|
||||
PipelineEditorWidget.prototype.SelectionManager = SelectionManager;
|
||||
PipelineEditorWidget.prototype.Connection = Connection;
|
||||
|
||||
PipelineEditorWidget.prototype.onCreateInitialNode =
|
||||
PipelineControl.prototype.onCreateInitialNode;
|
||||
|
||||
PipelineEditorWidget.prototype.setupItemCallbacks = function() {
|
||||
EasyDAGWidget.prototype.setupItemCallbacks.call(this);
|
||||
this.ItemClass.prototype.connectPort =
|
||||
PipelineEditorWidget.prototype.connectPort.bind(this);
|
||||
this.ItemClass.prototype.disconnectPort =
|
||||
PipelineEditorWidget.prototype.disconnectPort.bind(this);
|
||||
};
|
||||
|
||||
//////////////////// Port Support ////////////////////
|
||||
PipelineEditorWidget.prototype.addConnection = function(desc) {
|
||||
EasyDAGWidget.prototype.addConnection.call(this, desc);
|
||||
// Record the connection with the input (dst) port
|
||||
var dstItem = this.items[desc.dst],
|
||||
dstPort;
|
||||
|
||||
this._connForPort[desc.dstPort] = desc.id;
|
||||
if (dstItem) {
|
||||
dstPort = dstItem.inputs.find(port => port.id === desc.dstPort);
|
||||
|
||||
if (!dstPort) {
|
||||
this._logger.error(`Could not find port ${desc.dstPort}`);
|
||||
return;
|
||||
}
|
||||
|
||||
dstPort.connection = desc.id;
|
||||
// Update the given port...
|
||||
dstItem.refreshPorts();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.addNode = function(desc) {
|
||||
EasyDAGWidget.prototype.addNode.call(this, desc);
|
||||
// Update the input port connections (if not connection)
|
||||
var item = this.items[desc.id];
|
||||
if (item) {
|
||||
item.inputs.forEach(port =>
|
||||
port.connection = this._connForPort[port.id]
|
||||
);
|
||||
// Update the item's ports
|
||||
item.refreshPorts();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype._removeConnection = function(id) {
|
||||
// Update the input node (dstPort)
|
||||
var conn = this.connections[id].desc,
|
||||
dst = this.items[conn.dst],
|
||||
port;
|
||||
|
||||
if (dst) {
|
||||
port = dst.inputs.find(port => port.id === conn.dstPort);
|
||||
port.connection = null;
|
||||
dst.refreshPorts();
|
||||
}
|
||||
EasyDAGWidget.prototype._removeConnection.call(this, id);
|
||||
};
|
||||
|
||||
// May not actually need these port methods
|
||||
PipelineEditorWidget.prototype.addPort = function(desc) {
|
||||
this.items[desc.nodeId].addPort(desc);
|
||||
this.portIdToNode[desc.id] = desc.nodeId;
|
||||
this.refreshUI();
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.updatePort = function(desc) {
|
||||
this.items[desc.nodeId].updatePort(desc);
|
||||
this.refreshUI();
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.removeNode = function(gmeId) {
|
||||
if (this.portIdToNode.hasOwnProperty(gmeId)) {
|
||||
this.removePort(gmeId);
|
||||
} else {
|
||||
EasyDAGWidget.prototype.removeNode.call(this, gmeId);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.removePort = function(portId) {
|
||||
var nodeId = this.portIdToNode[portId];
|
||||
if (this.items[nodeId]) {
|
||||
this.items[nodeId].removePort(portId);
|
||||
this.refreshUI();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.disconnectPort = function(portId, connId) {
|
||||
this.removeConnection(connId);
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.connectPort = function(nodeId, id, isOutput) {
|
||||
this._logger.info('port ' + id + ' has been clicked! (', isOutput, ')');
|
||||
if (this.PORT_STATE === STATE.DEFAULT) {
|
||||
this.startPortConnection(nodeId, id, isOutput);
|
||||
} else if (this._selectedPort !== id) {
|
||||
this._logger.info('connecting ' + this._selectedPort + ' to ' + id);
|
||||
var src = !isOutput ? this._selectedPort : id,
|
||||
dst = isOutput ? this._selectedPort : id;
|
||||
|
||||
this.createConnection(src, dst);
|
||||
} else if (!this._selectedPort) {
|
||||
this._logger.error(`Invalid connection state: ${this.PORT_STATE} w/ ${this._selectedPort}`);
|
||||
this.resetPortState();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.startPortConnection = function(nodeId, id, isOutput) {
|
||||
var existingMatches = this.getExistingPortMatches(id, isOutput),
|
||||
item = this.items[nodeId];
|
||||
|
||||
// Hide all ports except 'id' on 'nodeId'
|
||||
this._selectedPort = id;
|
||||
item.showPorts(id, !isOutput);
|
||||
|
||||
// Get all existing potential port destinations for the id
|
||||
existingMatches.forEach(match =>
|
||||
this.showPorts(match.nodeId, match.portIds, isOutput)
|
||||
);
|
||||
|
||||
// Show the 'add' button
|
||||
// TODO
|
||||
|
||||
this.PORT_STATE = STATE.CONNECTING;
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.onDeselect =
|
||||
PipelineEditorWidget.prototype.resetPortState = function() {
|
||||
// Reset connecting state
|
||||
this._itemsShowingPorts.forEach(item => item.hidePorts());
|
||||
this.PORT_STATE = STATE.DEFAULT;
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.showPorts = function(nodeId, portIds, areInputs) {
|
||||
var item = this.items[nodeId];
|
||||
item.showPorts(portIds, areInputs);
|
||||
this._itemsShowingPorts.push(item);
|
||||
};
|
||||
|
||||
// No extra buttons - just the empty message!
|
||||
PipelineEditorWidget.prototype.refreshExtras =
|
||||
PipelineEditorWidget.prototype.updateEmptyMsg;
|
||||
|
||||
PipelineEditorWidget.prototype.refreshConnections = function() {
|
||||
// Update the connections to they first update their start/end points
|
||||
var connIds = Object.keys(this.connections),
|
||||
src,
|
||||
dst,
|
||||
conn;
|
||||
|
||||
for (var i = connIds.length; i--;) {
|
||||
conn = this.connections[connIds[i]];
|
||||
|
||||
// Update the start/end point
|
||||
src = this.items[conn.src];
|
||||
conn.setStartPoint(src.getPortLocation(conn.srcPort));
|
||||
|
||||
dst = this.items[conn.dst];
|
||||
conn.setEndPoint(dst.getPortLocation(conn.dstPort, true));
|
||||
|
||||
conn.redraw();
|
||||
}
|
||||
};
|
||||
|
||||
// Record the connections connected to input ports on connection creation
|
||||
// TODO
|
||||
|
||||
// Also, render the connections so they connect operations using the ports
|
||||
// (if the ports are rendered)
|
||||
// TODO
|
||||
|
||||
//////////////////// Action Overrides ////////////////////
|
||||
|
||||
PipelineEditorWidget.prototype.onAddItemSelected = function(item, selected) {
|
||||
this.createConnectedNode(item.id, selected.node.id);
|
||||
};
|
||||
|
||||
//PipelineEditorWidget.prototype.createNodeAfter = function(srcId, type) {
|
||||
//// Figure out the valid input and output port pairing(s)
|
||||
//// TODO
|
||||
|
||||
//// If none, error!
|
||||
//// TODO
|
||||
|
||||
//// If one, continue
|
||||
//// TODO
|
||||
|
||||
//// If many, prompt the user about the input/output
|
||||
//// TODO
|
||||
//};
|
||||
return PipelineEditorWidget;
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/*globals define*/
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
Buttons,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var SelectionManager = function(widget) {
|
||||
EasyDAGSelectionManager.call(this, widget);
|
||||
};
|
||||
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(/*width, height*/) {
|
||||
// move the 'x' to the top left
|
||||
new Buttons.DeleteOne({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
};
|
||||
|
||||
SelectionManager.prototype.deselect = function() {
|
||||
EasyDAGSelectionManager.prototype.deselect.call(this);
|
||||
// Update the widget's 'port connecting' state
|
||||
this._widget.onDeselect();
|
||||
};
|
||||
|
||||
return SelectionManager;
|
||||
});
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário