Comparar commits

..

55 Commits

Autor SHA1 Mensagem Data
Brian Broll 0207e73f6a v0.4.0 2016-06-06 08:12:04 -05:00
Brian Broll d5ec893264 Removed ExecView subclass of PipelineEditor. Fixes #215 (#216) 2016-06-04 11:06:46 -05:00
Brian Broll c0c36e8774 Fixed logger typo. Fixes #211 (#212) 2016-06-04 09:44:17 -05:00
Brian Broll 3ea0099347 Updated selObjChanged to check nodeId & updated deps. Fixes #208 (#209)
WIP #208 Added nodeId checks and logs for selectedObjChanged

WIP #208 Updated webgme-autoviz and webgme-fab
2016-06-04 08:47:55 -05:00
JimnyCricket 8ab026c5aa Merge pull request #204 from dfst/203-getid-of-null-fab-root
Added check for base node existing. Fixes #203
2016-06-03 13:37:40 -05:00
Brian Broll 8e07b4de97 Added check for base node existing. Fixes #203 2016-06-03 10:13:26 -05:00
Brian Broll 949100545d Updated the condensed transform and port locations. Fixes #200 (#201) 2016-06-03 08:39:39 -05:00
Brian Broll f37ed09777 Moved layer color assignment to ArchControl Fixes #164 (#199) 2016-06-03 07:52:43 -05:00
Brian Broll 0bcc0981dc Updated fab to wait for territory update Fixes #195 (#198)
WIP #195 Added onNodeLoad override

WIP #195 Made ArchEditor, ExecView embeddable

WIP #195 Fixed "super" onNodeLoad call

WIP #195 Updated fab dependency
2016-06-03 05:23:42 -05:00
Brian Broll 649df26bd4 Added delimiters for operation start and finish in worker. Fixes #163 (#197) 2016-06-03 04:43:49 -05:00
Brian Broll 970822ffee Added suffix for meta node actions. Fixes #169 (#196) 2016-06-03 04:35:34 -05:00
Brian Broll 025728729c Updated autoviz version. Fixes #179 (#194) 2016-06-03 04:11:36 -05:00
Brian Broll c7d29110b5 Added npm run local command. Fixes #121 (#193) 2016-06-02 20:34:14 -05:00
Brian Broll 0774c11ec2 Removed initial node constraints Fixes #186 (#191)
WIP #186 Deleted comment
2016-06-02 18:23:01 -05:00
Brian Broll 6cc7565e97 Added support for ports in PipelineEditor Fixes #178 (#192)
WIP #178 Moved delete button to top left

WIP #178 Added basic port rendering

WIP #178 Added labels for ports and fixed input pos's

WIP #178 Added support for connecting op ports

WIP Made PipelineEditor embedded

WIP #178 Added conn deletion

WIP #178 Fixed backwards connecting

WIP #178. Remove port opts that would create a cycle

WIP #178 Added single node delete

WIP #178 Updated connections to ports and removed create btn

WIP #178 Fixed port color on change
2016-06-02 18:22:38 -05:00
Brian Broll 90964afa23 Set display name for OpDec. Fixes #173 (#187) 2016-06-02 08:48:17 -05:00
Brian Broll 12439b15b9 Added op creation to fab. Fixes #177 (#185)
WIP #177 Added button

Added necessary callbacks to mixin WIP #177

WIP #177. Added PipelineWidget to use callbacks from mixin
2016-06-02 08:21:10 -05:00
JimnyCricket 317f033997 Merge pull request #181 from dfst/168-cursor-jumps
Fixed text updating. Fixes #168
2016-06-01 19:06:34 -04:00
Brian Broll 716b4aacff Added default names for pipelines, data, ops. Fixes #172 (#182) 2016-06-01 17:57:34 -05:00
Brian Broll 6f8612233f Fixed text updating. Fixes #168 2016-06-01 17:42:39 -05:00
Brian Broll e5acb09206 Embeddable rootviz. Fixes #160 (#161) 2016-06-01 15:21:39 -05:00
Brian Broll d8fac840b0 Added data type editor. Fixes #137 (#159)
WIP #137 Updated the default visualizers in seeds
2016-06-01 15:12:24 -05:00
Brian Broll 9bce45a786 Fixes #97 Added basic OperationEditor (#158)
WIP #97 Added tiling viz

WIP #97 Added OpInterfaceEditor, OpCodeEditor

WIP #97 Fixed node error with deep territories

WIP #97 Added data preparation for interface visualization

WIP #97 Fixed text editor sizing

WIP #97 Added node updates to panels

WIP #97 Added creating outputs

WIP #97 Updated selection for op interface

WIP #97 Added input creation functionality

WIP #97 Added custom dec w/ name editing

WIP #97 Added type tooltip

WIP #97 Fixed problem with split mode and OpInt

WIP #97 Added header updates for OperationCodeEditor

WIP #97 Increased delay on text save

WIP #97 Added embeddability

WIP #97 Updated comment for outputs

WIP #97 Updated seeds and input btn disabled rule

WIP #97 Added some ptr renaming support

WIP #97 Added deletion and fixed update bug
2016-06-01 14:42:15 -05:00
Brian Broll b8a82cf0fc Fixes #151 Fixed/updated plugin execution (#152)
WIP Fixed/updated plugin execution

WIP Added save dir detection

WIP Updated serialize dir

WIP Added 60min_blitz seed and git lfs

WIP Updated pipeline and root viz

Removed unworking 60min blitz
2016-05-31 08:10:23 -05:00
Brian Broll 5090df8358 v0.3.0 2016-05-30 15:52:00 -05:00
Brian Broll 6ca72a5b83 Set the job dec name to node name. Fixes #148 (#149) 2016-05-30 12:42:40 -05:00
Brian Broll 3a8454b582 Fixes #132 Added efficient data handling in the browser (#147)
WIP #132 Added name change w/ metadata... Not fixing zip file

WIP #132 Updated renaming to use metadata (no more dl-ing data!)

WIP #132. Chaining operations works!

WIP #132. Removed unneeded comments

WIP #132. cleaned up hash retrieval code
2016-05-30 12:39:39 -05:00
Brian Broll e25d376080 Set the conn type to Transporter. Fixes #145 (#146) 2016-05-30 10:28:29 -05:00
Brian Broll b7a823cf37 Added 'nodeName' option for RootViz. Fixes #143 (#144) 2016-05-30 10:28:22 -05:00
Brian Broll 504fe4652a Fixes #139 Added color coded jobs in execution view (#142)
WIP #139 Added JobDecorator

WIP #139 Added colored job nodes in execution view
2016-05-30 10:28:06 -05:00
Brian Broll b8021f467c Fixes #134. Updated ser/deser to be given 'path' to save to/read from (#136)
WIP #134. Updated templates

WIP #134 Added filepath to template contents
2016-05-27 22:26:20 -05:00
Brian Broll 4d49036e81 Added inheritance for actions by metatype. Fixes #130 (#133) 2016-05-27 16:17:50 -05:00
Brian Broll d738a54cb2 Explicitly added territory rule. Fixes #129 (#131)
The source of the problem is actually in webgme-easydag
2016-05-27 13:44:01 -05:00
Brian Broll c2213d216b Added support for MONGO_URI, PORT, env vars. Fixes #108 (#128)
WIP #108 Added .env to gitignore
2016-05-27 08:54:25 -05:00
Brian Broll fd9d728b1e Added execution dir detection. Fixes #125 (#126)
Also fixed executing empty pipelines
2016-05-27 08:36:23 -05:00
Brian Broll 32a3802244 Updated webgme-fab dep. Fixes #118 (#119) 2016-05-26 18:17:18 -05:00
Brian Broll c61009b67f Updated code generation. Op's should return table. Fixes #115 (#116) 2016-05-26 17:46:02 -05:00
Brian Broll bb3ce453c4 Removed requirement for all local op types in meta. Fixes #112 (#114) 2016-05-26 17:26:30 -05:00
Brian Broll c9fb8fe855 Added new operation to general meta set. Fixes #111 (#113) 2016-05-26 16:51:46 -05:00
Brian Broll 814995214f Fixes #106 Added fab actions (#107)
Added operation, data type proto creation
2016-05-26 12:53:42 -05:00
Brian Broll c993c1784b Added card-styled root viz. Fixes #103 (#105)
WIP #103 Removed extra comments, file
2016-05-26 11:39:32 -05:00
Brian Broll 788abb1512 Added project seed. Fixes #102 (#104) 2016-05-26 09:46:34 -05:00
Brian Broll 13f7f470e0 Updated pipeline seed to use new operation format. Fixes #60 (#101) 2016-05-26 09:03:00 -05:00
Brian Broll a835c02e52 Merge branch '99-style-rules' 2016-05-26 08:46:46 -05:00
Brian Broll c46d70ebe2 Updated the operation input parsing for OperationEditor. Fixes #96 (#98) 2016-05-26 08:45:35 -05:00
Brian Broll e7d554578d Added eslint, jshint config. Fixes #99
WIP #99 Updated code style violations
2016-05-26 08:45:00 -05:00
Brian Broll 289277aaf0 Updated css rules for text editor. Fixes #75 (#95) 2016-05-26 07:36:21 -05:00
Brian Broll 0671b7ade6 Fixes #80 Updated ExecutePipeline for new ops (#94)
WIP #80 Refactored CreateExecution for easier extension

WIP #80 Fixed linter errors

WIP #80 Refactoring for different node types

WIP #80 Refactored getting op inputs/outputs

WIP #80 Fixed CreateExecution when op has no input/output node

WIP #80 Fixed conn src/dst resolution in execution

WIP #80 Mostly added support for new operation/job structure

WIP #80 Generating correct files

WIP #80 Fixed onOperationComplete w/ no outputs

WIP #80. Fixed the data passing through ops

WIP #80. One file? -> don't zip it!

WIP #80. Fixed UploadText.

WIP #80 Added support for chained operations

WIP #80 Skipped ExecPipeline tests
2016-05-25 18:11:54 -05:00
Brian Broll f6da8485b5 Added support for initial op detection. Fixes #91 (#92) 2016-05-24 20:21:08 -05:00
Brian Broll cbd31c51d2 Fixes #89 Updated territory and added nodes (#90)
WIP #89 Added check for added nodes

WIP #89 Updated territory to contain all operations in meta
2016-05-24 20:03:41 -05:00
Brian Broll 9508351c54 Fixes #83 Added plugin for snapshotting pipelines (#87)
WIP #83 Added CreateExecution plugin

WIP #83 Fixed pointer resolution for data nodes

WIP #83 Added 'Job boxing'

WIP #83 Fixed connection ptr resolution

WIP #83. Skipping CE tests
2016-05-24 13:32:15 -05:00
Brian Broll 6a7f22bd3e Fixes #63 Added basic ExecutionView (#88)
WIP #63 Added basic execution view boilerplate

WIP #63

WIP #63. Added custom selection manager
2016-05-24 12:29:35 -05:00
Brian Broll 3c06fd6289 Only get operation data if relevant. Fixes #84 (#86)
WIP #84 Removed old comment
2016-05-24 09:21:25 -05:00
Brian Broll e31206658d Fixes #76 Added PipelineEditor (#79)
WIP #76 Added pipeline viz w/ custom decorator

WIP #76 Adding support for creating cnected nodes

WIP #76 No error on conn creation... Then fail..

WIP #76 Added basic pipeline viz support

WIP #76 Removed 'code' attribute
2016-05-23 09:45:53 -05:00
Brian Broll 68f46eb5d2 v0.2.0 2016-05-23 09:38:54 -05:00
122 arquivos alterados com 10262 adições e 812 exclusões
+4
Ver Arquivo
@@ -0,0 +1,4 @@
src/common/lua.js
src/visualizers/widgets/TextEditor/lib/*
src/common/js-yaml.min.js
src/visualizers/Visualizers.json
+18
Ver Arquivo
@@ -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
+1
Ver Arquivo
@@ -0,0 +1 @@
*.webgmex filter=lfs diff=lfs merge=lfs -text
+3
Ver Arquivo
@@ -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/
+3
Ver Arquivo
@@ -0,0 +1,3 @@
{
"esversion": 6
}
+7 -3
Ver Arquivo
@@ -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);
});
+25
Ver Arquivo
@@ -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));
+29 -1
Ver Arquivo
@@ -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."
}
]
}
}
+8 -3
Ver Arquivo
@@ -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;
+2
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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": {
+11 -27
Ver Arquivo
@@ -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 -1
Ver Arquivo
@@ -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--;) {
+42
Ver Arquivo
@@ -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;
});
+141
Ver Arquivo
@@ -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;
});
+43
Ver Arquivo
@@ -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;
});
+14
Ver Arquivo
@@ -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": []
}
+1 -2
Ver Arquivo
@@ -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);
+362 -348
Ver Arquivo
@@ -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;
});
+102
Ver Arquivo
@@ -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 %>
-12
Ver Arquivo
@@ -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 %>)
<% }); %>
-8
Ver Arquivo
@@ -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,3 +1,4 @@
/*globals define*/
define([
'text!./entry.ejs',
'text!./main.ejs',
@@ -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'
+7 -11
Ver Arquivo
@@ -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.
+3
Ver Arquivo
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bcb09f0e67a5840a0579fa44353602b20a4203452c00b59796ce9bc2026666d2
size 343292
+55 -1
Ver Arquivo
@@ -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;
});
+132 -19
Ver Arquivo
@@ -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;
@@ -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;
});
+5 -2
Ver Arquivo
@@ -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;
});
@@ -6,5 +6,5 @@
* simply write css if you prefer
*/
.operation-editor {
.execution-view {
outline: none; }
@@ -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;
});
@@ -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; }
@@ -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