Comparar commits

..

80 Commits

Autor SHA1 Mensagem Data
Brian Broll 3676d4c340 WIP Added istanbul 2016-10-02 09:04:17 -05:00
Brian Broll 16668468f4 Added boolean type check for attributes. Fixes #832 (#834) 2016-09-28 21:31:51 -05:00
Brian Broll ffae88a168 Set the exec status to 'running' on job restart. Fixes #831 (#833) 2016-09-28 21:27:45 -05:00
Brian Broll 25f5759c17 Cancel job if the exec has been canceled. Fixes #820 (#830)
* Cancel job if the exec has been canceled. Fixes #820

* WIP #820 Added test for stopping watching on cancel

* WIP #820 Increased the timeout for import torch
2016-09-27 19:28:57 -05:00
Brian Broll 7a0eae386f Added run.sh script to execution files. Fixes #818 (#829)
* WIP Added basic run.sh script creation

* WIP #818. Added baseURL... still needs work

* WIP #818 Added prompt for DEEPFORGE_URL and fixed wget issue
2016-09-27 15:01:51 -05:00
Brian Broll af5d74483a Added read-only tier of changes being applied. Fixes #826 (#827)
* Added read-only tier of changes being applied. Fixes #826

WIP #826 Updated currentChanges name. Added debugging

WIP #826 Added get/setAttr test for ExecJob

WIP #826 Added get/set attr tests

WIP #826 Added logs to try to figure out what on earth is going wrong

WIP #826 Fixed typo in test

WIP #826 Removed debugging logging

WIP #826 Enabled all tests

* WIP #826 Fixed code climate issue
2016-09-26 19:18:20 -05:00
Brian Broll 9bf7632aba Update README.md 2016-09-24 15:24:43 -05:00
Brian Broll d7f3544bb3 v0.16.0 2016-09-19 17:48:51 -05:00
Brian Broll 19a7b2a8fa Apply node creation/deletion before save. Fixes #824 (#825)
* WIP #824 Added extra logs

* WIP #824 Moved creation events to the local diff strategy

* WIP #824 Added deletion event to the local stored changes to apply

* WIP #824 Fixed variable name

* WIP #824 Fixed apply dependent creation changes

* WIP #824 Update local operation setAttr, getAttr

* WIP #824 Updated execpipeline save method

* WIP #824 Fixed code climate issue

I will probably remove all ArtifactFinder fn-ality

* WIP #824 Removed unused var

* WIP #824 update the meta on fast forward
2016-09-17 14:40:09 -05:00
Brian Broll aadd581189 Fixed regex for plotting negative numbers. Fixes #822 (#823) 2016-09-15 10:26:03 -05:00
Brian Broll a5d00efd39 Improved logo and icon legibility (#819)
WIP Changed logo font to "regular" for better legibility.

 WIP Changed node color on Icon

WIP CHANGED COLOR OF NODE TO MAKE MORE VISIBLE
2016-09-14 07:56:39 -05:00
Brian Broll a239c7bd44 Updated 'SGD' to graph error by default. Fixes #815 (#816) 2016-09-13 14:32:34 -05:00
Brian Broll 5871b5058e Better log-storage error handling on fork. Fixes #813 (#814)
WIP #813 Check if file exists before copy

WIP #813 Added test
2016-09-13 13:48:47 -05:00
Brian Broll 3a8108b321 Added deepforge.Image w/ update, title. Fixes #799 (#812)
WIP #799 Added deepforge.Image basics

WIP #799 deepforge.Image creates image

WIP #799 Fixed the image id creation

WIP #799 Don't reset zoom on image update

WIP #799 Added support for updating image names

WIP #799 Added id to deepforge.image

WIP #799 Fixed the simple image and log msg
2016-09-13 13:09:32 -05:00
Brian Broll b18a3b2747 Hide "monitor" button for Input/Outputs. Fixes #810 (#811) 2016-09-13 12:04:31 -05:00
Brian Broll 884ba2557f Delete executions w/ pipeline. Fixes #773 (#808)
WIP #773 Fixed deleting not loaded exec nodes
2016-09-13 11:23:23 -05:00
Brian Broll e2d3058de1 Added in-sync check for executions. Fixes #789 (#809) 2016-09-13 11:21:37 -05:00
Brian Broll 02739bfd62 Fixed saving race conditions in pipeline/job execution. Fixes #787 (#790)
* WIP #787 Fixing async race conditions in execs

* WIP #787 Fixed issues w/ the batched changes

* WIP #787 Added delAttribute
2016-09-13 10:18:38 -05:00
Brian Broll 89e2e387c7 Verified valid originIds before adding to territory. Fixes #753 (#807) 2016-09-13 08:28:45 -05:00
Brian Broll 0ac2b1b6ab Added deepforge.initialize(). Fixes #798 (#806)
WIP #798 Updated deepforge completer
2016-09-12 20:25:11 -05:00
Brian Broll a36e8df404 Added missing \n's to stdout. Fixes #804 (#805) 2016-09-11 20:26:01 -05:00
Brian Broll 93a89ddaa1 Fixed graph updating, express dependency Fixes #802 (#803)
WIP #802 Added express dependency

WIP #802 Added carriage return check to log-storage api

WIP #802 Fixed saving for graphs, images

Also fixed bug when using xlua progress bar w/ graphs
2016-09-11 13:33:51 -05:00
Brian Broll 7281dcefc6 Added log-storage for running jobs. Fixes #785 (#800)
WIP #785 Initial router commit

WIP #785 Added the log manager api

WIP #785 Added some comments for needed updates

WIP #785 Fixed typo in export

WIP #785 Added basic fn-ality to JobLogsClient

WIP #785 Added tests for the log router

WIP #785 uri encode project, branch. Updated viz to use the log-storage

WIP #785 Fixed updating on stdout update

WIP #785 Filtered out stdout update msgs from the notification widget

WIP #785 Added stdout save on canceled

WIP #785 Added tests for the joblogsclient

WIP #785 Moved job logs client to src/common

WIP #785 Added forking support to api

WIP #785 Added fork support for the job log client

WIP #785 Fixed flashing on canceled job

WIP #785 Fixed minor code climate issues

WIP #785 Create test-tmp on npm test
2016-09-10 17:34:36 -05:00
Brian Broll bfc1f08c7e Added 'net' to used var and fixed omitted vars. Fixes #795 (#796)
WIP #795 fixed the duplicate varnames

WIP #795 only omit last unset values

WIP #795 Replaced omitted, required values w/ nil

WIP #795 Updated tests
2016-09-09 16:47:42 -05:00
Brian Broll ad08fce281 Merge branch 'master' of https://github.com/dfst/deepforge 2016-09-05 08:56:14 -05:00
Brian Broll bb2a67e3f6 v0.15.0 2016-09-05 08:55:52 -05:00
Brian Broll 3f0b7e4720 Added check for compatible node version. Fixes #552 (#794) 2016-09-03 18:03:17 -05:00
Brian Broll 728c56261d Preserve jobs on server restart. Fixes #752 (#793)
WIP #752 Updated config.local.js setting
2016-09-03 17:49:46 -05:00
Brian Broll a3dd12386e Updated default torch base class for custom layers. Fixes #776 (#792)
WIP #776 Updated template for providing torch base class

WIP #776 Updated custom layer template

WIP #776 Updated nn library to 0.2.0
2016-09-03 17:15:49 -05:00
Brian Broll c017f9a1d7 Stored lib version w/ hash and clear on start. Fixes #788 (#791)
WIP #788 Clear the hash info on server start (in case blob changed)

WIP #788 Added version info to hash file.

WIP #788 Removed old comment
2016-09-03 14:27:41 -05:00
Brian Broll 6d95f21550 Filtered out old commands. Fixes #782 (#784)
Filtered out old lines. Fixes #782
2016-09-01 12:37:48 -05:00
Brian Broll 11cb9259d8 Filtered out undefined lineIds. Fixes #780 (#781) 2016-09-01 12:12:54 -05:00
Drew Martin 71f575c857 772 update logo (#779)
* WIP #772 Added background image. Still need to fix height

* WIP #772 Fixed height issues

* WIP #772 Added placeholders for gme-logo

* WIP #772 Added Logo

*  WIP #772 Added Icon
2016-08-31 21:19:23 -05:00
Brian Broll cf4404eaf7 Only save final changes if not deleted. Fixes #770 (#778) 2016-08-31 19:52:17 -05:00
Brian Broll 6ef0cb0bdc Removed ArtifactFinder (pipeline v0.3.0). Fixes #760 (#777) 2016-08-31 18:48:56 -05:00
Brian Broll e128cc408e Renamed ArtifactLoader, Save to Input, Output. Fixes #761 (#775)
* Renamed ArtifactLoader, Save to Input, Output. Fixes #761

WIP #761 Refactored ArtifactLoader references

WIP #761 Renamed ArtifactLoader -> Input; Save -> Output

WIP #761 Updated pipeline seed

WIP #761 Renamed Save -> Output

* WIP #761 Updated pipeline library

* WIP #761 Updated pipeline seed
2016-08-31 18:02:53 -05:00
Brian Broll 1477421f1a Added automatic library update detection. Fixes #410 (#771)
WIP #410 initial plugin creation

WIP #410 Added checking for library version info

WIP #410 Added library upload on out-of-date lib detection

WIP #410 Added ui indicator about updates available

WIP #410 Updated log/toast messages

WIP #410 Added library creation utility

WIP #410 Remove sync methods and added more logging

WIP #410 Updated the hash retrieval

WIP #410 Updated library version  method

WIP #410 Added versioned lib seeds

WIP #410 Fixed library update plugin

WIP #410 Fixing library checking

WIP #410 Fixed update message

WIP #410 Fixed version comparison

WIP #410 Removed unused method

WIP #410 Skipping update library tests

WIP #410 update check libraries check

WIP #410 Added toast updates

WIP #410 Updated nn, pipeline dependencies
2016-08-31 17:34:35 -05:00
Brian Broll 671a8af458 Added check for messages before displaying them. Fixes #768 (#769) 2016-08-30 15:23:59 -05:00
Brian Broll a4fcc73e9f Detect correct mongo port on start. Fixes #766 (#767)
WIP #766 Fixed `start -m`

WIP #766 Added error if starting remote mongo

WIP #766 Fixed error message
2016-08-30 12:49:09 -05:00
Brian Broll e88fb302d4 Added css, js map files. Fixes #762 (#764) 2016-08-30 12:20:57 -05:00
Brian Broll ff1f29955a Added architecture creation reference. Fixes #757 (#758)
WIP #757 Fixed unused variable and code dupe
2016-08-30 09:47:37 -05:00
Brian Broll 0b71ff6b9d Updated fab to use component settings. Fixes #755 (#756) 2016-08-30 08:13:07 -05:00
Brian Broll 4f3b6c5e39 Delete execution tag on execution delete. Fixes #739 (#749) 2016-08-25 22:50:52 -05:00
Brian Broll fe0c95116f Stopping Execution on delete. Fixes #726 (#748)
WIP #726 Stopping execution on delete

WIP #726 Added silent job/exec canceling

Added fast-forward to ExecutePipeline on merge. Fixes #682

WIP #682 Added cache update on merge

WIP #682 Updating cache, rootNode, activeNode on merge

WIP #682 Changed to fast-forward

WIP #682 Fixed merge errors w/ multi executions

WIP #682 Added fast-forward to ExecuteJob

WIP #682 Added more logs and removed old comment

Added symlink to node_modules. Fixes #724

WIP #726 Added silent job/exec canceling

WIP #726 Added some boilerplate for pipeline deletion

WIP #726 Fixed execution deletion checking

WIP #726 Removed unused variables
2016-08-25 21:46:12 -05:00
Brian Broll 4429cb11d4 Added flag for inTransaction on text save in text editors. Fixes #746 (#747) 2016-08-25 18:41:11 -05:00
Brian Broll 56b20ab429 v0.14.1 2016-08-24 19:44:52 -05:00
Brian Broll 4d0f4c3609 Added fast-forward to ExecutePipeline on merge. Fixes #682 (#712)
WIP #682 Added cache update on merge

WIP #682 Updating cache, rootNode, activeNode on merge

WIP #682 Changed to fast-forward

WIP #682 Fixed merge errors w/ multi executions

WIP #682 Added fast-forward to ExecuteJob

WIP #682 Added more logs and removed old comment
2016-08-24 19:42:04 -05:00
Brian Broll 209f46adb0 Improved name change detection and added transaction. Fixes #744 (#745)
WIP #744 Fixed name setting on every save

WIP #744 Placed 'saveTextFor' in a transaction
2016-08-24 17:18:53 -05:00
Brian Broll 2ac374a56e Added return template generation for operations. Fixes #247 (#742)
WIP #247 Fixed code climate issue

WIP #247 undefined var
2016-08-23 10:21:17 -05:00
Brian Broll fc4c5db0ce Added 'q' dependency. Fixes #740 (#741) 2016-08-23 08:08:49 -05:00
Brian Broll 1578886584 v0.14.0 2016-08-22 07:04:42 -05:00
Brian Broll 0927c2c270 Added npm install instructions 2016-08-20 15:08:45 -05:00
Brian Broll bd329bdfe3 Forwarded stdin to subprocess. Fixes #737 (#738)
WIP #737 Added stdin forwarding

WIP #737 Fixed rnn installation

WIP #737 Updated tests
2016-08-20 11:25:49 -05:00
Brian Broll e3a499f409 Improved error handling on torch install. Fixes #705 (#736)
WIP #705

WIP #705 Fixed error detection on torch install

WIP #705 Changed to Q promises

WIP #705 Updated tests
2016-08-20 08:45:52 -05:00
Brian Broll 63c78426d3 Downgraded nvd3 to v1.8.2. Fixes #593 (#735) 2016-08-19 16:05:27 -05:00
Brian Broll 6ec2f69268 Set y axis precision to 2 places. Fixes #674 (#734) 2016-08-19 15:38:33 -05:00
Brian Broll 1ccd193ddd Hide lines w/ no points. Fixes #732 (#733) 2016-08-19 15:07:28 -05:00
Brian Broll a5d52dce33 Added exec abbreviations when multiple selected in index. Fixes #675 (#731)
WIP #675 Added execIds to executions in ExecIndex

WIP #675 Updated line name if multi execs showing

WIP #675 show execution abbreviation if needed

WIP #675 Fixed code climate issues
2016-08-19 14:51:46 -05:00
Brian Broll ca358ae7b9 Added custom layers to the nn import mock. Fixes #729 (#730) 2016-08-19 11:43:21 -05:00
Brian Broll 0a1177c299 Created tag after execution saved. Fixes #727 (#728) 2016-08-19 11:42:14 -05:00
Brian Broll 46bf346c5c Added symlink to node_modules. Fixes #724 (#725) 2016-08-19 09:55:50 -05:00
Brian Broll 8a94496e01 Added "worker.dir" to config. Fixes #721 (#723) 2016-08-19 08:58:16 -05:00
Brian Broll d3cf339856 Created new directory for each worker. Fixes #720 (#722) 2016-08-19 08:47:20 -05:00
Brian Broll 5c0c58c3be Debounced execution widget updates. Fixes #713 (#719) 2016-08-18 15:10:45 -05:00
Brian Broll ef607e0e76 Removed forever-monitor from cli. Fixes #714 (#717)
WIP #714 Updated tests
2016-08-18 13:47:11 -05:00
Brian Broll 305503ac7a Changed title rename to single click. Fixes #715 (#716) 2016-08-18 12:41:55 -05:00
Brian Broll c76e62b976 Updated creation fn to use places promise. Fixes #710 (#711) 2016-08-17 16:03:14 -05:00
Brian Broll 554065ee11 Updated DeepForge.places to use promises. Fixes #681 (#709)
WIP #681 Added comments for work to be done and some place loading support

WIP #681 changed places to use promises

WIP #681 Updated MainView to use places promises
2016-08-17 15:27:32 -05:00
Brian Broll 7fba52ad97 Added shift-enter to restart jobs/execs/etc. Fixes #641 (#708)
WIP #641 Added key listener for floating action button

WIP #641 Ignored shift+enter in code editor

WIP #641 Fixed shift-enter to restart job

WIP #641 Added shift-enter for execution view

WIP #641 Fixed code climate issues
2016-08-17 13:33:43 -05:00
Brian Broll c56de24e7d Added ctrl-alt-pagedown/up to jump to EOF/beginning in logs. Fixes #667 (#707) 2016-08-17 09:45:53 -05:00
Brian Broll 6e16087fc3 Set the ArtifactLoader name to target in execution view. Fixes #574 (#706)
WIP #574 Added comments for modification locations

WIP #574 Added ArtifactLoader check

WIP #574 Set ArtifactLoader name to the pointer value
2016-08-16 16:07:54 -05:00
Brian Broll 8133acbb46 Added execution duration to ExecIndex. Fixes #628 (#704)
WIP #628 Added execution time support

WIP #628 Removed endTime on execution start

WIP #628 Added startTime, endTime to execution

WIP #628 updated pipeline lib
2016-08-16 11:14:24 -05:00
Brian Broll d974cb8215 Added margin to bottom of log viewer. Fixes #696 (#702)
WIP #696 Added 5 lines to bottom of log file

WIP #696 Set scroll margin to 75px (from bottom)
2016-08-16 10:02:25 -05:00
Brian Broll 68021c1903 Removed \u0000 from stdout logs. Fixes #700 (#701) 2016-08-16 09:55:27 -05:00
Brian Broll 7178b89578 Added better error handling for ops w/ old refs. Fixes #698 (#699) 2016-08-16 09:01:58 -05:00
Brian Broll 0935abe858 Added operation attributes to jobs in ExecutionView. Fixes #686 (#697)
WIP #686 Added opAttributes

WIP #686 Added readonly pointer, attr to job
2016-08-16 07:54:55 -05:00
Brian Broll 22225922e5 Added support for \r in job logs. Fixes #298 (#695)
WIP #298 Adding progress bar support...

WIP #298 Updated stdout logs for \r support
2016-08-15 15:25:12 -05:00
Brian Broll 343f2ffa61 Updated breadcrumb header. Fixes #662 (#694)
WIP #662 Set cachePrefix for path storage

WIP #662 Updated breadcrumbheader version
2016-08-15 12:40:42 -05:00
Brian Broll 477d38d313 Added unknown ref type error and setting. Fixes #690 (#692)
WIP #690 Added viz feedback about unknown type

WIP #690 Starting to add ref type setting

WIP #690 Added click fn-ality. still has bad error tooltip

WIP #690 Replaced baseName tooltip on ref set

WIP #690 Fixed code climate issues
2016-08-15 12:08:42 -05:00
Brian Broll 84e5377b8a Changed template settings to defaults. Fixes #691 (#693) 2016-08-15 12:08:36 -05:00
104 arquivos alterados com 4122 adições e 15682 exclusões
+2
Ver Arquivo
@@ -33,3 +33,5 @@ node_modules
tmp/
test-tmp/
blob-local-storage/
src/seeds/nn/hash.txt
src/seeds/pipeline/hash.txt
+13 -1
Ver Arquivo
@@ -7,7 +7,13 @@
**Notice**: DeepForge is still a work in progress and is also lacking significant documentation! That being said, any contributions and/or feedback is greatly appreciated (and feel free to always ask any questions on the gitter)!
# DeepForge
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks but we are planning on supporting additional deep learning classifiers such as RNNs and LSTMs. Additional features include real-time collaborative editing and version control.
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks, RNNs and LSTMs as well as the creation of custom layers. Additional features include:
- Graphical architecture editor
- Training/testing pipeline creation
- Distributed pipeline execution
- Real-time pipeline feedback
- Collaborative editing
- Automatic version control.
## Quick Start
Simply run the following command to install deepforge with its dependencies:
@@ -16,6 +22,12 @@ Simply run the following command to install deepforge with its dependencies:
curl -o- https://raw.githubusercontent.com/dfst/deepforge/master/install.sh | bash
```
Or, if you already have NodeJS (v6) installed, simply run
```
npm install -g deepforge
```
Next, start deepforge with `deepforge start`!
Finally, navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions, check out the [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
+6
Ver Arquivo
@@ -3,10 +3,16 @@
var gmeConfig = require('./config'),
webgme = require('webgme'),
path = require('path'),
rm_rf = require('rimraf'),
myServer;
webgme.addToRequireJsPaths(gmeConfig);
// Clear seed hash info
['nn', 'pipeline'].map(lib => path.join(__dirname, 'src', 'seeds', lib, 'hash.txt'))
.forEach(file => rm_rf.sync(file));
myServer = new webgme.standaloneServer(gmeConfig);
myServer.start(function (err) {
if (err) {
+2 -1
Ver Arquivo
@@ -9,7 +9,8 @@
"cache": {
"useBlob": true,
"dir": "~/.deepforge/worker/cache"
}
},
"dir": "~/.deepforge/worker"
},
"mongo": {
"dir": "~/.deepforge/data"
+142 -133
Ver Arquivo
@@ -4,12 +4,12 @@ var Command = require('commander').Command,
program = new Command(),
childProcess = require('child_process'),
rawSpawn = childProcess.spawn,
Q = require('q'),
execSync = childProcess.execSync,
path = require('path'),
fs = require('fs'),
version = require('../package.json').version,
exists = require('exists-file'),
forever = require('forever-monitor'),
DEFAULT_CONFIG = require('./config.json'),
merge = require('lodash.merge'),
config,
@@ -112,22 +112,12 @@ program
.version('v' + version)
.description('Command line interface for managing deepforge');
// start
var start = function(main, opts) {
var child = new forever.Monitor(main, opts);
child.on('exit', function () {
console.log('Exited after 3 failed restarts');
});
child.start();
};
var isLocalUri = function(protocol, uri) {
return uri.indexOf(protocol + '://localhost') === 0 ||
uri.indexOf(protocol + '://127.0.0.1') === 0;
};
var checkMongo = function(args) {
var checkMongo = function(args, notSilent) {
// check the webgme config
var gmeConfig = require('../config'),
mongoUri = gmeConfig.mongo.uri;
@@ -139,15 +129,26 @@ var checkMongo = function(args) {
console.log('MongoDB is already running!');
} catch (e) { // no pIds
console.log('Starting MongoDB...');
startMongo(args, true);
var match = mongoUri.match(/:([0-9]+)/),
port = '80';
if (match) {
port = match[1];
}
startMongo(args, port, !notSilent);
}
} else if (notSilent) {
console.log(`Cannot start remote mongo locally: ${mongoUri}`);
} else {
console.log(`Using remote mongo: ${mongoUri}`);
}
};
var startMongo = function(args, silent) {
var job = rawSpawn('mongod', ['--dbpath', p(config.mongo.dir)], {
cwd: process.env.HOME
});
var startMongo = function(args, port, silent) {
var opts = ['--dbpath', p(config.mongo.dir), '--port', port],
job = rawSpawn('mongod', opts, {cwd: process.env.HOME});
if (!silent) {
job.stdout.on('data',
data => process.stdout.write(data.toString()));
@@ -177,86 +178,95 @@ var startMongo = function(args, silent) {
}
});
};
var checkTorch = function() {
return new Promise(_checkTorch)
.catch(() => 'Torch installation failed');
var hasTorch = function() {
var result = childProcess.spawnSync('th', ['--help']);
return !result.error;
};
var _checkTorch = function(resolve, reject) {
var result = childProcess.spawnSync('th', ['--help']),
tgtDir = p(config.torch.dir),
gcl = `git clone https://github.com/torch/distro.git ${tgtDir} --recursive`;
var installTorchExtras = function() {
// Check if rnn is installed
var result = childProcess.spawnSync('luarocks', ['list', '--porcelain']),
pkgs = result.stdout.toString().split('\n')
.map(line => line.match(/^[a-zA-Z0-9]+/g))
.map(m => m && m[0]);
if (result.error) {
if (pkgs.indexOf('rnn') === -1) {
return spawn('luarocks', ['install', 'rnn']);
} else {
return Q();
}
};
var installTorch = function() {
var tgtDir = p(config.torch.dir),
args;
if (!hasTorch()) {
// Try to install torch
console.log(`Torch7 not found. Installing to ${tgtDir}...`);
args = `clone https://github.com/torch/distro.git ${tgtDir} --recursive`.split(' ');
spawnMany([gcl],
() => {
process.chdir(tgtDir);
spawnMany([
'bash install-deps',
'./install.sh',
'luarocks install rnn'
], () => {
storeConfig('torch.dir', tgtDir);
resolve(true);
}, reject);
},
reject
);
return spawn('git', args)
.then(code => {
if (code !== 0) {
if (code === 128) {
console.error(`${tgtDir} is not empty. ` +
'Please empty it or change the torch directory:\n' +
'\n deepforge config torch.dir NEW/TORCH/PATH\n');
}
throw `Torch install Failed with exit code ${code}`;
} else { // continue installation
process.chdir(tgtDir);
return spawn('bash', ['install-deps'])
.then(() => spawn('bash', ['install.sh'], true))
.then(() => {
storeConfig('torch.dir', tgtDir);
console.log('Installed torch. Please close and ' +
're-open your terminal to use DeepForge w/ ' +
'torch support!');
process.exit(0);
});
}
});
} else {
resolve(false);
return Q();
}
};
var spawnMany = function(cmds, succ, err) {
var rawCmd,
cmd,
args,
job;
if (cmds.length === 0) {
return succ();
}
rawCmd = cmds.shift();
args = rawCmd.split(' ');
cmd = args.shift();
job = rawSpawn(cmd, args);
job.stdout.on('data', data => process.stdout.write(data));
job.stderr.on('data', data => process.stderr.write(data));
job.on('close', code => {
if (code) {
console.log(`${rawCmd} failed w/ error code ${code}`);
err(code, rawCmd);
} else {
spawnMany(cmds, succ, err);
}
});
};
var spawn = function(cmd, args, opts) {
var promise,
var deferred = Q.defer(),
job,
spawnOpts = typeof opts === 'object' ? opts : null,
forwardStdin = opts === true,
isOpen = true,
err;
args = args || [];
promise = new Promise((resolve, reject) => {
var job = opts ? rawSpawn(cmd, args, opts) : rawSpawn(cmd, args);
job.stdout.on('data', data => process.stdout.write(data));
job.stderr.on('data', data => process.stderr.write(data));
job.on('close', code => {
if (err) {
reject(err);
} else {
resolve(code);
job = spawnOpts ? rawSpawn(cmd, args, spawnOpts) : rawSpawn(cmd, args);
job.stdout.on('data', data => process.stdout.write(data));
job.stderr.on('data', data => process.stderr.write(data));
job.on('close', code => {
isOpen = false;
if (err) {
deferred.reject(err, code);
} else {
deferred.resolve(code);
}
});
job.on('error', e => err = e);
if (forwardStdin) {
process.stdin.on('data', data => {
if (isOpen) {
job.stdin.write(data);
}
});
job.on('error', e => err = e);
});
}
return promise;
return deferred.promise;
};
program.command('start')
@@ -266,44 +276,45 @@ program.command('start')
.option('-w, --worker [url]', 'start a worker and connect to given url. Defaults to local deepforge')
.option('-m, --mongo', 'start MongoDB')
.action(args => {
var main = path.join(__dirname, 'start-local.js'),
opts;
opts = {
max: 3,
args: []
};
var main = path.join(__dirname, 'start-local.js');
if (args.port) {
opts.env = {
PORT: args.port
};
process.env.PORT = args.port;
}
if (args.server) {
checkMongo(args);
main = path.join(__dirname, '..', 'app.js');
start(main, opts);
spawn('node', [main]);
}
if (args.worker) {
checkTorch().then(() => {
main = path.join(__dirname, 'start-worker.js');
if (args.worker !== true) {
opts.args.push(args.worker);
}
start(main, opts);
});
if (hasTorch()) {
installTorchExtras().then(() => {
main = path.join(__dirname, 'start-worker.js');
if (args.worker !== true) {
spawn('node', [main, args.worker]);
} else {
spawn('node', [main]);
}
});
} else {
installTorch();
}
}
if (args.mongo) {
startMongo(args);
checkMongo(args, true);
}
if (!args.server && !args.worker && !args.mongo) {
// Starting everything
checkMongo(args);
checkTorch().then(() => start(main, opts));
if (hasTorch()) {
installTorchExtras().then(() => spawn('node', [main]));
} else {
installTorch();
}
}
});
@@ -348,34 +359,34 @@ program
if (args.torch || !args.server) {
// Update torch
checkTorch().then(justInstalled => {
if (!justInstalled) {
// Upgrade torch
console.log('Upgrading torch...');
console.log(`Checking for torch in ${config.torch.dir}`);
// Verify that torch is installed in the config's location
if (!exists.sync(path.join(config.torch.dir, 'update.sh'))) {
// config is incorrect!
console.log('Could not find torch installation. Please update the deepforge config with:');
console.log('');
console.log(' deepforge config torch.dir ~/path/to/torch/install');
console.log('');
return;
}
spawn('bash', ['./update.sh'], {cwd: p(config.torch.dir)})
.catch(err => console.log('Upgrade failed w/ error code: ' + err.code))
.then(() => {
console.log('About to update rnn package...');
// Update rnn
return spawn('luarocks', ['install', 'rnn']);
})
.then(() => {
console.log('Upgrade successful!');
})
.catch(code => console.log('Upgrade failed w/ error code: ' + code));
if (hasTorch()) {
// Upgrade torch
console.log('Upgrading torch...');
console.log(`Checking for torch in ${config.torch.dir}`);
// Verify that torch is installed in the config's location
if (!exists.sync(path.join(config.torch.dir, 'update.sh'))) {
// config is incorrect!
console.log('Could not find torch installation. Please update the deepforge config with:');
console.log('');
console.log(' deepforge config torch.dir ~/path/to/torch/install');
console.log('');
return;
}
});
spawn('bash', ['./update.sh'], {cwd: p(config.torch.dir)})
.catch(err => console.log('Upgrade failed w/ error code: ' + err.code))
.then(() => {
console.log('About to update rnn package...');
// Update rnn
return spawn('luarocks', ['install', 'rnn']);
})
.then(() => {
console.log('Upgrade successful!');
})
.catch(code => console.log('Upgrade failed w/ error code: ' + code));
} else {
installTorch();
}
}
});
@@ -400,11 +411,9 @@ program
}
if (!opts.torch || opts.clean) { // uninstall deepforge
spawnMany(
['npm uninstall -g deepforge'],
() => console.log('deepforge has been uninstalled!'),
() => console.log('uninstall failed')
);
spawn('npm', ['uninstall', '-g', 'deepforge'])
.then(() => console.log('deepforge has been uninstalled!'))
.catch(() => console.log('uninstall failed'));
}
});
@@ -440,8 +449,8 @@ program
module.exports = function(cmd) {
var cmds = cmd.split(/\s+/).filter(w => !!w);
cmds.unshift('node');
cmds.unshift('./bin/deepforge');
cmds.unshift('node');
program.parse(cmds);
};
+1
Ver Arquivo
@@ -1,5 +1,6 @@
{
"DEEPFORGE_BLOB_DIR": "blob.dir",
"DEEPFORGE_WORKER_CACHE": "worker.cache.dir",
"DEEPFORGE_WORKER_DIR": "worker.dir",
"DEEPFORGE_WORKER_USE_BLOB": "worker.cache.useBlob"
}
-1
Ver Arquivo
@@ -8,7 +8,6 @@ var spawn = require('child_process').spawn,
gmeConfig = require(__dirname + '/../config');
// Set the cache to the blob
console.log(gmeConfig);
if (gmeConfig.blob.type === 'FS') {
process.env.DEEPFORGE_WORKER_CACHE = path.resolve(gmeConfig.blob.fsDir + '/wg-content');
}
+17 -4
Ver Arquivo
@@ -8,8 +8,10 @@ var path = require('path'),
projectConfig = require(__dirname + '/../config'),
executorSrc = path.join(__dirname, '..', 'node_modules', 'webgme', 'src',
'server', 'middleware', 'executor', 'worker'),
workerPath = path.join(__dirname, '..', 'src', 'worker'),
workerConfigPath = path.join(workerPath, 'config_' + Date.now() + '.json'),
id = Date.now(),
workerRootPath = process.env.DEEPFORGE_WORKER_DIR || path.join(__dirname, '..', 'src', 'worker'),
workerPath = path.join(workerRootPath, `worker_${id}`),
workerConfigPath = path.join(workerPath, 'config.json'),
workerTmp = path.join(workerPath, 'tmp'),
address,
config = {};
@@ -24,9 +26,20 @@ var createDir = function(dir) {
}
return false;
};
createDir(workerRootPath);
createDir(workerPath);
createDir(workerTmp);
// Create sym link to the node_modules
var modules = path.join(workerRootPath, 'node_modules');
try {
fs.statSync(modules);
} catch (e) {
// Create dir
childProcess.spawnSync('ln', ['-s', `${__dirname}/../node_modules`, modules]);
return true;
}
// Check torch support
var result = childProcess.spawnSync('th', ['--help']);
if (result.error) {
@@ -37,8 +50,8 @@ if (result.error) {
}
var cleanUp = function() {
console.log('removing config ', workerConfigPath);
rm_rf.sync(workerConfigPath);
console.log('removing worker directory ', workerPath);
rm_rf.sync(workerPath);
};
var startExecutor = function() {
+24 -2
Ver Arquivo
@@ -12,10 +12,32 @@
"LayerColors": {}
},
"BreadcrumbHeader": {
"pathRule": "history"
"pathRule": "history",
"cachePrefix": "deepforge-header"
},
"FloatingActionButton": {
"hideOnEmpty": true
"hideOnEmpty": true,
"pluginUIConfigs": {
"GenerateArchitecture": {
"icon": "description",
"hotkey": "shift enter",
"priority": -1
},
"ExecutePipeline": {
"icon": "play_arrow",
"hotkey": "shift enter",
"color": "green",
"priority": 1
},
"ImportTorch": {
"icon": "import_export",
"priority": -1
},
"GenerateExecFile": {
"icon": "play_for_work",
"priority": -1
}
}
},
"GenericUIProjectNavigatorController": {
"rootMenuClass": "deepforge-logo",
-1
Ver Arquivo
@@ -19,7 +19,6 @@ config.plugin.allowBrowserExecution = true;
config.plugin.allowServerExecution = true;
config.executor.enable = true;
config.executor.clearOldDataAtStartUp = true;
config.visualization.extraCss.push('deepforge/styles/global.css');
-1
Ver Arquivo
@@ -7,7 +7,6 @@ var config = require('./config.default'),
// Turn up the worker polling rate
config.executor.workerRefreshInterval = 150;
config.executor.clearOldDataAtStartUp = true,
validateConfig(config);
module.exports = config;
+4 -2
Ver Arquivo
@@ -5,9 +5,11 @@
'use strict';
var config = require('./config.default');
var config = require('./config.default'),
path = require('path');
config.server.port = 9001;
config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme_tests';
config.blob.fsDir = path.join(__dirname, '..', 'test-tmp', 'blob');
module.exports = config;
module.exports = config;
+22 -20
Ver Arquivo
@@ -6,33 +6,35 @@
var config = require('webgme/config/config.default'),
validateConfig = require('webgme/config/validator');
// The paths can be loaded from the webgme-setup.json
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');
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/project');
config.seedProjects.basePaths.push('src/seeds/cifar10');
config.seedProjects.basePaths.push('src/seeds/xor');
config.plugin.basePaths.push(__dirname + '/../src/plugins');
config.plugin.basePaths.push(__dirname + '/../node_modules/webgme-simple-nodes/src/plugins');
config.visualization.layout.basePaths.push(__dirname + '/../node_modules/webgme-chflayout/src/layouts');
config.visualization.decoratorPaths.push(__dirname + '/../src/decorators');
config.visualization.decoratorPaths.push(__dirname + '/../node_modules/webgme-easydag/src/decorators');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/nn');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devTests');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devUtilTests');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/pipeline');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devPipelineTests');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/project');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/cifar10');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/xor');
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devProject');
config.visualization.panelPaths.push('node_modules/webgme-fab/src/visualizers/panels');
config.visualization.panelPaths.push('node_modules/webgme-breadcrumbheader/src/visualizers/panels');
config.visualization.panelPaths.push('node_modules/webgme-autoviz/src/visualizers/panels');
config.visualization.panelPaths.push('node_modules/webgme-easydag/src/visualizers/panels');
config.visualization.panelPaths.push('src/visualizers/panels');
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-fab/src/visualizers/panels');
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-breadcrumbheader/src/visualizers/panels');
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-autoviz/src/visualizers/panels');
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-easydag/src/visualizers/panels');
config.visualization.panelPaths.push(__dirname + '/../src/visualizers/panels');
config.rest.components['execution/logs'] = __dirname + '/../src/routers/JobLogsAPI/JobLogsAPI.js';
// Visualizer descriptors
config.visualization.visualizerDescriptors.push('./src/visualizers/Visualizers.json');
config.visualization.visualizerDescriptors.push(__dirname + '/../src/visualizers/Visualizers.json');
// Add requirejs paths
config.requirejsPaths = {
'EllipseDecorator': 'node_modules/webgme-easydag/src/decorators/EllipseDecorator',
+15 -40
Ver Arquivo
@@ -41,15 +41,9 @@ detect_profile() {
}
detect_profile
command -v node >/dev/null 2>&1 || {
# No node! Install nvm
echo >&2 "NodeJS is not found. Installing (using nvm)...";
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash;
source $DETECTED_PROFILE
. $NVM_DIR/nvm.sh
set_node_version() {
# Install nodejs v6.2.0
echo "Installing nodejs v6.2.0"
echo "Installing NodeJS v6.2.0"
nvm install v6.2.0
nvm alias default v6.2.0
@@ -58,40 +52,21 @@ command -v node >/dev/null 2>&1 || {
}
command -v node >/dev/null 2>&1 || {
# No mongod!
echo >&2 "MongoDB is not found. Installing...";
if [[ `uname` == "Darwin" ]]; then
brew install mongodb
elif [[ "$(uname)" == 'Linux' ]]; then
# No node! Install nvm
echo >&2 "NodeJS is not found. Installing (using nvm)...";
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash;
source $DETECTED_PROFILE
. $NVM_DIR/nvm.sh
if [[ -r /etc/os-release ]]; then
# this will get the required information without dirtying any env state
DIST_VERS="$( ( . /etc/os-release &>/dev/null
echo "$ID $VERSION_ID") )"
DISTRO="${DIST_VERS%% *}" # get our distro name
VERSION="${DIST_VERS##* }" # get our version number
elif [[ -r /etc/lsb-release ]]; then
DIST_VERS="$( ( . /etc/lsb-release &>/dev/null
echo "${DISTRIB_ID,,} $DISTRIB_RELEASE") )"
DISTRO="${DIST_VERS%% *}" # get our distro name
VERSION="${DIST_VERS##* }" # get our version number
else # well, I'm out of ideas for now
echo '==> Failed to determine distro and version.'
exit 1
fi
set_node_version
}
# Detect archlinux
if [[ "$DISTRO" = "arch" ]]; then
distribution="archlinux"
sudo pacman -S mongodb
# Detect Ubuntu
elif [[ "$DISTRO" = "ubuntu" ]]; then
export DEBIAN_FRONTEND=noninteractive
sudo apt-get install mongodb
else
NEEDS_MONGO=true
fi
fi
# Check node version supports arrow fns and string templates
node -e '() => console.log(`print "3": ${1+2}`)' >/dev/null 2>&1 || {
echo "Unsupported version of NodeJS."
echo ""
echo "Please update NodeJS to version 4.x.x or later (6.x.x recommended)"
exit 1
}
echo >&2 "Installing DeepForge...";
+7 -4
Ver Arquivo
@@ -8,23 +8,25 @@
"start-dev": "NODE_ENV=dev node app.js",
"local": "node ./bin/start-local.js",
"worker": "node ./bin/start-worker.js",
"test": "node ./node_modules/mocha/bin/mocha --recursive test",
"test": "mkdir ./test-tmp; node ./node_modules/mocha/bin/mocha --recursive test",
"test-cover": "node node_modules/istanbul/lib/cli.js --hook-run-in-context cover node_modules/mocha/bin/_mocha -- -R spec test/**/*",
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'",
"build-nn": "node ./utils/nn-parser.js"
},
"version": "0.13.0",
"version": "0.16.0",
"dependencies": {
"commander": "^2.9.0",
"dotenv": "^2.0.0",
"exists-file": "^2.1.0",
"forever-monitor": "^1.7.0",
"express": "^4.14.0",
"lodash.difference": "^4.1.2",
"lodash.merge": "^4.5.1",
"nodemon": "^1.9.2",
"q": "1.4.1",
"rimraf": "^2.4.0",
"webgme": "^2.0.0",
"webgme-autoviz": "dfst/webgme-autoviz",
"webgme-breadcrumbheader": "^2.1.0",
"webgme-breadcrumbheader": "^2.1.1",
"webgme-chflayout": "^2.0.0",
"webgme-easydag": "dfst/webgme-easydag",
"webgme-fab": "dfst/webgme-fab",
@@ -34,6 +36,7 @@
"chai": "^3.0.0",
"jszip": "^2.5.0",
"mocha": "^2.2.5",
"istanbul": "^0.4.5",
"mockery": "^1.7.0"
}
}
+17 -2
Ver Arquivo
@@ -5,12 +5,27 @@ define({
// DeepForge metadata creation in dist execution
START_CMD: 'deepforge-cmd',
IMAGE: 'IMG',
IMAGE: { // all prefixed w/ 'IMG' for simple upload detection
PREFIX: 'IMG',
BASIC: 'IMG-B',
CREATE: 'IMG-C',
UPDATE: 'IMG-U',
NAME: 'IMAGE-N' // No upload required
},
GRAPH_CREATE: 'GRAPH',
GRAPH_PLOT: 'PLOT',
GRAPH_CREATE_LINE: 'LINE',
// Code Generation Constants
CTOR_ARGS_ATTR: 'ctor_arg_order'
CTOR_ARGS_ATTR: 'ctor_arg_order',
// Operation types
OP: {
INPUT: 'Input',
OUTPUT: 'Output'
},
// Job stdout update
STDOUT_UPDATE: 'stdout_update'
});
+132
Ver Arquivo
@@ -0,0 +1,132 @@
/* globals define */
define([
'q',
'superagent'
], function(
Q,
superagent
) {
'use strict';
// Wrap the ability to read, update, and delete logs using the JobLogsAPI
var JobLogsClient = function(params) {
params = params || {};
this.logger = params.logger.fork('JobLogsClient');
// Get the server url
this.token = params.token;
this.origin = this._getServerUrl(params);
this.relativeUrl = '/execution/logs';
this.url = this.origin + this.relativeUrl;
this.logger.debug(`Setting url to ${this.url}`);
// Get the project, branch name
if (!(params.branchName && params.projectId)) {
throw Error('"branchName" and "projectId" required');
}
this.branch = params.branchName;
this.project = params.projectId;
this._modifiedJobs = [];
this.logger.debug(`Using <project>:<branch>: "${this.project}"/"${this.branch}"`);
this.logger.info('ctor finished');
};
JobLogsClient.prototype._getServerUrl = function(params) {
if (typeof window !== 'undefined') {
return window.location.origin;
}
// If not in browser, set using the params
var server = params.server || '127.0.0.1',
port = params.port || '80',
protocol = params.httpsecure ? 'https' : 'http'; // default is http
return params.origin || `${protocol}://${server}:${port}`;
};
// This method could be optimized - it could make a log of requests
JobLogsClient.prototype.fork = function(forkName) {
var jobIds = this._modifiedJobs,
deferred = Q.defer(),
url = [
this.url,
'migrate',
encodeURIComponent(this.project),
encodeURIComponent(this.branch),
encodeURIComponent(forkName)
].join('/'),
req = superagent.post(url);
this.logger.info(`migrating ${jobIds.length} jobs from ${this.branch} to ${forkName} in ${this.project}`);
if (this.token) {
req.set('Authorization', 'Bearer ' + this.token);
}
req.send({jobs: jobIds})
.end((err, res) => {
if (err || res.status > 399) {
return deferred.reject(err || res.status);
}
return deferred.resolve(res);
});
this.branch = forkName;
return deferred.promise;
};
JobLogsClient.prototype.getUrl = function(jobId) {
return [
this.url,
encodeURIComponent(this.project),
encodeURIComponent(this.branch),
encodeURIComponent(jobId)
].join('/');
};
JobLogsClient.prototype._logRequest = function(method, jobId, content) {
var deferred = Q.defer(),
req = superagent[method](this.getUrl(jobId));
this.logger.info(`sending ${method} request to ${this.getUrl(jobId)}`);
if (this.token) {
req.set('Authorization', 'Bearer ' + this.token);
}
if (content) {
req = req.send(content);
}
req.end((err, res) => {
if (err || res.status > 399) {
return deferred.reject(err || res.status);
}
return deferred.resolve(res);
});
return deferred.promise;
};
JobLogsClient.prototype.appendTo = function(jobId, text) {
this._modifiedJobs.push(jobId);
this.logger.info(`Appending logs to ${jobId}`);
return this._logRequest('patch', jobId, {patch: text});
};
JobLogsClient.prototype.getLog = function(jobId) {
this.logger.info(`Getting logs for ${jobId}`);
return this._logRequest('get', jobId)
.then(res => res.text);
};
JobLogsClient.prototype.deleteLog = function(jobId) {
this.logger.info(`Deleting logs for ${jobId}`);
return this._logRequest('delete', jobId);
};
return JobLogsClient;
});
+51 -22
Ver Arquivo
@@ -4,12 +4,14 @@ define([
'panel/FloatingActionButton/styles/Materialize',
'js/RegistryKeys',
'js/Panels/MetaEditor/MetaEditorConstants',
'js/Constants'
'js/Constants',
'q'
], function(
Materialize,
REGISTRY_KEYS,
META_CONSTANTS,
CONSTANTS
CONSTANTS,
Q
) {
var DeepForge = {},
placesTerritoryId,
@@ -92,6 +94,7 @@ define([
};
//////////////////// DeepForge places detection ////////////////////
DeepForge.places = {};
var TYPE_TO_CONTAINER = {
Architecture: 'MyArchitectures',
@@ -107,10 +110,29 @@ define([
PLACE_NAMES = Object.keys(TYPE_TO_CONTAINER).map(key => TYPE_TO_CONTAINER[key]);
// Add DeepForge directories
var placePromises = {},
setPlaceId = {},
firstProject = true;
var getPlace = function(name) {
return placePromises[name];
};
var initializePlaces = function() {
PLACE_NAMES.forEach(name => {
var deferred = Q.defer();
placePromises[name] = deferred.promise;
setPlaceId[name] = deferred.resolve;
});
};
var updateDeepForgeNamespace = function() {
var territory = {};
DeepForge.places = {};
if (!firstProject) {
initializePlaces();
}
firstProject = false;
// Create a territory
if (placesTerritoryId) {
@@ -137,13 +159,16 @@ define([
nodes.forEach(node =>
nodeIdsByName[node.getAttribute('name')] = node.getId());
PLACE_NAMES.forEach(name => DeepForge.places[name] = nodeIdsByName[name]);
PLACE_NAMES.forEach(name => setPlaceId[name](nodeIdsByName[name]));
// Remove the territory
client.removeUI(placesTerritoryId);
placesTerritoryId = null;
};
initializePlaces();
PLACE_NAMES.forEach(name => DeepForge.places[name] = getPlace.bind(null, name));
//////////////////// DeepForge creation actions ////////////////////
var instances = [
'Architecture',
@@ -156,8 +181,7 @@ define([
];
var createNew = function(type, metasheetName) {
var parentId,
placeName = TYPE_TO_CONTAINER[type],
var placeName = TYPE_TO_CONTAINER[type],
newId,
baseId,
msg = `Created new ${type + (metasheetName ? ' prototype' : '')}`;
@@ -167,19 +191,20 @@ define([
.getId();
// Look up the parent container
parentId = DeepForge.places[placeName];
DeepForge.places[placeName]().then(parentId => {
client.startTransaction(msg);
newId = createNamedNode(baseId, parentId, !!metasheetName);
client.startTransaction(msg);
newId = createNamedNode(baseId, parentId, !!metasheetName);
if (metasheetName) {
addToMetaSheet(newId, metasheetName);
}
if (metasheetName) {
addToMetaSheet(newId, metasheetName);
}
client.completeTransaction();
client.completeTransaction();
WebGMEGlobal.State.registerActiveObject(newId);
return newId;
WebGMEGlobal.State.registerActiveObject(newId);
return newId;
});
};
var createCustomLayer = function(typeName) {
@@ -200,16 +225,20 @@ define([
}
}
client.startTransaction(msg);
return DeepForge.places.MyLayers()
.then(id => {
newId = createNamedNode(baseId, DeepForge.places.MyLayers, true);
addToMetaSheet(newId, 'CustomLayers');
client.addMixin(newId, customLayerId);
client.setRegistry(newId, REGISTRY_KEYS.IS_ABSTRACT, false);
client.startTransaction(msg);
client.completeTransaction();
newId = createNamedNode(baseId, id, true);
addToMetaSheet(newId, 'CustomLayers');
client.addMixin(newId, customLayerId);
client.setRegistry(newId, REGISTRY_KEYS.IS_ABSTRACT, false);
WebGMEGlobal.State.registerActiveObject(newId);
client.completeTransaction();
WebGMEGlobal.State.registerActiveObject(newId);
});
};
// Creating Artifacts
+18 -21
Ver Arquivo
@@ -2,14 +2,16 @@
// This is an 'executor' containing the implementations of all local operations
// These are all primitives in DeepForge
define([
'deepforge/Constants'
], function(
CONSTANTS
) {
'use strict';
var LocalExecutor = function() {
};
// Should these be in lua?
LocalExecutor.prototype.ArtifactLoader = function(node) {
LocalExecutor.prototype[CONSTANTS.OP.INPUT] = function(node) {
// Get the hash from the output node
var hash;
return this.core.loadChildren(node)
@@ -18,13 +20,13 @@ define([
var output = cntrs
.find(cntr => {
var metaNode = this.core.getMetaType(cntr),
metaName = this.core.getAttribute(metaNode, 'name');
metaName = this.getAttribute(metaNode, 'name');
return metaName === 'Outputs';
});
return this.core.loadChildren(output);
})
.then(dataNodes => {
hash = this.core.getAttribute(dataNodes[0], 'data');
hash = this.getAttribute(dataNodes[0], 'data');
return this.getOutputs(node);
})
.then(outputTuples => {
@@ -46,7 +48,7 @@ define([
var hash,
typeId = this.core.getPointerPath(node, 'type'),
type,
artifactName = this.core.getAttribute(node, 'artifactName');
artifactName = this.getAttribute(node, 'artifactName');
return this.core.loadByPath(this.rootNode, typeId)
.then(_type => {
@@ -56,25 +58,20 @@ define([
.then(saveDir => this.core.loadChildren(saveDir))
.then(artifacts => {
return artifacts.find(artifact =>
this.core.getAttribute(artifact, 'name') === artifactName &&
this.getAttribute(artifact, 'name') === artifactName &&
this.isMetaTypeOf(artifact, type));
})
.then(matchingArtifact => {
hash = matchingArtifact && this.core.getAttribute(matchingArtifact, 'data');
hash = matchingArtifact && this.getAttribute(matchingArtifact, 'data');
// If no hash, just continue (the subsequent ops will receive 'nil')
if (!hash) {
return this.onOperationComplete(node);
} else {
return this.getOutputs(node)
.then(outputPairs => {
var outputs = outputPairs.map(pair => pair[2]),
paths;
paths = outputs.map(output => this.core.getPath(output));
var outputs = outputPairs.map(pair => pair[2]);
// 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));
outputs.forEach(output => this.setAttribute(output, 'data', hash));
this.onOperationComplete(node);
});
@@ -97,7 +94,7 @@ define([
if (containers.length > 1) {
saveDir = containers.find(c =>
this.core.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
this.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
) || containers[0];
}
@@ -105,7 +102,7 @@ define([
});
};
LocalExecutor.prototype.Save = function(node) {
LocalExecutor.prototype[CONSTANTS.OP.OUTPUT] = function(node) {
var parentNode,
currNameHashPairs;
@@ -119,8 +116,8 @@ define([
.then(artifacts => {
currNameHashPairs = artifacts
.map(node => [
this.core.getAttribute(node, 'name'),
this.core.getAttribute(node, 'data')
this.getAttribute(node, 'name'),
this.getAttribute(node, 'data')
]);
return this.getInputs(node);
})
@@ -140,9 +137,9 @@ define([
// Remove nodes that already exist
dataNodes = allDataNodes.filter(dataNode => {
var hash = this.core.getAttribute(dataNode, 'data'),
var hash = this.getAttribute(dataNode, 'data'),
name = this.core.getOwnAttribute(node, 'saveName') ||
this.core.getAttribute(dataNode, 'name');
this.getAttribute(dataNode, 'name');
return !(currNameHashPairs
.find(pair => pair[0] === name && pair[1] === hash));
@@ -154,10 +151,10 @@ define([
newName = this.core.getOwnAttribute(node, 'saveName');
if (newName) {
newNodes.forEach(node =>
this.core.setAttribute(node, 'name', newName)
this.setAttribute(node, 'name', newName)
);
}
var hashes = dataNodes.map(n => this.core.getAttribute(n, 'data'));
var hashes = dataNodes.map(n => this.getAttribute(n, 'data'));
this.logger.info(`saving hashes: ${hashes.map(h => `"${h}"`)}`);
} else if (allDataNodes.length === 0) {
this.logger.warn('No data nodes found!');
+13 -17
Ver Arquivo
@@ -1,22 +1,18 @@
/* latin-ext */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/7pSgz2MbVvTCvvm7vukSHxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/8XtYtNKEyyZh481XVWfVOltXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
li.deepforge-logo {
background-image: url(img/deepforge-logo.png);
background-repeat: no-repeat;
background-position: center;
width: 100px;
background-size: 95px;
}
.deepforge-logo .item-label {
font-family: 'Audiowide', cursive;
li.deepforge-logo span {
visibility: hidden;
}
i.gme-icon {
background-image: url(img/deepforge-icon.png);
background-size: 15.20px 18px;
}
.create-node text {
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 2.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.3 KiB

+60 -6
Ver Arquivo
@@ -1,7 +1,13 @@
/* globals define*/
define([
], function(
) {
(function(root, factory){
if(typeof define === 'function' && define.amd) {
define([], function(){
return (root.utils = factory());
});
} else if(typeof module === 'object' && module.exports) {
module.exports = (root.utils = factory());
}
}(this, function() {
var isBoolean = txt => {
return typeof txt === 'boolean' || (txt === 'false' || txt === 'true');
};
@@ -33,7 +39,55 @@ define([
return schema;
};
return {
getSetterSchema: getSetterSchema
var abbrWord = function(word) { // camelcase
word = word.substring(0, 1).toUpperCase() + word.substring(1);
return word.split(/[a-z]+/g).join('').toLowerCase();
};
});
var abbrPhrase = function(words) { // dashes, spaces, underscores, etc
return words.map(word => word[0]).join('');
};
var abbr = function(phrase) {
var words = phrase.split(/[^a-zA-Z0-9]+/g);
if (words.length === 1) {
return abbrWord(phrase);
} else {
return abbrPhrase(words);
}
};
// Resolving stdout
var resolveCarriageReturns = function(text) {
// resolve \r
var lines,
chars,
result,
i = 0;
text = text.replace(/\u0000/g, '');
lines = text.split('\n');
for (var l = lines.length-1; l >= 0; l--) {
i = 0;
chars = lines[l].split('');
result = [];
for (var c = 0; c < chars.length; c++) {
if (chars[c] === '\r') {
i = 0;
}
result[i] = chars[c];
i++;
}
lines[l] = result.join('');
}
return lines;
};
return {
getSetterSchema: getSetterSchema,
resolveCarriageReturns: resolveCarriageReturns,
abbr: abbr
};
}));
+191
Ver Arquivo
@@ -0,0 +1,191 @@
/* globals define, WebGMEGlobal */
// Mixin for executing jobs and pipelines
define([
'q',
'executor/ExecutorClient',
'panel/FloatingActionButton/styles/Materialize'
], function(
Q,
ExecutorClient,
Materialize
) {
var Execute = function(client, logger) {
this.client = this.client || client;
this.logger = this.logger || logger;
this._executor = new ExecutorClient({
logger: this.logger.fork('ExecutorClient'),
serverPort: WebGMEGlobal.gmeConfig.server.port,
httpsecure: window.location.protocol === 'https:'
});
};
Execute.prototype.executeJob = function(node) {
return this.runExecutionPlugin('ExecuteJob', {node: node});
};
Execute.prototype.executePipeline = function(node) {
return this.runExecutionPlugin('ExecutePipeline', {node: node});
};
Execute.prototype.runExecutionPlugin = function(pluginId, opts) {
var context = this.client.getCurrentPluginContext(pluginId),
node = opts.node || this.client.getNode(this._currentNodeId),
name = node.getAttribute('name'),
method;
// Set the activeNode
context.managerConfig.namespace = 'pipeline';
context.managerConfig.activeNode = node.getId();
method = opts.useSecondary ? 'runBrowserPlugin' : 'runServerPlugin';
if (method === 'runServerPlugin' &&
this.client.getBranchStatus() !== this.client.CONSTANTS.BRANCH_STATUS.SYNC) {
Materialize.toast('Cannot execute operations when client is out-of-sync', 2000);
return;
}
this.client[method](pluginId, context, (err, result) => {
var msg = err ? `${name} failed!` : `${name} executed successfully!`,
duration = err ? 4000 : 2000;
// Check if it was canceled - if so, show that type of message
if (result && result.messages.length) {
msg = result.messages[0].message;
duration = 4000;
}
Materialize.toast(msg, duration);
});
};
Execute.prototype.isRunning = function(node) {
var baseId,
base,
type;
node = node || this.client.getNode(this._currentNodeId);
baseId = node.getBaseId();
base = this.client.getNode(baseId);
type = base.getAttribute('name');
if (type === 'Execution') {
return node.getAttribute('status') === 'running';
} else if (type === 'Job') {
return this.isRunningJob(node);
}
return false;
};
Execute.prototype.isRunningJob = function(job) {
var status = job.getAttribute('status');
return (status === 'running' || status === 'pending') &&
job.getAttribute('secret') && job.getAttribute('jobId');
};
Execute.prototype.silentStopJob = function(job) {
var jobHash,
secret;
job = job || this.client.getNode(this._currentNodeId);
jobHash = job.getAttribute('jobId');
secret = job.getAttribute('secret');
if (!jobHash || !secret) {
this.logger.error('Cannot stop job. Missing jobHash or secret');
return;
}
return this._executor.cancelJob(jobHash, secret)
.then(() => this.logger.info(`${jobHash} has been cancelled!`))
.fail(err => this.logger.error(`Job cancel failed: ${err}`));
};
Execute.prototype.stopJob = function(job, silent) {
var jobId;
job = job || this.client.getNode(this._currentNodeId);
jobId = job.getId();
this.silentStopJob(job);
if (!silent) {
this.client.startTransaction(`Stopping "${name}" job`);
}
this.client.delAttributes(jobId, 'jobId');
this.client.delAttributes(jobId, 'secret');
this.client.setAttributes(jobId, 'status', 'canceled');
if (!silent) {
this.client.completeTransaction();
}
};
Execute.prototype.loadChildren = function(id) {
var deferred = Q.defer(),
execNode = this.client.getNode(id || this._currentNodeId),
jobIds = execNode.getChildrenIds(),
jobsLoaded = !jobIds.length || this.client.getNode(jobIds[0]);
// May need to load the jobs...
if (!jobsLoaded) {
// Create a territory and load the nodes
var territory = {},
ui;
territory[id] = {children: 1};
ui = this.client.addUI(this, () => {
this.client.removeUI(ui);
deferred.resolve();
});
this.client.updateTerritory(ui, territory);
} else {
deferred.resolve();
}
return deferred.promise;
};
Execute.prototype.stopExecution = function(id, inTransaction) {
var execNode = this.client.getNode(id || this._currentNodeId);
return this.loadChildren(id)
.then(() => this._stopExecution(execNode, inTransaction));
};
Execute.prototype.silentStopExecution = function(id) {
var execNode = this.client.getNode(id || this._currentNodeId);
// Stop the execution w/o setting any attributes
return this.loadChildren(id)
.then(() => this._silentStopExecution(execNode));
};
Execute.prototype._stopExecution = function(execNode, inTransaction) {
var msg = `Canceling ${execNode.getAttribute('name')} execution`;
if (!inTransaction) {
this.client.startTransaction(msg);
}
this._silentStopExecution(execNode);
this.client.setAttributes(execNode.getId(), 'status', 'canceled');
if (!inTransaction) {
this.client.completeTransaction();
}
};
Execute.prototype._silentStopExecution = function(execNode) {
var jobIds = execNode.getChildrenIds();
jobIds.map(id => this.client.getNode(id))
.filter(job => this.isRunning(job)) // get running jobs
.forEach(job => this.silentStopJob(job)); // stop them
};
return Execute;
});
+1 -1
Ver Arquivo
@@ -21,7 +21,7 @@ define([
RenameablePanel.OPTIONS = PanelBaseWithHeader.OPTIONS;
RenameablePanel.prototype.initializeRenameable = function () {
this.$panelHeaderTitle.on('dblclick', this.editTitle.bind(this));
this.$panelHeaderTitle.on('click', this.editTitle.bind(this));
};
RenameablePanel.prototype.currentNodeId = function () {
@@ -1,12 +1,8 @@
/*globals define, _*/
/*jshint browser: true, camelcase: false*/
/**
* @author brollb / https://github.com/brollb
*/
define([
'js/Constants',
'deepforge/Constants',
'decorators/DcOpDecorator/EasyDAG/DcOpDecorator.EasyDAGWidget',
'css!./ArtifactOpDecorator.EasyDAGWidget.css'
], function (
@@ -19,16 +15,17 @@ define([
var ArtifactOpDecorator,
DECORATOR_ID = 'ArtifactOpDecorator',
CAST_OPTS = {
ArtifactLoader: {
ptr: 'artifact',
metaTgt: false
},
ArtifactFinder: {
ptr: 'type',
metaTgt: true
}
};
CAST_OPTS[CONSTANTS.OP.INPUT] = {
ptr: 'artifact',
metaTgt: false
};
// ArtifactOp nodes need to be able to...
// - dynamically change their outputs (downcast)
ArtifactOpDecorator = function (options) {
@@ -74,7 +71,7 @@ define([
};
ArtifactOpDecorator.prototype.getDisplayName = function() {
var ptrName = this._node.baseName === 'ArtifactLoader' ? 'artifact' : 'type',
var ptrName = this._node.baseName === CONSTANTS.OP.INPUT ? 'artifact' : 'type',
id = this._node.pointers[ptrName],
name = this.nameFor[id] || this._node.name;
return name;
@@ -91,7 +88,7 @@ define([
ArtifactOpDecorator.prototype.updateTargetName = function(id, name) {
DecoratorBase.prototype.updateTargetName.apply(this, arguments);
// Update name
var ptrName = this._node.baseName === 'ArtifactLoader' ? 'artifact' : 'type';
var ptrName = this._node.baseName === CONSTANTS.OP.INPUT ? 'artifact' : 'type';
if (this._node.pointers[ptrName] === id) {
this._name = name;
this.onResize();
@@ -0,0 +1,17 @@
/*globals define*/
define([
'decorators/EllipseDecorator/EasyDAG/AttributeField'
], function(
BaseAttributeField
) {
var AttributeField = function() {
BaseAttributeField.apply(this, arguments);
};
AttributeField.prototype = Object.create(BaseAttributeField.prototype);
AttributeField.prototype.onClick = function() {
};
return AttributeField;
});
@@ -2,10 +2,16 @@
/*jshint browser: true, camelcase: false*/
define([
'deepforge/Constants',
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
'./PointerField.RO',
'./AttributeField.RO',
'css!./JobDecorator.EasyDAGWidget.css'
], function (
EllipseDecorator
CONSTANTS,
EllipseDecorator,
PointerField,
AttributeField
) {
'use strict';
@@ -42,18 +48,46 @@ define([
_.extend(JobDecorator.prototype, EllipseDecorator.prototype);
JobDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
JobDecorator.prototype.AttributeField = AttributeField;
JobDecorator.prototype.PointerField = PointerField;
JobDecorator.prototype.isInputOperation = function() {
return this._node.name === CONSTANTS.OP.INPUT;
};
JobDecorator.prototype.getDisplayName = function() {
if (this.isInputOperation()) {
var id = this._node.pointers.artifact;
// Try to look up the pointer name
return this.nameFor[id] || this._node.name;
}
return this._node.name;
};
JobDecorator.prototype.setAttributes = function() {
EllipseDecorator.prototype.setAttributes.call(this);
var attrs = this._node.attributes,
status = attrs.status && attrs.status.value;
status = attrs.status && attrs.status.value,
opAttrs = Object.keys(this._node.opAttributes);
// Update the color based on the 'status' attr
this.color = COLORS[status] || COLORS.fail;
// Set _attributes from opAttributes
for (var i = opAttrs.length; i--;) {
this._attributes[opAttrs[i]] = this._node.opAttributes[opAttrs[i]];
}
};
JobDecorator.prototype.updateTargetName = function() {
EllipseDecorator.prototype.updateTargetName.apply(this, arguments);
var name = this.getDisplayName();
if (name !== this.name) {
this.name = name;
this.onResize();
}
};
return JobDecorator;
@@ -0,0 +1,22 @@
/*globals define*/
define([
'decorators/EllipseDecorator/EasyDAG/PointerField'
], function(
BasePointerField
) {
var PointerField = function() {
BasePointerField.apply(this, arguments);
};
PointerField.prototype = Object.create(BasePointerField.prototype);
PointerField.prototype.onClick = function() {
};
// Remove the delete icon and adjust the text location
PointerField.prototype.hasIcon = function() {
return false;
};
return PointerField;
});
@@ -1,4 +1,4 @@
/*globals define, $,_*/
/*globals define, _*/
/*jshint browser: true, camelcase: false*/
/**
+185
Ver Arquivo
@@ -0,0 +1,185 @@
/*globals define*/
/*jshint node:true, browser:true*/
define([
'text!./metadata.json',
'module',
'path',
'fs',
'q',
'plugin/PluginBase'
], function (
pluginMetadata,
module,
path,
fs,
Q,
PluginBase
) {
'use strict';
pluginMetadata = JSON.parse(pluginMetadata);
var __dirname = path.dirname(module.uri),
SEEDS_DIR = path.join(__dirname, '..', '..', 'seeds');
/**
* Initializes a new instance of CheckLibraries.
* @class
* @augments {PluginBase}
* @classdesc This class represents the plugin CheckLibraries.
* @constructor
*/
var CheckLibraries = function () {
// Call base class' constructor.
PluginBase.call(this);
this.pluginMetadata = pluginMetadata;
this.libraries = {};
};
/**
* 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}
*/
CheckLibraries.metadata = pluginMetadata;
// Prototypical inheritance from PluginBase.
CheckLibraries.prototype = Object.create(PluginBase.prototype);
CheckLibraries.prototype.constructor = CheckLibraries;
/**
* 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
*/
CheckLibraries.prototype.main = function (callback) {
var tuples;
return this.getAllLibraries()
.then(libs => {
tuples = libs.map(lib => { // map to [name, version, dir]
var version,
hash,
data,
versionPath = this.getSeedVersionPath(lib);
try {
this.logger.info(`Checking for version info at ${versionPath}`);
version = fs.readFileSync(versionPath, 'utf8');
this.logger.debug(`${lib} version is ${version}`);
data = fs.readFileSync(this.getSeedHashPath(lib), 'utf8').split(' ');
if (data[1] === version) {
hash = data[0];
this.logger.debug(`${lib} hash is ${hash}`);
}
} catch (e) {
if (!version) {
this.logger.warn(`Could not find library version for ${lib}`);
} else {
this.logger.warn(`Could not find library hash for ${lib}`);
}
}
return [lib, version, hash];
})
.filter(tuple => {
var projVersion = this.getLoadedVersion(tuple[0]),
latest = tuple[1].replace(/\s+/g, '');
this.logger.info(`${tuple[0]} version info:\n${projVersion} ` +
`(project)\n${latest} (latest)`);
return latest !== projVersion;
});
return Q.all(tuples.map(tuple => this.uploadSeed.apply(this, tuple)));
})
.then(hashes => {
var name;
for (var i = hashes.length; i--;) {
name = tuples[i][0];
this.createMessage(this.libraries[name], `${name} ${hashes[i]}`);
}
this.logger.info(`Found ${hashes.length} out of date libraries`);
this.result.setSuccess(true);
callback(null, this.result);
})
.fail(err => {
this.logger.error(`Could not check the libraries: ${err}`);
callback(err, this.result);
});
};
CheckLibraries.prototype.getSeedDir = function (name) {
return path.join(SEEDS_DIR, name);
};
CheckLibraries.prototype.getSeedDataPath = function (name) {
return path.join(this.getSeedDir(name), name + '.webgmex');
};
CheckLibraries.prototype.getSeedHashPath = function (name) {
return path.join(this.getSeedDir(name), 'hash.txt');
};
CheckLibraries.prototype.getSeedVersionPath = function (name) {
return path.join(this.getSeedDir(name), 'version.txt');
};
CheckLibraries.prototype.uploadSeed = function (name, version, hash) {
if (!hash) { // Upload the seed
// Get the data
return Q.nfcall(fs.readFile, this.getSeedDataPath(name))
.then(data => {
this.logger.info(`Uploading new version of ${name} (${version})`);
return this.blobClient.putFile(`${name}.webgmex`, data);
})
.then(newHash => { // Store the new hash
this.logger.info(`Upload of ${name} finished!`);
hash = newHash;
return Q.nfcall(
fs.writeFile,
this.getSeedHashPath(name),
`${hash} ${version}`
);
}).then(() => hash);
}
return hash;
};
CheckLibraries.prototype.getAllLibraries = function () {
var name,
names = [];
return this.core.loadChildren(this.rootNode)
.then(children => {
for (var i = children.length; i--;) {
if (this.core.isLibraryRoot(children[i])) {
name = this.core.getAttribute(children[i], 'name');
this.libraries[name] = children[i];
names.push(name);
}
}
if (names.length) {
this.logger.debug(`Found libraries: ${names.join(', ')}`);
} else {
this.logger.debug('Found no libraries!');
}
return names;
});
};
CheckLibraries.prototype.getLoadedVersion = function (libName) {
var node = this.libraries[libName],
version = this.core.getAttribute(node, 'version'); // using library root hash
return version;
};
return CheckLibraries;
});
+14
Ver Arquivo
@@ -0,0 +1,14 @@
{
"id": "CheckLibraries",
"name": "CheckLibraries",
"version": "0.1.0",
"description": "",
"icon": {
"class": "glyphicon glyphicon-cog",
"src": ""
},
"disableServerSideExecution": false,
"disableBrowserSideExecution": true,
"writeAccessRequired": false,
"configStructure": []
}
+6 -10
Ver Arquivo
@@ -88,11 +88,9 @@ define([
// 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,
execName,
copies,
opTuples, // [[op, index], [op, index], ...]
dataMapping = {};
@@ -107,17 +105,19 @@ define([
base: this.META.Execution,
parent: execDir
});
this.logger.debug(`New execution created w/ id: ${this.core.getPath(tgtNode)}`);
// Get a unique name
this.logger.debug(`About to get a unique name starting w/ ${basename}`);
return this.getUniqueExecName(basename);
})
.then(execName => {
.then(_execName => {
var isSnapshot = !this.getCurrentConfig().debug,
originName = this.core.getAttribute(this.activeNode, 'name'),
oId = this.core.getPath(this.activeNode),
tgtId = this.core.getPath(tgtNode);
execName = _execName;
this.logger.debug(`Configuring execution attributes (${execName})`);
// Set all the metadata for the new execution
@@ -131,15 +131,9 @@ define([
this.core.addMember(this.activeNode, 'executions', tgtNode);
this.logger.debug(`Creating tag "${execName}"`);
return this.project.createTag(
execName,
this.currentHash
);
})
.then(() => this.core.loadChildren(node))
.then(children => {
var execName = this.core.getAttribute(tgtNode, 'name');
if (!children.length) {
this.logger.warn('No children in pipeline. Will proceed anyway');
}
@@ -170,6 +164,7 @@ define([
this.logger.debug('Finished! Saving...');
return this.save(`Created execution from ${name}`);
})
.then(() => this.project.createTag(execName, this.currentHash))
.then(() => tgtNode); // return tgtNode
};
@@ -192,6 +187,7 @@ define([
})
.then(execDir => {
var cIds = this.core.getChildrenPaths(execDir);
this.logger.debug(`Current executions are ${cIds.join(', ')}`);
return Q.all(cIds.map(id => this.core.loadByPath(this.rootNode, id)));
})
.then(execs => {
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+35 -3
Ver Arquivo
@@ -1,6 +1,13 @@
-- Instantiate the deepforge object
deepforge = {}
function deepforge.initialize()
require 'nn'
require 'rnn'
require './classes/init'
require './custom-layers'
end
function deepforge.id()
if __deepforge_id == nil then
__deepforge_id = 0
@@ -16,7 +23,7 @@ function deepforge._cmd(...)
for i=1,n do
cmd = cmd .. ' ' .. tostring(arg[i])
end
print(cmd)
print(cmd .. ' ') -- guarantee ends w/ space
end
-- Graph support
@@ -46,7 +53,7 @@ function Graph:line(name, opts)
end
-- Image support
function deepforge.image(name, tensor)
local function saveImage(name, tensor)
require 'image'
require 'paths'
@@ -59,7 +66,32 @@ function deepforge.image(name, tensor)
end
image.save(path, tensor)
deepforge._cmd("<%= IMAGE %>", name)
end
function deepforge.image(name, tensor)
saveImage(name, tensor)
deepforge._cmd("<%= IMAGE.BASIC %>", deepforge.id(), name)
end
Image = torch.class('deepforge.Image')
function Image:__init(name, tensor)
self.id = deepforge.id()
self.name = name
if tensor ~= nil then
saveImage(name, tensor)
deepforge._cmd('<%= IMAGE.CREATE %>', self.id, self.name)
end
end
function Image:update(tensor)
saveImage(self.name, tensor)
deepforge._cmd('<%= IMAGE.UPDATE %>', self.id, self.name)
end
function Image:title(name)
self.name = name
deepforge._cmd('<%= IMAGE.NAME %>', self.id, self.name)
end
return deepforge
+5 -8
Ver Arquivo
@@ -1,15 +1,12 @@
-- load custom layers
require './custom-layers'
-- load custom class definitions
require './classes'
-- load custom layers and classes
deepforge.initialize()
-- input data<% inputs.forEach(function(pair) { var input = pair[0], isNil = pair[1];%>
<%= isNil ? 'local ' : ''%><%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
local <%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
-- load references<% pointers.forEach(function(pair) { var pointer = pair[0], isNil = pair[1];%>
<%= isNil ? 'local ' : ''%><%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
attributes = require './attributes'
local <%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
local attributes = require './attributes'
-- main operation code for <%= name %>
<%= code %>
+2 -2
Ver Arquivo
@@ -12,7 +12,7 @@ var spawn = require('child_process').spawn,
// Get the BlobClient...
var COMMAND_PREFIX = '<%= START_CMD %>',
IMAGE = '<%= IMAGE %>',
IMAGE = '<%= IMAGE.PREFIX %>',
requirejs = require('webgme').requirejs,
remainingImageCount = 0,
exitCode = null;
@@ -80,7 +80,7 @@ requirejs([
var uploadImage = function(line) {
var args = line.split(/\s+/),
name = args.slice(2).join(' ').replace(/\s+$/, ''),
name = args.slice(3).join(' ').replace(/\s+$/, ''),
filename = 'metadata/' + name + '.png';
// Upload the image from metadata/
+103 -25
Ver Arquivo
@@ -4,6 +4,7 @@
define([
'plugin/CreateExecution/CreateExecution/CreateExecution',
'plugin/ExecuteJob/ExecuteJob/ExecuteJob',
'deepforge/JobLogsClient',
'common/storage/constants',
'common/core/constants',
'q',
@@ -12,6 +13,7 @@ define([
], function (
CreateExecution,
ExecuteJob,
JobLogsClient,
STORAGE_CONSTANTS,
CONSTANTS,
Q,
@@ -34,6 +36,11 @@ define([
this.pluginMetadata = pluginMetadata;
this._currentSave = Q();
this.changes = {};
this.currentChanges = {}; // read-only changes being applied
this.creations = {};
this.deletions = [];
this.createIdToMetadataId = {};
this.initRun();
};
@@ -94,17 +101,14 @@ define([
* @param {function(string, plugin.PluginResult)} callback - the result callback
*/
ExecutePipeline.prototype.main = function (callback) {
// 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;
this.initRun();
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.logger.debug(`Finished creating execution "${this.core.getAttribute(execNode, 'name')}"`);
this.logger.debug(`Finished creating execution "${this.getAttribute(execNode, 'name')}"`);
this.activeNode = execNode;
});
} else if (this.core.isTypeOf(this.activeNode, this.META.Execution)) {
@@ -114,6 +118,13 @@ define([
return callback('Current node is not a Pipeline or Execution!', this.result);
}
// Get the gmeConfig...
this.logManager = new JobLogsClient({
logger: this.logger,
port: this.gmeConfig.server.port,
branchName: this.branchName,
projectId: this.projectId
});
this._callback = callback;
this.currentForkName = null;
@@ -123,7 +134,7 @@ define([
var children = subtree
.filter(n => this.core.getParent(n) === this.activeNode);
this.pipelineName = this.core.getAttribute(this.activeNode, 'name');
this.pipelineName = this.getAttribute(this.activeNode, 'name');
this.logger.debug(`Loaded subtree of ${this.pipelineName}. About to build cache`);
this.buildCache(subtree);
this.logger.debug('Parsing execution for job inter-dependencies');
@@ -142,19 +153,46 @@ define([
// before continuing
this._currentSave = this._currentSave
.then(() => this.updateForkName(this.pipelineName))
.then(() => this.applyModelChanges())
.then(() => CreateExecution.prototype.save.call(this, msg))
.then(result => {
var msg;
if (result.status === STORAGE_CONSTANTS.FORKED) {
this.currentForkName = result.forkName;
this.logManager.fork(result.forkName);
msg = `"${this.pipelineName}" execution has forked to "${result.forkName}"`;
this.sendNotification(msg);
} else if (result.status === STORAGE_CONSTANTS.MERGED) {
this.logger.debug('Merged changes. About to update plugin nodes');
return this.updateNodes();
}
});
return this._currentSave;
};
ExecutePipeline.prototype.updateNodes = function (hash) {
var result = ExecuteJob.prototype.updateNodes.call(this, hash);
return result.then(() => this.updateCache());
};
ExecutePipeline.prototype.updateCache = function () {
var nodeIds = Object.keys(this.nodes),
nodes = nodeIds.map(id => this.core.loadByPath(this.rootNode, id));
this.logger.debug(`updating node cache (${nodeIds.length} nodes)`);
return Q.all(nodes).then(nodes => {
for (var i = nodeIds.length; i--;) {
this.nodes[nodeIds[i]] = nodes[i];
}
});
};
ExecutePipeline.prototype.isExecutionCanceled = function () {
return this.getAttribute(this.activeNode, 'status') === 'canceled';
};
ExecutePipeline.prototype.isInputData = function (node) {
var prnt = this.core.getParent(node);
return this.core.isTypeOf(prnt, this.META.Inputs);
@@ -174,13 +212,15 @@ define([
nodes.filter(node => this.core.isTypeOf(node, this.META.Job))
.forEach(node => {
this.recordOldMetadata(node);
this.core.setAttribute(node, 'status', 'pending');
this.setAttribute(node, 'status', 'pending');
});
// Set the status of the execution to 'running'
this.core.setAttribute(this.activeNode, 'status', 'running');
this.setAttribute(this.activeNode, 'status', 'running');
this.logger.info('Setting all jobs status to "pending"');
this.logger.debug(`Making a commit from ${this.currentHash}`);
this.setAttribute(this.activeNode, 'startTime', Date.now());
this.core.delAttribute(this.activeNode, 'endTime');
return this.save(`Initializing ${this.pipelineName} for execution`);
};
@@ -271,24 +311,24 @@ define([
ExecutePipeline.prototype.onOperationFail = function(node, err) {
var job = this.core.getParent(node),
id = this.core.getPath(node),
name = this.core.getAttribute(node, 'name');
name = this.getAttribute(node, 'name');
this.logger.debug(`Operation ${name} (${id}) failed: ${err}`);
this.core.setAttribute(job, 'status', 'fail');
this.setAttribute(job, 'status', 'fail');
this.clearOldMetadata(job);
this.onPipelineComplete(err);
};
ExecutePipeline.prototype.onOperationCanceled = function(op) {
var job = this.core.getParent(op);
this.core.setAttribute(job, 'status', 'canceled');
this.setAttribute(job, 'status', 'canceled');
this.runningJobs--;
this.logger.debug(`${this.core.getAttribute(job, 'name')} has been canceled`);
this.logger.debug(`${this.getAttribute(job, 'name')} has been canceled`);
this.onPipelineComplete();
};
ExecutePipeline.prototype.onPipelineComplete = function(err) {
var name = this.core.getAttribute(this.activeNode, 'name'),
var name = this.getAttribute(this.activeNode, 'name'),
msg = `"${this.pipelineName}" `;
if (err) {
@@ -318,18 +358,56 @@ define([
msg += 'finished!';
}
this.logger.debug(`Pipeline "${name}" complete!`);
this.core.setAttribute(this.activeNode, 'status',
(this.pipelineError ? 'failed' : (this.canceled ? 'canceled' : 'success')));
this.isDeleted().then(isDeleted => {
if (!isDeleted) {
this._finished = true;
this.resultMsg(msg);
this.save('Pipeline execution finished')
.then(() => {
this.logger.debug(`Pipeline "${name}" complete!`);
this.setAttribute(this.activeNode, 'endTime', Date.now());
this.setAttribute(this.activeNode, 'status',
(this.pipelineError ? 'failed' :
(this.canceled ? 'canceled' : 'success')
)
);
this._finished = true;
this.resultMsg(msg);
this.save('Pipeline execution finished')
.then(() => {
this.result.setSuccess(!this.pipelineError);
this._callback(this.pipelineError || null, this.result);
})
.fail(e => this.logger.error(e));
} else { // deleted!
this.logger.debug('Execution has been deleted!');
this.result.setSuccess(!this.pipelineError);
this._callback(this.pipelineError || null, this.result);
}
});
};
ExecutePipeline.prototype.isDeleted = function () {
var activeId = this.core.getPath(this.activeNode);
// Check if the current execution has been deleted
return this.project.getBranchHash(this.branchName)
.then(hash => this.updateNodes(hash))
.then(() => this.core.loadByPath(this.rootNode, activeId))
.then(node => {
var deleted = node === null,
msg = `Verified that execution is ${deleted ? '' : 'not '}deleted`;
this.logger.debug(msg);
return deleted;
})
.fail(e => this.logger.error(e));
.fail(err => this.logger.error(err));
};
ExecutePipeline.prototype.onPipelineDeleted = function () {
var msg = `${this.pipelineName} has been deleted`;
this.resultMsg(msg);
this.result.setSuccess(true);
this._callback(null, this.result);
};
ExecutePipeline.prototype.executeReadyOperations = function () {
@@ -362,7 +440,7 @@ define([
};
ExecutePipeline.prototype.onOperationComplete = function (opNode) {
var name = this.core.getAttribute(opNode, 'name'),
var name = this.getAttribute(opNode, 'name'),
nextPortIds = this.getOperationOutputIds(opNode),
jNode = this.core.getParent(opNode),
resultPorts,
@@ -372,7 +450,7 @@ define([
// Set the operation to 'success'!
this.clearOldMetadata(jNode);
this.runningJobs--;
this.core.setAttribute(jNode, 'status', 'success');
this.setAttribute(jNode, 'status', 'success');
this.logger.info(`Setting ${jobId} status to "success"`);
this.logger.info(`There are now ${this.runningJobs} running jobs`);
this.logger.debug(`Making a commit from ${this.currentHash}`);
@@ -391,11 +469,11 @@ define([
.forEach(pair => { // [ resultPort, nextPort ]
var result = pair[0],
next = pair[1],
hash = this.core.getAttribute(result, 'data');
hash = this.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);
this.setAttribute(next, 'data', hash);
this.logger.info(`Setting ${jobId} data to ${hash}`);
});
@@ -5,12 +5,14 @@ define([
'SimpleNodes/SimpleNodes',
'SimpleNodes/Constants',
'deepforge/layer-args',
'deepforge/utils',
'underscore',
'text!./metadata.json'
], function (
PluginBase,
Constants,
createLayerDict,
utils,
_,
metadata
) {
@@ -36,11 +38,15 @@ define([
GenerateArchitecture.prototype = Object.create(PluginBase.prototype);
GenerateArchitecture.prototype.constructor = GenerateArchitecture;
GenerateArchitecture.prototype.getTemplateSettings = function () {
return null;
};
GenerateArchitecture.prototype.main = function () {
this.addCustomLayersToMeta();
this.LayerDict = createLayerDict(this.core, this.META);
this.uniqueId = 2;
this.varnames = {};
this.varnames = {net: true};
return PluginBase.prototype.main.apply(this, arguments);
};
@@ -208,18 +214,13 @@ define([
};
};
GenerateArchitecture.abbr = function (word) {
word = word.substring(0, 1).toUpperCase() + word.substring(1);
return word.split(/[a-z]+/g).join('').toLowerCase();
};
GenerateArchitecture.prototype.getValue = function (arg, layer) {
var content = layer[arg];
if (typeof content === 'object') { // layer as arg
if (content[Constants.CHILDREN].length) {
// Generate the code for the children of layer[arg]
var name = this.getVarName(GenerateArchitecture.abbr(arg)),
var name = this.getVarName(utils.abbr(arg)),
layers;
this.logger.debug(`Adding layer arg for ${arg} (${layer.name})`);
@@ -246,17 +247,27 @@ define([
base = layer[Constants.BASE],
desc,
fn,
layerCode;
layerCode,
args,
i;
this.logger.debug(`Creating arg string for ${layer.name}`);
layerCode = '(' + this.LayerDict[layer.name].args
.map(arg => this.getValue(arg.name, layer))
.filter(GenerateArchitecture.isSet)
args = this.LayerDict[layer.name].args
.map(arg => this.getValue(arg.name, layer));
for (i = args.length; i--;) {
if (GenerateArchitecture.isSet(args[i])) {
break;
}
args.pop();
}
layerCode = '(' + args.map(arg => GenerateArchitecture.isSet(arg) ? arg : 'nil')
.join(', ') + ')';
// Add any setters
// For each setter, check if it has been changed (and needs to be set)
for (var i = setterNames.length; i--;) {
for (i = setterNames.length; i--;) {
desc = setters[setterNames[i]];
if (desc.setterType === 'const') {
// if the value is not the default, add the given fn
+18
Ver Arquivo
@@ -49,6 +49,8 @@ define([
return callback('Torch code not provided.', this.result);
}
this.addCustomLayersToMeta();
this.blobClient.getMetadata(srcHash)
.then(mdata => { // Create the new model
// If the current node is an architecture, assume we are just extending it
@@ -90,6 +92,22 @@ define([
);
};
ImportTorch.prototype.addCustomLayersToMeta = function () {
// Add custom layers to the metamodel
var metanodes = this.core.getAllMetaNodes(this.rootNode),
name;
Object.keys(metanodes).map(id => metanodes[id])
.filter(node => this.core.isTypeOf(node, this.META.Layer))
.forEach(layer => {
name = this.core.getAttribute(layer, 'name');
if (!this.META[name]) {
this.logger.debug(`Adding ${name} to the meta`);
this.META[name] = layer;
}
});
};
// Create the 'nn' shim and add it to the global context
ImportTorch.prototype.loadNNMock = function () {
// This needs a refactor...
@@ -0,0 +1,139 @@
/*globals define*/
/*jshint node:true, browser:true*/
define([
'text!./metadata.json',
'child_process',
'path',
'q',
'fs',
'module',
'plugin/PluginBase'
], function (
pluginMetadata,
childProcess,
path,
Q,
fs,
module,
PluginBase
) {
'use strict';
pluginMetadata = JSON.parse(pluginMetadata);
var SEEDS_DIR = path.join(path.dirname(module.uri), '..', '..', 'seeds');
/**
* Initializes a new instance of UpdateLibrarySeed.
* @class
* @augments {PluginBase}
* @classdesc This class represents the plugin UpdateLibrarySeed.
* @constructor
*/
var UpdateLibrarySeed = 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}
*/
UpdateLibrarySeed.metadata = pluginMetadata;
// Prototypical inheritance from PluginBase.
UpdateLibrarySeed.prototype = Object.create(PluginBase.prototype);
UpdateLibrarySeed.prototype.constructor = UpdateLibrarySeed;
/**
* 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
*/
UpdateLibrarySeed.prototype.main = function (callback) {
// get the root hash
var name = this.projectName,
version;
// get the name and validate
return this.getLibraryVersion()
.then(vers => {
version = vers;
return this.checkForLibName(name);
})
.then(valid => {
if (!valid) {
var err = `Invalid library name "${name}"`;
this.logger.error(err);
return callback(err, this.result);
}
return this.updateSeed(name);
})
.then(() => this.recordVersion(name, version))
.then(() => {
this.logger.info(`Finished updating library seed for ${name}`);
this.result.setSuccess(true);
callback(null, this.result);
})
.fail(err => callback(err, this.result));
};
UpdateLibrarySeed.prototype.getLibraryVersion = function () {
var version,
config = this.getCurrentConfig(),
vnames = ['major', 'minor', 'patch'],
bumpIndex,
newVersion;
version = (this.core.getAttribute(this.rootNode, 'version') || '0.0.0')
.split('.').map(num => parseInt(num));
bumpIndex = vnames.indexOf(config.releaseType);
version[bumpIndex]++;
newVersion = version.join('.');
this.core.setAttribute(this.rootNode, 'version', newVersion);
return this.save(`Bumped version to ${newVersion}`).then(() => newVersion);
};
UpdateLibrarySeed.prototype.checkForLibName = function (name) {
// check for the library name from the fs
return Q.nfcall(fs.readdir, SEEDS_DIR).then(seeds => seeds.indexOf(name) !== -1);
};
UpdateLibrarySeed.prototype.updateSeed = function (seedName) {
var deferred = Q.defer(),
err,
job = childProcess.spawn('webgme', ['new', 'seed', seedName], {
cwd: path.dirname(module.uri)
});
this.logger.info(`Updating ${seedName} seed`);
job.on('error', _err => {
err = _err;
});
job.on('exit', code => {
if (!code) {
deferred.resolve();
} else {
deferred.reject(err || code);
}
});
return deferred.promise;
};
UpdateLibrarySeed.prototype.recordVersion = function (seed, version) {
var versionPath = path.join(SEEDS_DIR, seed, 'version.txt');
this.logger.info(`Updating ${seed} version (${version})`);
return Q.nfcall(fs.writeFile, versionPath, version);
};
return UpdateLibrarySeed;
});
+28
Ver Arquivo
@@ -0,0 +1,28 @@
{
"id": "UpdateLibrarySeed",
"name": "UpdateLibrarySeed",
"version": "0.1.0",
"description": "",
"icon": {
"class": "glyphicon glyphicon-cog",
"src": ""
},
"disableServerSideExecution": false,
"disableBrowserSideExecution": true,
"writeAccessRequired": false,
"configStructure": [
{
"name": "releaseType",
"displayName": "Release Type",
"description": "Specify major, minor or patch release",
"value": "minor",
"valueItems": [
"major",
"minor",
"patch"
],
"valueType": "string",
"readOnly": false
}
]
}
+149
Ver Arquivo
@@ -0,0 +1,149 @@
var path = require('path'),
Q = require('q'),
fs = require('fs'),
exists = require('exists-file'),
utils = require('../../common/utils'),
NO_LOG_FOUND = '';
var JobLogManager = function(logger, config) {
this.rootDir = path.join(config.blob.fsDir, 'log-storage');
this.logger = logger.fork('JobLogManager');
this._onCopyFinished = {};
};
JobLogManager.prototype._getFilePath = function(jInfo) {
this.logger.debug(`getting file path for ${jInfo.job} in ${jInfo.project} on ${jInfo.branch}`);
var jobId = jInfo.job.replace(/\//g, '_'),
filename = `${jobId}.txt`;
return path.join(this.rootDir, jInfo.project, jInfo.branch, filename);
};
JobLogManager.prototype.exists = function(jobInfo) {
var filename = this._getFilePath(jobInfo);
return Q.nfcall(exists, filename);
};
JobLogManager.prototype.mkdirIfNeeded = function(dir) {
return Q.nfcall(exists, dir).then(exist => {
if (!exist) {
this.logger.debug('making dir:', dir);
return Q.nfcall(fs.mkdir, dir)
.catch(() => this.logger.debug(`dir already created: ${dir}`));
}
});
};
JobLogManager.prototype._copyFile = function(src, dst) {
return Q.nfcall(exists, src).then(exists => {
if (!exists) {
this.logger.warn(`Cannot copy file from ${src}. File doesn't exist!`);
return;
}
return this.mkdirIfNeeded(path.dirname(dst)).then(() => {
var deferred = Q.defer(),
stream = fs.createReadStream(src).pipe(fs.createWriteStream(dst));
stream.on('error', deferred.reject);
stream.on('finish', deferred.resolve);
return deferred.promise;
});
});
};
// Copy one branch info to the next
// Could optimize this to symlink until data appended...
JobLogManager.prototype.migrate = function(migrationInfo, jobIds) {
// Recursively copy the srcBranch dir to the dstBranch dir
// Should probably use streams...
// Need to block appends to the given files so they are not written
// to until they have finished copying...
// TODO
var jobs,
src,
dst,
i;
for (i = jobIds.length; i--;) {
this._onCopyFinished[jobIds[i]] = [];
}
// Copy the job files and evaluate each of the finish functions
this.logger.info('migrating from ' + migrationInfo.srcBranch + ' to '+ migrationInfo.dstBranch);
return Q.all(jobIds.map(jobId => {
src = this._getFilePath({
project: migrationInfo.project,
branch: migrationInfo.srcBranch,
job: jobId
});
dst = this._getFilePath({
project: migrationInfo.project,
branch: migrationInfo.dstBranch,
job: jobId
});
return this._copyFile(src, dst).then(() => {
jobs = this._onCopyFinished[jobId];
for (var j = jobs.length; j--;) {
jobs[j]();
}
});
}));
};
JobLogManager.prototype._appendTo = function(filename, logs) {
return Q.nfcall(exists, filename).then(exists => {
var promise = Q().then(() => '');
if (exists) {
promise = Q.nfcall(fs.readFile, filename, 'utf8');
}
return promise.then(content => {
// This could be optimized to not re-read/write the whole file each time...
var lines = utils.resolveCarriageReturns(content + logs);
return Q.nfcall(fs.writeFile, filename, lines.join('\n'));
});
});
};
JobLogManager.prototype.appendTo = function(jobInfo, logs) {
var filename = this._getFilePath(jobInfo),
branchDirname = path.dirname(filename),
projDirname = path.dirname(branchDirname);
this.logger.info(`Appending content to ${filename}`);
// Make directory if needed
return this.mkdirIfNeeded(this.rootDir)
.then(() => this.mkdirIfNeeded(projDirname))
.then(() => this.mkdirIfNeeded(branchDirname))
.then(() => this._appendTo(filename, logs));
};
JobLogManager.prototype.getLog = function(jobInfo) {
var filename = this._getFilePath(jobInfo);
this.logger.info(`Getting log content from ${filename}`);
return this.exists(jobInfo)
.then(exists => {
if (exists) {
return Q.nfcall(fs.readFile, filename);
}
return NO_LOG_FOUND;
});
};
JobLogManager.prototype.delete = function(jobInfo) {
var filename = this._getFilePath(jobInfo);
return this.exists(jobInfo)
.then(exists => {
if (exists) {
this.logger.debug(`Removing file ${filename}`);
return Q.nfcall(fs.unlink, filename);
}
this.logger.info(`${filename} doesn't exist. No need to delete...`);
});
};
module.exports = JobLogManager;
+93
Ver Arquivo
@@ -0,0 +1,93 @@
/*jshint node:true*/
'use strict';
var express = require('express'),
JobLogManager = require('./JobLogManager'),
router = express.Router();
/**
* Called when the server is created but before it starts to listening to incoming requests.
* N.B. gmeAuth, safeStorage and workerManager are not ready to use until the start function is called.
* (However inside an incoming request they are all ensured to have been initialized.)
*
* @param {object} middlewareOpts - Passed by the webgme server.
* @param {GmeConfig} middlewareOpts.gmeConfig - GME config parameters.
* @param {GmeLogger} middlewareOpts.logger - logger
* @param {function} middlewareOpts.ensureAuthenticated - Ensures the user is authenticated.
* @param {function} middlewareOpts.getUserId - If authenticated retrieves the userId from the request.
* @param {object} middlewareOpts.gmeAuth - Authorization module.
* @param {object} middlewareOpts.safeStorage - Accesses the storage and emits events (PROJECT_CREATED, COMMIT..).
* @param {object} middlewareOpts.workerManager - Spawns and keeps track of "worker" sub-processes.
*/
function initialize(middlewareOpts) {
var logger = middlewareOpts.logger.fork('JobLogsAPI'),
ensureAuthenticated = middlewareOpts.ensureAuthenticated,
gmeConfig = middlewareOpts.gmeConfig,
logManager = new JobLogManager(logger, gmeConfig);
logger.debug('initializing ...');
// Ensure authenticated can be used only after this rule.
router.use('*', function (req, res, next) {
// This header ensures that any failures with authentication won't redirect.
res.setHeader('X-WebGME-Media-Type', 'webgme.v1');
next();
});
// Use ensureAuthenticated if the routes require authentication. (Can be set explicitly for each route.)
router.use('*', ensureAuthenticated);
router.get('/:project/:branch/:job', function (req, res/*, next*/) {
// Retrieve the job logs for the given job
logManager.getLog(req.params).then(log => {
res.set('Content-Type', 'text/plain');
res.send(log);
});
});
router.patch('/:project/:branch/:job', function (req, res/*, next*/) {
var logs = req.body.patch;
logger.info(`Received append request for ${req.params.job} in ${req.params.project}`);
logManager.appendTo(req.params, logs)
.then(() => res.send('Append successful'))
.catch(err => logger.error(`Append failed: ${err}`));
});
router.delete('/:project/:branch/:job', function (req, res/*, next*/) {
logManager.delete(req.params).then(() => res.send('delete successful'));
});
router.post('/migrate/:project/:srcBranch/:dstBranch', function (req, res/*, next*/) {
var jobs = req.body.jobs;
logManager.migrate(req.params, jobs)
.then(() => res.send('migration successful'))
.fail(err => logger.error(err));
});
logger.debug('ready');
}
/**
* Called before the server starts listening.
* @param {function} callback
*/
function start(callback) {
callback();
}
/**
* Called after the server stopped listening.
* @param {function} callback
*/
function stop(callback) {
callback();
}
module.exports = {
initialize: initialize,
router: router,
start: start,
stop: stop
};
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
+1
Ver Arquivo
@@ -0,0 +1 @@
0.2.0
Arquivo binário não exibido.
+1
Ver Arquivo
@@ -0,0 +1 @@
0.3.0
Arquivo binário não exibido.
@@ -117,7 +117,7 @@ define([
}
}
TextEditorControl.prototype.saveTextFor.call(this, id, text);
TextEditorControl.prototype.saveTextFor.call(this, id, text, true);
this._client.completeTransaction();
};
@@ -2,9 +2,11 @@
/*jshint browser: true*/
define([
'js/Constants'
'js/Constants',
'deepforge/utils'
], function (
CONSTANTS
CONSTANTS,
utils
) {
'use strict';
@@ -27,6 +29,9 @@ define([
this._lineToExec = {};
this._pipelineNames = {};
this.abbrToId = {};
this.abbrFor = {};
this._initWidgetEventHandlers();
this._logger.debug('ctor finished');
@@ -38,14 +43,36 @@ define([
ExecutionIndexControl.prototype.setExecutionDisplayed = function (id, bool) {
var lines = this._linesForExecution[id] || [],
action = bool ? 'addNode' : 'removeNode';
// If removing, just get the ids
lines = bool ? lines : lines.map(line => line.id);
otherLines,
wasMultiLine = this.displayedExecCount() > 1,
isMultiLine;
this._logger.info(`setting execution ${id} to ${bool ? 'displayed' : 'hidden'}`);
this.displayedExecutions[id] = bool;
// If we just crossed the multi line threshold, then update all the lines
isMultiLine = this.displayedExecCount() > 1;
if (isMultiLine !== wasMultiLine) {
// Refresh the other lines visible
otherLines = Object.keys(this.displayedExecutions)
.filter(eId => this.displayedExecutions[eId] && (eId !== id))
.map(id => this._linesForExecution[id] || [])
.reduce((l1, l2) => l1.concat(l2), []);
this._updateLines(otherLines, false);
this._updateLines(otherLines, true);
}
this._updateLines(lines, bool);
};
ExecutionIndexControl.prototype._updateLines = function (lines, added) {
var action = added ? 'addNode' : 'removeNode';
// If removing, just get the ids
lines = !added ? lines : lines.map(line => this._getObjectDescriptor(line))
.filter(line => !!line);
// update the given lines
for (var i = lines.length; i--;) {
this._widget[action](lines[i]);
@@ -83,6 +110,28 @@ define([
}
};
ExecutionIndexControl.prototype.getUniqAbbreviation = function(desc) {
// Get a unique abbreviation for the given execution
var base = utils.abbr(desc.name).toLowerCase(),
abbr = base,
oldAbbr = this.abbrFor[desc.id],
i = 2;
// Make sure it is unique!
while (this.abbrToId[abbr] && this.abbrToId[abbr] !== desc.id) {
abbr = base + i;
i++;
}
if (oldAbbr !== undefined) { // updating abbr
delete this.abbrToId[oldAbbr];
}
this.abbrToId[abbr] = desc.id;
this.abbrFor[desc.id] = abbr;
return abbr;
};
// This next function retrieves the relevant node information for the widget
ExecutionIndexControl.prototype._getObjectDescriptor = function (nodeId) {
var node = this._client.getNode(nodeId),
@@ -105,10 +154,16 @@ define([
desc.originTime = node.getAttribute('createdAt');
desc.originId = node.getPointer('origin').to;
desc.pipelineName = this._pipelineNames[desc.originId];
desc.startTime = node.getAttribute('startTime');
desc.endTime = node.getAttribute('endTime');
this._logger.debug(`Looking up pipeline name for ${desc.name}: ${desc.pipelineName}`);
// Add the (unique) abbreviation of the execution!
desc.abbr = this.getUniqAbbreviation(desc);
// Create a territory for this origin and update it!
this._selfPatterns[desc.originId] = {children: 0};
if (desc.originId) {
this._selfPatterns[desc.originId] = {children: 0};
}
setTimeout(() => this._client.updateTerritory(this._territoryId, this._selfPatterns), 0);
} else if (type === 'Line') {
desc = this.getLineDesc(node);
@@ -147,7 +202,6 @@ define([
desc = {
id: id,
//execName: execName,
execId: execId,
lineName: node.getAttribute('name'),
name: node.getAttribute('name'),
@@ -155,12 +209,23 @@ define([
points: points
};
// Update records
if (!this._linesForExecution[execId]) {
this._linesForExecution[execId] = [];
if (!this._lineToExec[id]) {
// Update records
if (!this._linesForExecution[execId]) {
this._linesForExecution[execId] = [];
}
this._linesForExecution[execId].push(id);
this._lineToExec[id] = execId;
}
// If there are multiple executions, add the exec's abbr
var displayedCnt = this.displayedExecCount(),
execAbbr;
if (displayedCnt > 1) {
execAbbr = this.abbrFor[execId] || this._getObjectDescriptor(execId).abbr;
desc.name = `${desc.name} (${execAbbr})`;
}
this._linesForExecution[execId].push(desc);
this._lineToExec[id] = execId;
return desc;
};
@@ -235,18 +300,25 @@ define([
};
ExecutionIndexControl.prototype._onUnload = function (id) {
var execId = this._lineToExec[id];
var execId = this._lineToExec[id],
abbr;
if (execId) { // it is a line
delete this._lineToExec[id];
for (var k = this._linesForExecution[execId].length; k--;) {
if (this._linesForExecution[execId][k].id === id) {
if (this._linesForExecution[execId][k] === id) {
this._linesForExecution[execId].splice(k, 1);
break;
}
}
}
if (this.abbrFor[id]) {
abbr = this.abbrFor[id];
delete this.abbrFor[id];
delete this.abbrToId[abbr];
}
this._widget.removeNode(id);
};
@@ -255,6 +327,12 @@ define([
return this.displayedExecutions[line.execId];
};
ExecutionIndexControl.prototype.displayedExecCount = function () {
return Object.keys(this.displayedExecutions)
.map(id => this.displayedExecutions[id])
.filter(shown => shown).length;
};
ExecutionIndexControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
if (this._currentNodeId === activeObjectId) {
// The same node selected as before - do not trigger
@@ -1,15 +1,14 @@
/*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/Constants',
'deepforge/Constants',
'panels/EasyDAG/EasyDAGControl',
'deepforge/viz/PipelineControl',
'underscore'
], function (
GME_CONSTANTS,
CONSTANTS,
EasyDAGControl,
PipelineControl,
@@ -62,7 +61,7 @@ define([
return;
}
if (event.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UNLOAD) {
this.originId = null;
this._widget.onOriginDeleted();
} else {
@@ -90,6 +89,65 @@ define([
};
};
ExecutionViewControl.prototype._getObjectDescriptor = function(id) {
var desc = PipelineControl.prototype._getObjectDescriptor.call(this, id),
childrenIds,
node,
opId;
// If it is a job, add the operation attributes
if (this.hasMetaName(id, 'Job')) {
node = this._client.getNode(id);
childrenIds = node.getChildrenIds();
opId = childrenIds.find(id => this.hasMetaName(id, 'Operation'));
desc.opAttributes = {};
if (opId) {
var opNode = this._client.getNode(opId),
attrs,
allAttrs = {},
hiddenAttrs = [
CONSTANTS.LINE_OFFSET,
'code',
'name'
],
i;
opNode.getValidAttributeNames().concat(opNode.getAttributeNames())
.forEach(attr => allAttrs[attr] = true);
// Remove skip values
hiddenAttrs.forEach(attr => delete allAttrs[attr]);
attrs = Object.keys(allAttrs);
for (i = attrs.length; i--;) {
desc.opAttributes[attrs[i]] = {
name: attrs[i],
value: opNode.getAttribute(attrs[i]),
type: 'string'
};
}
// Pointers
var allPtrs = {},
ptrs;
opNode.getValidPointerNames().concat(opNode.getPointerNames())
.filter(ptr => ptr !== 'base')
.forEach(ptr => allPtrs[ptr] = true);
ptrs = Object.keys(allPtrs);
for (i = ptrs.length; i--;) {
desc.pointers[ptrs[i]] = opNode.getPointer(ptrs[i]).to;
}
} else {
this.logger.error(`Job "${desc.name}" (${id}) is missing an operation!`);
}
}
return desc;
};
ExecutionViewControl.prototype._onLoad = function(id) {
var desc = this._getObjectDescriptor(id);
@@ -0,0 +1,28 @@
/* globals define */
// A notification widget which filters out stdout update notifications
define([
'deepforge/Constants',
'js/Widgets/Notification/NotificationWidget'
], function(
CONSTANTS,
GmeNotificationWidget
) {
var NotificationWidget = function() {
GmeNotificationWidget.apply(this, arguments);
};
NotificationWidget.prototype = Object.create(GmeNotificationWidget.prototype);
NotificationWidget.prototype.isUserNotication = function(data) {
return data.message.indexOf(CONSTANTS.STDOUT_UPDATE) === -1;
};
NotificationWidget.prototype._refreshNotifications = function(eventData) {
if (this.isUserNotication(eventData)) {
GmeNotificationWidget.prototype._refreshNotifications.call(this, eventData);
}
};
return NotificationWidget;
});
+9 -10
Ver Arquivo
@@ -1,8 +1,5 @@
/*globals define, _, WebGMEGlobal, $ */
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
*/
define([
'js/PanelBase/PanelBase',
@@ -10,13 +7,15 @@ define([
'js/Widgets/BranchStatus/BranchStatusWidget',
'js/Widgets/BranchSelector/BranchSelectorWidget',
'js/Widgets/KeyboardManager/KeyboardManagerWidget',
'js/Widgets/Notification/NotificationWidget'
], function (PanelBase,
NetworkStatusWidget,
BranchStatusWidget,
BranchSelectorWidget,
KeyboardManagerWidget,
NotificationWidget) {
'./FilteredNotificationWidget'
], function (
PanelBase,
NetworkStatusWidget,
BranchStatusWidget,
BranchSelectorWidget,
KeyboardManagerWidget,
NotificationWidget
) {
'use strict';
@@ -1,4 +1,4 @@
/*globals DeepForge, define, $, WebGMEGlobal*/
/*globals define, $, WebGMEGlobal*/
// These are actions defined for specific meta types. They are evaluated from
// the context of the ForgeActionButton
define([
@@ -9,7 +9,8 @@ define([
], function(
Materialize,
Q,
REGISTRY_KEYS
REGISTRY_KEYS,
DeepForge
) {
var FILE_UPLOAD_INPUT = $('<input type="file" />');
@@ -138,18 +139,19 @@ define([
}
];
var makeRestartButton = function(name, pluginId) {
var makeRestartButton = function(name, pluginId, hotkeys) {
return {
name: 'Restart ' + name,
icon: 'replay',
priority: 1000,
color: 'red',
hotkey: hotkeys && 'shift enter',
filter: function() {
// Only show if stopped!
return !this.isRunning();
},
action: function(event) {
this.runExecutionPlugin(pluginId, event.shiftKey);
this.runExecutionPlugin(pluginId, {useSecondary: event.shiftKey});
}
};
};
@@ -239,28 +241,18 @@ define([
}
],
Execution: [
makeRestartButton('Execution', 'ExecutePipeline'),
makeRestartButton('Execution', 'ExecutePipeline', true),
// Stop execution button
{
name: 'Stop Running Execution',
icon: 'stop',
priority: 1001,
hotkey: 'shift enter',
filter: function() {
return this.isRunning();
},
action: function() {
// Stop every running job
var execNode = this.client.getNode(this._currentNodeId),
jobIds = execNode.getChildrenIds(),
msg = `Canceling ${execNode.getAttribute('name')} execution`;
this.client.startTransaction(msg);
jobIds.map(id => this.client.getNode(id))
.filter(job => this.isRunning(job)) // get running jobs
.forEach(job => this.stopJob(job)); // stop them
this.client.setAttributes(execNode.getId(), 'status', 'canceled');
this.client.completeTransaction();
this.stopExecution();
}
}
],
@@ -1,53 +1,46 @@
/*globals DeepForge, $, WebGMEGlobal, window, define, _ */
/*globals $, window, define, _ */
/*jshint browser: true*/
define([
'panel/FloatingActionButton/styles/Materialize',
'blob/BlobClient',
'executor/ExecutorClient',
'js/Constants',
'panel/FloatingActionButton/FloatingActionButton',
'deepforge/viz/PipelineControl',
'deepforge/viz/NodePrompter',
'deepforge/viz/Execute',
'./Actions',
'widgets/EasyDAG/AddNodeDialog',
'js/RegistryKeys',
'js/Panels/MetaEditor/MetaEditorConstants',
'q',
'text!./PluginConfig.json',
'deepforge/globals'
], function (
Materialize,
BlobClient,
ExecutorClient,
CONSTANTS,
PluginButton,
PipelineControl,
NodePrompter,
Execute,
ACTIONS,
AddNodeDialog,
REGISTRY_KEYS,
META_CONSTANTS,
Q,
PluginConfig
DeepForge
) {
'use strict';
var NEW_OPERATION_ID = '__NEW_OPERATION__';
var ForgeActionButton= function (layoutManager, params) {
PluginButton.call(this, layoutManager, params);
this._pluginConfig = JSON.parse(PluginConfig);
this._executor = new ExecutorClient({
logger: this.logger.fork('ExecutorClient'),
serverPort: WebGMEGlobal.gmeConfig.server.port,
httpsecure: window.location.protocol === 'https:'
});
this._client = this.client;
this._actions = [];
this._blobClient = new BlobClient({
logger: this.logger.fork('BlobClient')
});
Execute.call(this, this.client, this.logger);
this.initializeKeyListener();
this.logger.debug('ctor finished');
};
@@ -55,9 +48,46 @@ define([
_.extend(
ForgeActionButton.prototype,
PluginButton.prototype,
Execute.prototype,
PipelineControl.prototype
);
ForgeActionButton.prototype.initializeKeyListener = function() {
// add key listener to parent?
this.oldOnKeyDown = document.body.onkeydown;
document.onkeydown = event => {
var keys = String.fromCharCode(event.which) || '',
names = Object.keys(this.buttons),
btn,
name;
// Simple button detection
if (event.which === 13) {
keys = 'enter';
}
if (event.shiftKey) {
keys = 'shift ' + keys;
}
for (var i = names.length; i--;) {
name = names[i];
btn = this.buttons[name];
if (btn.hotkey && btn.hotkey === keys) {
btn.action.call(this, event);
}
}
if (this.oldOnKeyDown) {
this.oldOnKeyDown(event);
}
};
};
ForgeActionButton.prototype.destroy = function() {
PluginButton.prototype.destroy.call(this);
PipelineControl.prototype.destroy.call(this);
document.body.onclick = this.oldOnKeyDown;
};
ForgeActionButton.prototype.findActionsFor = function(nodeId) {
var node = this.client.getNode(nodeId),
base = this.client.getNode(node.getMetaTypeId()),
@@ -330,74 +360,5 @@ define([
}
};
ForgeActionButton.prototype.runExecutionPlugin = function(pluginId, useSecondary) {
var context = this.client.getCurrentPluginContext(pluginId),
name = this.client.getNode(this._currentNodeId).getAttribute('name'),
method;
context.managerConfig.namespace = 'pipeline';
method = useSecondary ? 'runBrowserPlugin' : 'runServerPlugin';
this.client[method](pluginId, context, (err, result) => {
var msg = err ? `${name} failed!` : `${name} executed successfully!`,
duration = err ? 4000 : 2000;
// Check if it was canceled - if so, show that type of message
if (result) {
msg = result.messages[0].message;
duration = 4000;
}
Materialize.toast(msg, duration);
});
};
ForgeActionButton.prototype.isRunning = function(node) {
var baseId,
base,
type;
node = node || this.client.getNode(this._currentNodeId);
baseId = node.getBaseId();
base = this.client.getNode(baseId);
type = base.getAttribute('name');
if (type === 'Execution') {
return node.getAttribute('status') === 'running';
} else if (type === 'Job') {
return this.isRunningJob(node);
}
return false;
};
ForgeActionButton.prototype.isRunningJob = function(job) {
var status = job.getAttribute('status');
return (status === 'running' || status === 'pending') &&
job.getAttribute('secret') && job.getAttribute('jobId');
};
ForgeActionButton.prototype.stopJob = function(job) {
var jobHash,
jobId,
secret;
job = job || this.client.getNode(this._currentNodeId);
jobId = job.getId();
jobHash = job.getAttribute('jobId');
secret = job.getAttribute('secret');
if (!jobHash || !secret) {
this.logger.error('Cannot stop job. Missing jobHash or secret');
return;
}
this.client.delAttributes(jobId, 'jobId');
this.client.delAttributes(jobId, 'secret');
this.client.setAttributes(jobId, 'status', 'canceled');
return this._executor.cancelJob(jobHash, secret)
.then(() => this.logger.info(`${jobHash} has been cancelled!`))
.fail(err => this.logger.error(`Job cancel failed: ${err}`));
};
return ForgeActionButton;
});
@@ -1,19 +0,0 @@
{
"GenerateArchitecture": {
"icon": "description",
"priority": -1
},
"ExecutePipeline": {
"icon": "play_arrow",
"color": "green",
"priority": 1
},
"ImportTorch": {
"icon": "import_export",
"priority": -1
},
"GenerateExecFile": {
"icon": "play_for_work",
"priority": -1
}
}
@@ -68,6 +68,9 @@ define([
// The OperationCodeEditor should receive the
if (!this.readOnly) {
// Pass a reference to the panel
this._panels[0].control.currentJobId = nodeId;
// Get the operation base node id and pass it to OpCodeEditor selObjChanged
if (this._territoryId) {
this._client.removeUI(this._territoryId);
@@ -32,6 +32,8 @@ define([
LayerEditorControl.prototype._getObjectDescriptor = function (nodeId) {
var desc = TextEditorControl.prototype._getObjectDescriptor.call(this, nodeId),
node = this._client.getNode(nodeId),
baseId = node.getBaseId(),
base = this._client.getNode(baseId),
hasCode = node.getValidAttributeNames().indexOf('code') > -1,
template;
@@ -50,7 +52,16 @@ define([
}
if (template) {
desc.text = _.template(template)(desc);
var baseTorchType = 'nn.Module';
// If the base type is 'Criterion', set the base type to nn.Criterion
if (base.getAttribute('name') === 'Criterion') {
baseTorchType = 'nn.Criterion';
}
desc.text = _.template(template)({
name: desc.name,
baseTorchType: baseTorchType
});
}
return desc;
};
@@ -82,7 +93,7 @@ define([
this._client.startTransaction(msg);
TextEditorControl.prototype.saveTextFor.call(this, id, text);
TextEditorControl.prototype.saveTextFor.call(this, id, text, true);
this._client.setAttributes(id, 'name', layerSchema.name);
this._logger.debug(`Setting ctor args to ${ctorAttrs.join(',')}`);
@@ -2,9 +2,18 @@
/*jshint browser: true*/
// This is a read-only view of the 'stdout' attribute for a Job node
// if the job is running, get the logs from the log-storage
define([
'q',
'deepforge/JobLogsClient',
'js/Constants',
'deepforge/Constants',
'panels/TextEditor/TextEditorControl'
], function (
Q,
JobLogsClient,
GME_CONSTANTS,
CONSTANTS,
TextEditorControl
) {
@@ -19,11 +28,68 @@ define([
_.extend(LogViewerControl.prototype, TextEditorControl.prototype);
LogViewerControl.prototype.getFullDescriptor = function (id) {
var desc = LogViewerControl.prototype._getObjectDescriptor.call(this, id);
return this._getRunningLogs(id).then(text => {
// Use attribute or running log if none
desc.text = desc.text || text;
return desc;
});
};
LogViewerControl.prototype.getUpdatedJobId = function (msg) {
// verify that it is the given notification type
if (msg.indexOf(CONSTANTS.STDOUT_UPDATE) !== -1) {
return msg.replace(/^[^\/]*\//, '');
}
};
LogViewerControl.prototype.selectedObjectChanged = function (id) {
TextEditorControl.prototype.selectedObjectChanged.call(this, id);
// Listen for notifications about updated logs
this.removeNotificationHandler();
this.notificationHandler = (sender, data) => {
var nodeId = this.getUpdatedJobId(data.message);
if (nodeId === id) {
this._onUpdate(id);
}
};
this._client.addEventListener(GME_CONSTANTS.CLIENT.NOTIFICATION, this.notificationHandler);
};
LogViewerControl.prototype.removeNotificationHandler = function () {
// Remove the notifications listener
if (this.notificationHandler) {
this._client.removeEventListener();
this.notificationHandler = null;
}
};
LogViewerControl.prototype.destroy = function () {
TextEditorControl.prototype.destroy.call(this);
this.removeNotificationHandler();
};
LogViewerControl.prototype._onLoad = function (id) {
this.getFullDescriptor(id).then(desc => this._widget.addNode(desc));
};
LogViewerControl.prototype._onUpdate = function (id) {
if (id === this._currentNodeId) {
TextEditorControl.prototype._onUpdate.call(this, id);
this.getFullDescriptor(id).then(desc => this._widget.updateNode(desc));
}
};
LogViewerControl.prototype._getRunningLogs = function (id) {
var logManager = new JobLogsClient({
logger: this._logger,
projectId: this._client.getActiveProjectId(),
branchName: this._client.getActiveBranchName()
});
return logManager.getLog(id);
};
return LogViewerControl;
});
+31 -14
Ver Arquivo
@@ -4,14 +4,12 @@
define([
'blob/BlobClient',
'js/Constants',
'js/Utils/GMEConcepts',
'js/NodePropertyNames',
'q',
'deepforge/globals'
], function (
BlobClient,
CONSTANTS,
GMEConcepts,
nodePropertyNames,
Q,
DeepForge
) {
@@ -22,15 +20,11 @@ define([
MainViewControl = function (options) {
this._logger = options.logger.fork('Control');
this._client = options.client;
// Initialize core collections and variables
this._widget = options.widget;
this._currentNodeId = null;
this._embedded = options.embedded;
this.territory = {};
this.ui = {};
this._blobClient = new BlobClient({
@@ -67,12 +61,33 @@ define([
};
this._widget.toggleEmbeddedPanel = () => this.toggleEmbeddedPanel();
this._widget.updateLibraries = this.updateLibraries.bind(this);
this._widget.checkLibUpdates = this.checkLibUpdates.bind(this);
this._widget.getProjectName = this.getProjectName.bind(this);
};
MainViewControl.prototype.getProjectName = function () {
return this._client.getActiveProjectId().split('+')[1];
};
MainViewControl.prototype.checkLibUpdates = function () {
var pluginId = 'CheckLibraries',
context = this._client.getCurrentPluginContext(pluginId);
return Q.ninvoke(this._client, 'runServerPlugin', pluginId, context)
.then(res => {
return res.messages.map(msg => msg.message.split(' '));
});
};
MainViewControl.prototype.updateLibraries = function (libraries) {
var promises = libraries
.map(lib => Q.ninvoke(this._client, 'updateLibrary', lib[0], lib[1]));
return Q.all(promises);
};
/* * * * * * * * Visualizer content update callbacks * * * * * * * */
// One major concept here is with managing the territory. The territory
// defines the parts of the project that the visualizer is interested in
// (this allows the browser to then only load those relevant parts).
MainViewControl.prototype.selectedObjectChanged = function (nodeId) {
this._logger.debug('activeObject nodeId \'' + nodeId + '\'');
@@ -94,9 +109,11 @@ define([
// Update the territory
this.territory[type] = {};
this.territory[type][DeepForge.places[dirname]] = {children: 1};
this.ui[type] = this._client.addUI(this, this.handleEvents.bind(this, type));
this._client.updateTerritory(this.ui[type], this.territory[type]);
DeepForge.places[dirname]().then(id => {
this.territory[type][id] = {children: 1};
this.ui[type] = this._client.addUI(this, this.handleEvents.bind(this, type));
this._client.updateTerritory(this.ui[type], this.territory[type]);
});
});
}
};
@@ -73,7 +73,8 @@ define([
this.control.toggleEmbeddedPanel = this.toggleEmbeddedPanel.bind(this);
var selectedObjectChanged = this.control.selectedObjectChanged;
this.control.selectedObjectChanged = id => {
this.embeddedPanel.control.selectedObjectChanged(this.getEmbeddedNode());
this.getEmbeddedNode().then(nodeId =>
this.embeddedPanel.control.selectedObjectChanged(nodeId));
selectedObjectChanged.call(this.control, id);
};
@@ -82,7 +83,11 @@ define([
};
MainViewPanel.prototype.getEmbeddedNode = function() {
return this.nextPanelIndex === 1 ? DeepForge.places.MyPipelines : DeepForge.places.MyExecutions;
if (this.nextPanelIndex === 1) {
return DeepForge.places.MyPipelines();
} else {
return DeepForge.places.MyExecutions();
}
};
MainViewPanel.prototype.toggleEmbeddedPanel = function (silent) {
@@ -102,7 +107,8 @@ define([
// Call on Resize and selectedObjectChanged
this.onResize(this.width, this.height);
if (!silent) {
this.embeddedPanel.control.selectedObjectChanged(this.getEmbeddedNode());
this.getEmbeddedNode().then(nodeId =>
this.embeddedPanel.control.selectedObjectChanged(nodeId));
}
};
@@ -4,11 +4,13 @@
define([
'panels/TextEditor/TextEditorControl',
'deepforge/viz/OperationControl',
'deepforge/viz/Execute',
'deepforge/Constants',
'underscore'
], function (
TextEditorControl,
OperationControl,
Execute,
CONSTANTS,
_
) {
@@ -20,17 +22,21 @@ define([
OperationCodeEditorControl = function (options) {
options.attributeName = 'code';
TextEditorControl.call(this, options);
Execute.call(this, this._client, this._logger);
this.currentJobId = null;
};
_.extend(
OperationCodeEditorControl.prototype,
OperationControl.prototype,
TextEditorControl.prototype
TextEditorControl.prototype,
Execute.prototype
);
OperationCodeEditorControl.prototype._initWidgetEventHandlers = function () {
TextEditorControl.prototype._initWidgetEventHandlers.call(this);
this._widget.getOperationAttributes = this.getOperationAttributes.bind(this);
this._widget.executeOrStopJob = this.executeOrStopJob.bind(this);
};
OperationCodeEditorControl.prototype.TERRITORY_RULE = {children: 3};
@@ -78,6 +84,19 @@ define([
return attrs;
};
OperationCodeEditorControl.prototype.executeOrStopJob = function () {
var job;
if (this.currentJobId) { // Only if nested in a job
job = this._client.getNode(this.currentJobId);
if (this.isRunning(job)) {
this.stopJob(job);
} else {
this.executeJob(job);
}
}
};
// Line offset handling
OperationCodeEditorControl.prototype.offsetNodeChanged = function (id) {
// Create a territory for this node
@@ -9,6 +9,7 @@ define([
this._widget.allDataTypeIds = this.allDataTypeIds.bind(this);
this._widget.allValidReferences = this.allValidReferences.bind(this);
this._widget.addRefTo = this.addRefTo.bind(this);
this._widget.setRefType = this.setRefType.bind(this);
this._widget.changePtrName = this.changePtrName.bind(this);
this._widget.removePtr = this.removePtr.bind(this);
this._widget.getCreationNode = this.getCreationNode.bind(this);
@@ -138,6 +139,29 @@ define([
this._client.completeTransaction();
};
OperationInterfaceEditorEvents.prototype.setRefType = function(ref, targetId) {
var meta = this._client.getPointerMeta(this._currentNodeId, ref),
msg = `Setting ${ref} reference type to ${targetId}`;
if (!meta) {
this.logger.debug(`No meta found for ${ref}. Creating a new reference to ${targetId}`);
meta = {
min: 1,
max: 1,
items: []
};
}
meta.items.push({
id: targetId,
max: 1
});
this._client.startTransaction(msg);
this._client.setPointerMeta(this._currentNodeId, ref, meta);
this._client.completeTransaction();
};
OperationInterfaceEditorEvents.prototype.changePtrName = function(from, to) {
var opNode = this._client.getNode(this._currentNodeId),
name = opNode.getAttribute('name'),
@@ -255,13 +255,23 @@ define([
};
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'),
var Decorator = this._client.decoratorManager.getDecoratorForWidget('OpIntPtrDecorator', 'EasyDAG'),
id = 'ptr_'+name,
used = this.isUsedInput(name);
used = this.isUsedInput(name),
ptrMeta = this._client.getPointerMeta(this._currentNodeId, name),
targetId,
target,
baseName;
if (!ptrMeta || ptrMeta.items.length === 0) {
// No known type
this._logger.error(`No known target type for "${name}" reference`);
baseName = null;
} else {
targetId = ptrMeta.items[0].id;
target = this._client.getNode(targetId);
baseName = target.getAttribute('name');
}
if (used === null) {
used = this._usage[id] !== undefined ? this._usage[id] : true;
@@ -270,7 +280,8 @@ define([
return {
id: id,
isPointer: true,
baseName: target.getAttribute('name'),
baseName: baseName,
isUnknown: !baseName,
Decorator: Decorator,
used: used,
attributes: {},
@@ -2,9 +2,11 @@
/*jshint browser: true*/
define([
'deepforge/Constants',
'js/Constants',
'panels/EasyDAG/EasyDAGControl',
'deepforge/viz/PipelineControl',
'deepforge/viz/Execute',
'deepforge/globals',
'common/core/coreQ',
'common/storage/constants',
@@ -12,8 +14,10 @@ define([
'underscore'
], function (
CONSTANTS,
GME_CONSTANTS,
EasyDAGControl,
PipelineControl,
Execute,
DeepForge,
Core,
STORAGE_CONSTANTS,
@@ -29,26 +33,28 @@ define([
DST: 'dst'
},
DECORATORS = {
ArtifactLoader: 'ArtifactOpDecorator',
ArtifactFinder: 'ArtifactOpDecorator'
},
WIDGET_NAME = 'EasyDAG';
DECORATORS[CONSTANTS.OP.INPUT] = 'ArtifactOpDecorator';
PipelineEditorControl = function (options) {
EasyDAGControl.call(this, options);
Execute.call(this, this._client, this._logger);
this.addedIds = {};
this.executionTerritory = {};
this.executionUI = null;
this.invalidated = {};
this._widget.deleteNode = id => {
this._deleteNode(id);
};
this._widget.deleteExecution = this.deleteExecution.bind(this);
this._widget.isArchitecturePtr = this.isArchitecturePtr.bind(this);
};
_.extend(
PipelineEditorControl.prototype,
EasyDAGControl.prototype,
PipelineControl.prototype
PipelineControl.prototype,
Execute.prototype
);
PipelineEditorControl.prototype._getValidInitialNodes =
@@ -126,7 +132,7 @@ define([
// Add arch/artifact dir to the territory
// loading more than necessary.... can restrict it in the future
// if perf is a problem
this._territories[CONSTANTS.PROJECT_ROOT_ID] = {children: 2};
this._territories[GME_CONSTANTS.PROJECT_ROOT_ID] = {children: 2};
this._client.updateTerritory(this._territoryId, this._territories);
};
@@ -498,7 +504,7 @@ define([
PipelineEditorControl.prototype._getTargetDirs = function (typeIds) {
// Find the directories containing these types
return this._client.getNode(CONSTANTS.PROJECT_ROOT_ID).getChildrenIds()
return this._client.getNode(GME_CONSTANTS.PROJECT_ROOT_ID).getChildrenIds()
// No referencing data meta types
.filter(id => {
var cMeta = this._client.getChildrenMeta(id),
@@ -543,11 +549,11 @@ define([
// Handle events related to the associated executions
for (var i = events.length; i--;) {
event = events[i];
if (event.etype === CONSTANTS.TERRITORY_EVENT_LOAD) {
if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_LOAD) {
this.onExecLoad(event.eid);
} else if (event.etype === CONSTANTS.TERRITORY_EVENT_UPDATE) {
} else if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UPDATE) {
this.onExecUpdate(event.eid);
} else if (event.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
} else if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UNLOAD) {
this.onExecUnload(event.eid);
}
}
@@ -595,6 +601,42 @@ define([
}
};
PipelineEditorControl.prototype._deleteTag = function (tagName) {
// Check if the tag exists and delete it if so!
var projectId = this._client.getActiveProjectId();
this._client.deleteTag(projectId, tagName, err => {
if (err) {
this.logger.error(`Tag deletion failed: ${err}`);
}
});
};
PipelineEditorControl.prototype.deleteExecution = function (id) {
var node = this._client.getNode(id),
name = '',
msg;
if (node) {
name = node && node.getAttribute('name');
}
msg = `Deleted ${name} (${id}) execution`;
// Stop the execution w/o setting any attributes on the execution
this._client.startTransaction(msg);
this._deleteTag(name); // Remove execution tag
if (this.isRunning(node)) {
this.silentStopExecution(id, true).then(() => {
this._client.delMoreNodes([id]);
this._client.completeTransaction();
});
} else {
this._client.delMoreNodes([id]);
this._client.completeTransaction();
}
};
PipelineEditorControl.prototype.updateThumbnail = function (svg) {
var node = this._client.getNode(this._currentNodeId),
name,
@@ -641,7 +683,19 @@ define([
} else {
return EasyDAGControl.prototype._getValidTargetsFor.apply(this, arguments);
}
};
PipelineEditorControl.prototype.isArchitecturePtr = function (id, ptr) {
var ptrMeta = this._client.getPointerMeta(id, ptr),
targets;
// Check if ptr of the given id is referencing an architecture
if (ptrMeta.items) {
targets = ptrMeta.items.map(item => this._client.getNode(item.id));
return !!targets.find(node => node.getAttribute('name') === 'Architecture');
}
return false;
};
return PipelineEditorControl;
@@ -1,17 +1,17 @@
/*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',
define([
'js/PanelBase/PanelBaseWithHeader',
'js/PanelManager/IActivePanel',
'widgets/PipelineEditor/PipelineEditorWidget',
'./PipelineEditorControl'
], function (PanelBaseWithHeader,
IActivePanel,
PipelineEditorWidget,
PipelineEditorControl) {
], function (
PanelBaseWithHeader,
IActivePanel,
PipelineEditorWidget,
PipelineEditorControl
) {
'use strict';
var PipelineEditorPanel;
@@ -62,7 +62,7 @@ define(['js/PanelBase/PanelBaseWithHeader',
});
// Editable pipeline name
this.$panelHeaderTitle.on('dblclick', () => this.editTitle());
this.$panelHeaderTitle.on('click', () => this.editTitle());
this.onActivate();
};
@@ -33,12 +33,33 @@ define([
this._widget.deletePipeline = id => {
var node = this._client.getNode(id),
name = node.getAttribute('name'),
msg = `Deleting pipeline "${name}"`;
msg = `Deleting pipeline "${name}"`,
delTerritory = {},
delUI,
ids = [id];
// Change the current active object
this._client.startTransaction(msg);
this._client.delMoreNodes([id]);
this._client.completeTransaction();
// Delete all associated executions
ids = node.getMemberIds('executions');
for (var i = ids.length; i--;) {
delTerritory[ids[i]] = {children: 0};
}
delUI = this._client.addUI(this, events => {
var ids = [id];
for (i = events.length; i--;) {
if (events[i].eid && events[i].etype === CONSTANTS.TERRITORY_EVENT_LOAD) {
ids.push(events[i].eid);
}
}
this._client.startTransaction(msg);
this._client.delMoreNodes(ids);
this._client.completeTransaction();
this._client.removeUI(delUI);
});
this._client.updateTerritory(delUI, delTerritory);
};
this._widget.setName = (id, name) => {
@@ -47,8 +47,18 @@ define([
this._widget.setName = this.setName.bind(this);
};
TextEditorControl.prototype.saveTextFor = function (id, text) {
TextEditorControl.prototype.saveTextFor = function (id, text, inTransaction) {
var node = this._client.getNode(this._currentNodeId),
name = node.getAttribute('name'),
msg = `Updating ${this.ATTRIBUTE_NAME} of ${name} (${id})`;
if (!inTransaction) {
this._client.startTransaction(msg);
}
this._client.setAttributes(id, this.ATTRIBUTE_NAME, text);
if (!inTransaction) {
this._client.completeTransaction();
}
};
TextEditorControl.prototype.setName = function (name) {
@@ -125,6 +135,7 @@ define([
desc.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
desc.parentId = nodeObj.getParentId(); // used by the 'up' button in the toolbar
desc.text = nodeObj.getAttribute(this.ATTRIBUTE_NAME);
desc.ownText = nodeObj.getOwnAttribute(this.ATTRIBUTE_NAME);
}
return desc;
@@ -25,6 +25,7 @@ define([
_.extend(DeserializeEditorWidget.prototype, SerializeEditorWidget.prototype);
DeserializeEditorWidget.prototype.getHeader = function(desc) {
this._name = desc.name;
return [
`-- The deserialization function for ${desc.name}`,
'-- Globals:',
@@ -5,6 +5,7 @@
<td>Name</td>
<td>Creation Date</td>
<td>Origin Pipeline</td>
<td>Duration</td>
</tr>
</thead>
<tbody class="execs-content">
@@ -23,6 +23,7 @@ define([
this.nodes = {};
this.graphs = {};
this.checkedIds = [];
this._initialize();
this._logger.debug('ctor finished');
@@ -97,6 +98,8 @@ define([
// Adding/Removing/Updating items
ExecutionIndexWidget.prototype.addNode = function (desc) {
var isFirstNode = Object.keys(this.nodes).length === 0;
if (desc.type === 'Execution') {
// Add node to a table of nodes
this.addExecLine(desc);
@@ -105,6 +108,10 @@ define([
desc.type = 'line';
this.lineGraph.addNode(desc);
}
if (isFirstNode) {
this.updateTimes();
}
};
ExecutionIndexWidget.prototype.updatePipelineName = function (execId, name) {
@@ -120,6 +127,7 @@ define([
fields,
pipeline,
name,
duration = $('<div>'),
td;
pipeline = $('<a>', {
@@ -127,13 +135,15 @@ define([
'data-id': desc.originId
}).text(desc.pipelineName || 'view pipeline');
name = $('<a>', {class: 'node-nav', 'data-id': desc.id}).text(desc.name);
name = $('<a>', {class: 'node-nav', 'data-id': desc.id})
.text(desc.name);
fields = [
checkBox,
name,
Utils.getDisplayTime(desc.originTime),
pipeline
pipeline,
duration
];
for (var i = 0; i < fields.length; i++) {
@@ -152,11 +162,61 @@ define([
this.nodes[desc.id] = {
statusClass: statusClass,
desc: desc,
$el: row,
$checkbox: checkBox[0],
$pipeline: pipeline,
$duration: duration,
$name: name
};
this.updateTime(desc.id, true);
};
ExecutionIndexWidget.prototype.getDurationText = function (duration) {
var hours,
min,
sec;
sec = duration/1000;
hours = Math.floor(sec/3600);
sec = sec%3600;
min = Math.floor(sec/60);
sec = Math.floor(sec%60);
return `${hours}:${min}:${sec}`;
};
ExecutionIndexWidget.prototype.updateTime = function (id, force) {
var desc = this.nodes[id].desc,
duration = 'unknown';
if (desc.status === 'running') {
if (desc.startTime) {
duration = this.getDurationText(Date.now() - desc.startTime);
}
this.nodes[id].$duration.text(duration);
return true;
} else if (force) {
if (desc.endTime && desc.startTime) {
duration = this.getDurationText(desc.endTime - desc.startTime);
}
this.nodes[id].$duration.text(duration);
return true;
}
return false;
};
ExecutionIndexWidget.prototype.updateTimes = function () {
var nodeIds = Object.keys(this.nodes),
updated = false;
for (var i = nodeIds.length; i--;) {
updated = this.updateTime(nodeIds[i]) || updated;
}
if (updated) { // if there are still nodes, call again!
setTimeout(this.updateTimes.bind(this), 1000);
}
};
ExecutionIndexWidget.prototype.removeNode = function (id) {
@@ -185,8 +245,46 @@ define([
};
ExecutionIndexWidget.prototype.toggleAbbreviations = function (show, ids) {
var node,
desc,
name;
ids = ids || this.checkedIds;
for (var i = ids.length; i--;) {
node = this.nodes[ids[i]];
desc = node.desc;
name = show ? `${desc.name} (${desc.abbr})` : desc.name;
node.$name.text(name);
}
};
ExecutionIndexWidget.prototype.setSelect = function (id, checked) {
var wasChecked = this.checkedIds.length > 1,
isChecked;
this.nodes[id].$checkbox.checked = checked;
// If multiple are checked, display the abbreviation
if (checked) {
this.checkedIds.push(id);
} else {
var k = this.checkedIds.indexOf(id);
if (k !== -1) {
this.checkedIds.splice(k, 1);
}
}
isChecked = this.checkedIds.length > 1;
if (isChecked !== wasChecked) {
this.toggleAbbreviations(isChecked);
}
// Update the given node
if (!checked || isChecked) {
this.toggleAbbreviations(checked, [id]);
}
this.setExecutionDisplayed(id, checked);
};
@@ -205,6 +303,7 @@ define([
this._logger.debug(`setting execution ${desc.id} to ${desc.status}`);
node.statusClass = Utils.ClassForJobStatus[desc.status];
node.desc = desc;
} else if (desc.type === 'line') {
this.lineGraph.updateNode(desc);
}
@@ -3,10 +3,12 @@
define([
'widgets/EasyDAG/SelectionManager',
'widgets/EasyDAG/Buttons',
'deepforge/Constants',
'underscore'
], function(
EasyDAGSelectionManager,
Buttons,
CONSTANTS,
_
) {
'use strict';
@@ -18,16 +20,19 @@ define([
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
SelectionManager.prototype.createActionButtons = function(width/*, height*/) {
// Add 'watch' and 'jumpToDef' buttons
// TODO
new Buttons.Enter({
context: this._widget,
$pEl: this.$selection,
item: this.selectedItem,
icon: 'monitor',
x: width,
y: 0
});
var jobName = this.selectedItem.desc.name;
// Check if it is an Input or Output job
if (jobName !== CONSTANTS.OP.INPUT && jobName !== CONSTANTS.OP.OUTPUT) {
new Buttons.Enter({
context: this._widget,
$pEl: this.$selection,
item: this.selectedItem,
icon: 'monitor',
x: width,
y: 0
});
}
};
return SelectionManager;
@@ -82,7 +82,6 @@ define([
ImageViewerWidget.prototype.updateImage = function (url) {
url = url || NO_IMAGE_URL;
this.zoom = 1;
this.$image.attr('src', url);
};
@@ -48,6 +48,7 @@ define([
.axisLabel(this.options.xAxis);
}
chart.yAxis.tickFormat(d3.format('.02f'));
if (this.options.yAxis) {
chart.yAxis
.axisLabel(this.options.yAxis);
@@ -68,7 +69,9 @@ define([
};
LineGraphWidget.prototype.getData = function () {
return Object.keys(this.lineData).map(id => this.lineData[id]);
return Object.keys(this.lineData)
.map(id => this.lineData[id])
.filter(data => data.values.length !== 0); // hide empty lines
};
// Adding/Removing/Updating items
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1 +1 @@
{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"AAqBA,oBAfA,oBAgBI,KAAM,KAmXN,gBAAiB,WAhFrB,kBA+DA,uBAnWA,oBAfA,oBAmYI,gBAAiB,WAmErB,UAAW,UAJX,mBAvcA,eAsbA,uBA8BA,uCACI,eAAgB,KA+DpB,WA7QA,aAoRI,QAAS,MAST,sBAAuB,KAEvB,mBAAoB,KAtiBxB,eAEI,QAAS,EAuCb,2BA4JA,0DACI,QAAS,EAjMb,oBAEI,OAAQ,KACR,eAAgB,IAIpB,2BACI,eAAgB,IAGpB,gCACI,eAAgB,EAGpB,oBAEI,OAAQ,QAIZ,0BACI,0BACA,eAAgB,IAGpB,mCACI,YAAa,IAGjB,sCACA,uCACA,uCACI,YAAa,OAOjB,oBACI,aAAc,IAEd,WAAY,aAAa,MAAM,OAC/B,gBAAiB,aAAa,MAAM,OACpC,mBAAoB,aAAa,MAAM,OAG3C,0BACI,aAAc,EAGlB,2BACI,KAAM,QAGV,oBACI,KAAM,YAGV,2BACI,KAAM,cAKV,sCAFA,mCACA,6CAEI,eAAgB,EAEhB,WAAY,aAAa,MAAM,OAC/B,gBAAiB,aAAa,MAAM,OACpC,mBAAoB,aAAa,MAAM,OAK3C,8CACA,4CAHA,yCACA,mDAGI,aAAc,EAGlB,sCACA,6CACI,YAAa,IACb,KAAM,cACN,OAAQ,YAIZ,yBACE,aAAc,GAGhB,+BAIA,6BAHE,aAAc,EAOhB,6BACE,OAAQ,KAGV,uBACE,aAAc,MAGhB,gBAAkB,KAAM,KAAK,WAC7B,4BAA8B,aAAc,GAC5C,kCAAoC,aAAc,EAClD,2BAA6B,OAAQ,KAAM,aAAc,IACzD,mCAAqC,OAAQ,KAAM,KAAM,KAAM,aAAc,MAC7E,+BAAiC,OAAQ,KAAM,aAAc,MAC7D,8BAAgC,OAAQ,KAAM,aAAc,KAC5D,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,0BAA4B,UAAW,KAAM,YAAa,IAC1D,6BAA+B,KAAM,KAGrC,0BACI,KAAM,QACN,aAAc,GAElB,gCACI,aAAc,GAGlB,2CACI,aAAc,IAGlB,iDACI,aAAc,IAGlB,yDACI,OAAQ,QACR,KAAM,QAGV,yDACI,OAAQ,QACR,KAAM,QAGV,wDACI,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAIxE,uCACI,OAAQ,KAIZ,eACE,OAAQ,KACR,aAAc,MAEhB,eACE,OAAQ,KACR,eAAgB,GAElB,oBACE,aAAc,EAOhB,4BACI,aAAa,EACb,aAAa,EAGjB,8BACI,aAAa,EACb,aAAa,EAGjB,qDACI,aAAa,EACb,eAAe,EAQnB,kCACI,aAAc,IAGlB,wCACI,aAAc,EAElB,8BACI,KAAM,KAGV,8BACI,OAAQ,KAGZ,oDACI,aAAc,EACd,eAAgB,EAGpB,sDACI,aAAc,aACd,eAAgB,aAIpB,6CACI,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAKxE,iCADA,4CAEI,aAAc,IACd,aAAc,cACd,eAAgB,cAIpB,2BACI,OAAQ,KACR,eAAgB,EAChB,KAAM,KACN,aAAc,EAKlB,oBACI,OAAQ,UAUZ,aAEI,oBAAqB,KAErB,gBAAiB,KACjB,iBAAkB,KAClB,YAAa,KAEb,MAAM,KACN,OAAO,KAMX,0BAA2B,2BACvB,gBAAiB,EAAE,IAAI,KAAK,eAC5B,mBAAoB,EAAE,IAAI,KAAK,eAC/B,WAAY,EAAE,IAAI,KAAK,eAEvB,sBAAuB,IACvB,mBAAoB,IACpB,cAAe,IAInB,WACI,KAAM,IAAO,KAAK,MAGtB,aACI,KAAM,IAAK,KAAK,MAGpB,qBACI,KAAM,KACN,aAAc,EAGlB,gBACI,UAAW,KACX,YAAa,IAQjB,kBACI,aAAc,KAIlB,uBACI,KAAM,KACN,OAAQ,KAQZ,4BACI,OAAQ,QAGZ,qCACI,aAAc,EAIlB,wBACI,aAAc,YAGlB,+BACI,OAAQ,KACR,aAAc,GACd,KAAM,KACN,aAAc,GAOlB,aACE,WACE,aAAc,EACd,aAAc,GAIlB,oCACI,aAAc,IAGlB,0CACI,aAAc,IAGlB,6CACI,OAAQ,QAGZ,6CACI,OAAQ,QAIZ,uBACI,KAAM,KACN,OAAQ,KACR,eAAgB,GAIpB,uBACI,KAAM,KACN,eAAgB,GAGpB,4CAEI,KAAM,KACN,aAAc,GACd,OAAQ,KACR,gBAAiB,WAGrB,qCACI,aAAc,EACjB,aAAc,IAIf,8BACE,KAAM,KACN,OAAQ,KACR,aAAc,EACd,eAAgB,EAChB,iBAAkB,EAAG,EAUvB,2BACI,UAAW,KACX,KAAM,qBAGV,4BACI,OAAQ,KACR,aAAc,EAGlB,kBAhBI,WAAY,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OACvF,gBAAiB,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5F,mBAAoB,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OAe/F,OAAQ,KACR,aAAc,IACd,eAAgB,EAIhB,aAAc,GAElB,yBACI,aAAc,EAKlB,4BACI,aAAc,EACd,eAAgB,EAIpB,iCACI,aAAc,KACd,eAAgB,GAGpB,kCACI,aAAc,EAWlB,wBACI,KAAM,KAOV,2CACI,OAAQ,KACR,aAAc,MAGlB,uBACA,yBACI,eAAgB,IA4LpB,+BAvIA,WAwII,eAAe,KA1LnB,oBACI,aAAc,EACd,eAAgB,EAGpB,kCACA,kCACI,aAAc,EACd,UAAW,KACX,YAAa,IAGjB,kCACI,OAAQ,KAGZ,oCACI,OAAQ,QACR,KAAM,QAGV,oCACI,OAAQ,QACR,KAAM,QAGV,wCACI,YAAa,IACb,UAAW,MAsEf,cAsCA,wBACI,YAAa,IA1GjB,kCACI,aAAc,GACd,eAAgB,EAChB,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAGxE,wCACI,aAAc,GAIlB,0CACI,eAAgB,EAChB,aAAc,EAIlB,WACI,SAAU,SAEV,MAAO,cACP,QAAS,IAET,QAAS,MAGT,YAAa,MACb,UAAW,KACX,WAAY,KAGZ,YAAa,OAGb,oBAAqB,KAErB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KAIb,WAAY,qBACZ,OAAQ,IAAI,MAAM,eAClB,cAAe,IAqBnB,cAgBA,aACI,OAAQ,EAER,WAAY,OAlChB,4BAA6B,6BACzB,WAAY,QAAQ,KAAK,OACzB,gBAAiB,QAAQ,KAAK,OAC9B,mBAAoB,QAAQ,KAAK,OAEjC,iBAAkB,MAClB,sBAAuB,MACvB,yBAA0B,MAG9B,uBACA,uBACI,QAAS,IAGb,cAEI,QAAS,IAAI,KACb,YAAa,KAEb,iBAAkB,sBAClB,MAAO,cAGP,cAAe,IAAI,MAAM,QAEzB,sBAAuB,IAAI,IAAI,EAAE,EACjC,mBAAoB,IAAI,IAAI,EAAE,EAC9B,cAAe,IAAI,IAAI,EAAE,EAG7B,aAEI,QAAS,IAAI,KAIjB,gBACI,QAAS,aACT,OAAQ,IAAI,EAGhB,iBACI,OAAQ,IACR,eAAe,EAInB,oBACI,QAAS,IAAI,IAAI,IAAI,EACrB,eAAgB,OAMpB,8BACI,YAAa,IAEjB,0BACI,WAAY,MACZ,YAAa,IAGjB,4BACI,MAAO,QAGX,iCACI,QAAS,IAAI,IAAI,IAAI,EACrB,oBAAqB,MACrB,oBAAqB,IACrB,iBAAkB,MAClB,iBAAkB,IAGtB,2CAGI,eAAgB,OAIhB,MAAO,KACP,OAAQ,KACR,OAAQ,IAAI,MAAM,KAGtB,mBACI,QAAS,IACT,WAAY,OAGhB,2BACI,eAAgB,KAChB,QAAS,KAUb,wBACI,OAAQ"}
{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"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"}
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -27,6 +27,8 @@ define([
this._el.addClass('log-viewer');
this.editor.setTheme('ace/theme/twilight');
this.editor.setShowPrintMargin(false);
this.editor.renderer.setScrollMargin(0, 75);
this.addKeyListeners();
// Override the textlayer to add support for ansi colors
this.customizeAce();
@@ -34,6 +36,24 @@ define([
_.extend(LogViewerWidget.prototype, TextEditorWidget.prototype);
LogViewerWidget.prototype.addKeyListeners = function() {
// Need to add key listeners to the container itself since ace is in read-only mode
this._el.on('keydown', event => {
// ctrl-alt-pagedown -> EOF
if (event.key === 'PageDown' && event.altKey && (event.ctrlKey || event.metaKey)) {
this.editor.gotoLine(Infinity);
event.stopPropagation();
event.preventDefault();
}
// ctrl-alt-pagedown -> beginning of file
if (event.key === 'PageUp' && event.altKey && (event.ctrlKey || event.metaKey)) {
this.editor.gotoLine(0);
event.stopPropagation();
event.preventDefault();
}
});
};
LogViewerWidget.prototype.getHeader = function(desc) {
return `Console logging for Operation "${desc.name}":\n`;
};
@@ -2,12 +2,14 @@
/*jshint browser: true*/
define([
'panel/FloatingActionButton/styles/Materialize',
'deepforge/globals',
'text!./NavBar.html',
'text!./ListItem.ejs',
'underscore',
'css!./styles/MainViewWidget.css'
], function (
Materialize,
DeepForge,
NavBarHTML,
ListItem,
@@ -24,12 +26,12 @@ define([
];
MainViewWidget = function (logger, container) {
this._logger = logger.fork('Widget');
this.logger = logger.fork('Widget');
this.$el = container;
this.$el.addClass(WIDGET_CLASS);
this.toggleIndex = 0;
this.initialize();
this._logger.debug('ctor finished');
this.logger.debug('ctor finished');
};
MainViewWidget.prototype.initialize = function () {
@@ -66,6 +68,51 @@ define([
this.$nav.on('click', '.dl-node', this.onDownloadNodeClick.bind(this));
this.htmlFor = {};
setTimeout(() => this.checkLibraries(), 100);
};
MainViewWidget.prototype.checkLibraries = function () {
this.checkLibUpdates()
.then(updates => {
if (updates.length) { // prompt about updates
var names = updates.map(update => update[0]),
projName = this.getProjectName(),
content = $('<span>'),
msg = `${projName} is out of date. Click to update.`;
this.logger.info(`Updates available for ${names.join(', ')}`);
if (names.indexOf('nn') !== -1) {
msg = 'Newer nn library available. Click to update';
} else if (names.indexOf('pipeline') !== -1) {
msg = 'Execution updates available. Click to update';
}
content.text(msg);
content.on('click', () => {
// Remove the toast
content.parent().fadeOut();
// Create updating notification
msg = 'Updating execution library...';
if (names.indexOf('nn') !== -1) {
msg = 'Updating nn library...';
}
content.text(msg);
Materialize.toast(content, 8000);
this.updateLibraries(updates).then(() => {
content.parent().remove();
Materialize.toast('Update complete!', 2000);
});
});
Materialize.toast(content, 8000);
}
})
.fail(err => Materialize.toast(`Library update check failed: ${err}`, 2000));
};
MainViewWidget.prototype.width = function () {
@@ -189,11 +236,11 @@ define([
};
MainViewWidget.prototype.onActivate = function () {
this._logger.debug('MainViewWidget has been activated');
this.logger.debug('MainViewWidget has been activated');
};
MainViewWidget.prototype.onDeactivate = function () {
this._logger.debug('MainViewWidget has been deactivated');
this.logger.debug('MainViewWidget has been deactivated');
};
return MainViewWidget;
@@ -17,6 +17,15 @@ define([
OperationCodeEditorWidget = function (logger, container) {
TextEditorWidget.call(this, logger, container);
this.lineOffset = 0;
// Add the shift-enter command
this.editor.commands.addCommand({
name: 'executeOrStopJob',
bindKey: {
mac: 'Shift-Enter',
win: 'Shift-Enter'
},
exec: () => this.executeOrStopJob()
});
};
_.extend(OperationCodeEditorWidget.prototype, TextEditorWidget.prototype);
@@ -25,7 +34,6 @@ define([
// 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}" Implementation`
];
@@ -41,22 +49,28 @@ define([
header.push('--');
header.push('-- The following will be executed when the operation is run:');
// Add info about outputs
outputs = desc.outputs.map(pair => `-- ${pair[0]} = <${pair[1]}>`)
.join('\n');
if (outputs.length) {
header.push('-- Returning something like:');
header.push('-- {');
header.push(outputs);
header.push('-- }');
}
return header.join('\n');
};
OperationCodeEditorWidget.prototype.addNode = function () {
TextEditorWidget.prototype.addNode.apply(this, arguments);
OperationCodeEditorWidget.prototype.canAddReturnTmpl = function (desc) {
return desc.outputs.length &&
(!desc.ownText || desc.ownText.indexOf('return') === -1);
};
OperationCodeEditorWidget.prototype.updateText = function (desc) {
if (this.canAddReturnTmpl(desc)) {
// Add the return template
desc.text += '\n\nreturn {\n' +
desc.outputs.map((pair, i) =>
` ${pair[0]} = nil${i === desc.outputs.length-1 ? '' : ','} -- ${pair[1]}`).join('\n') +
'\n}';
}
};
OperationCodeEditorWidget.prototype.addNode = function (desc) {
this.updateText(desc);
TextEditorWidget.prototype.addNode.call(this, desc);
this.updateOffset();
};
@@ -1,4 +1,4 @@
/*globals define */
/*globals define*/
define([
'widgets/EasyDAG/DAGItem',
'underscore'
@@ -13,6 +13,7 @@ define([
// Show the warnings
this.$warning = null;
this.updateWarnings();
};
_.extend(Item.prototype, DAGItem.prototype);
@@ -29,38 +30,55 @@ define([
if (this.desc.used === false) {
this.warn(msg, isInput ? 'bottom' : 'top');
} else {
this.clearWarning();
this.clearNotification('$warning');
}
if (this.desc.isUnknown) { // ptrs only
this.error('Unknown type! Click to set', 'bottom');
} else if (this.$error) {
// Set the baseName tooltip, if needed
this.clearNotification('$error');
this.decorator.enableTooltip(this.desc.baseName, 'dark');
}
};
Item.prototype.warn = function(message, tipJoint) {
// Create a temporary div over the given svg element
if (this.$warning) {
this.clearWarning();
}
this.notify(message, '$warning', '#ffeb3b', 'standard', tipJoint);
};
this.decorator.highlight('#ffeb3b');
this.$warning = this.createTooltip(message, {
Item.prototype.error = function(message, tipJoint) {
this.notify(message, '$error', '#ef5350', 'alert', tipJoint);
};
Item.prototype.notify = function(message, varname, color, style, tipJoint) {
this.clearNotification(varname);
this.decorator.highlight(color);
this[varname] = this.createTooltip(message, {
showIf: () => !this.isSelected(),
tipJoint: tipJoint,
style: 'standard'
style: style
});
};
Item.prototype.clearWarning = function() {
if (this.$warning) {
this.destroyTooltip(this.$warning);
this.$warning = null;
Item.prototype.clearNotification = function(varname) {
if (this[varname]) {
this.destroyTooltip(this[varname]);
this[varname] = null;
}
this.decorator.unHighlight();
};
Item.prototype.onSelect = function() {
DAGItem.prototype.onSelect.call(this);
if (this.$warning) {
this.$warning.hide();
}
// Add click listener to set type
if (this.desc.isUnknown) {
this.onSetRefClicked(this.desc.name);
}
};
Item.prototype.setupDecoratorCallbacks = function() {
@@ -37,7 +37,7 @@ define([
EasyDAG.prototype.setupItemCallbacks.call(this);
// Add ptr rename callback
this.ItemClass.prototype.changePtrName = (from, to) => this.changePtrName(from, to);
this.ItemClass.prototype.onSetRefClicked = OperationInterfaceEditorWidget.prototype.onSetRefClicked.bind(this);
};
OperationInterfaceEditorWidget.prototype.onAddItemSelected = function(selected, isInput) {
@@ -77,6 +77,25 @@ define([
this.active = true; // keep refreshing the screen -> it is always visible
};
OperationInterfaceEditorWidget.prototype.onSetRefClicked = function(name) {
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.setRefType(name, selected.node.id);
}
};
} else if (refs[0]) {
this.setRefType(name, refs[0].node.id);
}
};
OperationInterfaceEditorWidget.prototype.onAddRefClicked = function() {
var refs = this.allValidReferences();
@@ -2,6 +2,7 @@
/*jshint browser: true*/
define([
'deepforge/Constants',
'widgets/EasyDAG/AddNodeDialog',
'widgets/EasyDAG/EasyDAGWidget',
'deepforge/viz/PipelineControl',
@@ -13,6 +14,7 @@ define([
'underscore',
'css!./styles/PipelineEditorWidget.css'
], function (
CONSTANTS,
AddNodeDialog,
EasyDAGWidget,
PipelineControl,
@@ -32,8 +34,7 @@ define([
STATE = {
DEFAULT: 'default',
CONNECTING: 'connecting'
},
UPLOAD_ARTIFACT_ID = '__UPLOAD_ARTIFACT__';
};
PipelineEditorWidget = function (logger, container, execCntr) {
EasyDAGWidget.call(this, logger, container);
@@ -44,6 +45,7 @@ define([
this._connForPort = {};
this._itemsShowingPorts = [];
this.updateExecutions = _.debounce(this._updateExecutions, 50);
this.initExecs(execCntr);
};
@@ -283,7 +285,7 @@ define([
this.updateExecutions();
};
PipelineEditorWidget.prototype.updateExecutions = function() {
PipelineEditorWidget.prototype._updateExecutions = function() {
var keys = Object.keys(this.executions),
hasExecutions = !!keys.length,
msg = `${keys.length || 'No'} Associated Execution` +
@@ -325,7 +327,7 @@ define([
() => WebGMEGlobal.State.registerActiveObject(exec.id));
// Add the remove icon
rmIcon.on('click', () => this.deleteNode(exec.id));
rmIcon.on('click', () => this.deleteExecution(exec.id));
row.append(title, timestamp, rmIcon);
row[0].className = className;
return row;
@@ -338,36 +340,55 @@ define([
////////////////////////// Action Overrides //////////////////////////
PipelineEditorWidget.prototype.selectTargetFor = function(itemId) {
// If it is an 'ArtifactLoader', then we will need to add 'upload artifact'
// If it is an input operation, then we will need to add 'upload artifact'
// options
if (this.items[itemId].desc.baseName === 'ArtifactLoader') {
this.selectTargetForLoader.apply(this, arguments);
if (this.items[itemId].desc.baseName === CONSTANTS.OP.INPUT) {
return this.selectTargetForLoader.apply(this, arguments);
} else if (this.isArchitecturePtr.apply(this, arguments)) {
// Create new architecture from the "set ptr" dialog
return this.selectArchitectureTarget.apply(this, arguments);
} else {
return EasyDAGWidget.prototype.selectTargetFor.apply(this, arguments);
}
};
PipelineEditorWidget.prototype.selectTargetForLoader = function(itemId, ptr, filter) {
var validTargets = this.getValidTargetsFor(itemId, ptr, filter),
nodeId = validTargets.length ? validTargets[0].node.id : null,
uploadNode;
PipelineEditorWidget.prototype.addCreationNode = function(name, targets) {
var nodeId = targets.length ? targets[0].node.id : null,
creationNode;
// Add the 'Upload Artifact' option
uploadNode = {
creationNode = {
node: {
id: UPLOAD_ARTIFACT_ID,
name: 'Upload Artifact',
id: `creation-node-${name}`,
name: name,
class: 'create-node',
attributes: {},
Decorator: this.getDecorator(nodeId)
}
};
validTargets.push(uploadNode);
targets.push(creationNode);
return creationNode.node.id;
};
PipelineEditorWidget.prototype.selectArchitectureTarget = function(itemId, ptr, filter) {
return this.selectTargetWithCreationNode('New Architecture',
DeepForge.create.Architecture, itemId, ptr, filter);
};
PipelineEditorWidget.prototype.selectTargetForLoader = function(itemId, ptr, filter) {
return this.selectTargetWithCreationNode('Upload Artifact',
DeepForge.create.Artifact, itemId, ptr, filter);
};
PipelineEditorWidget.prototype.selectTargetWithCreationNode = function(name, fn, itemId, ptr, filter) {
var validTargets = this.getValidTargetsFor(itemId, ptr, filter),
creationNodeId = this.addCreationNode(name, validTargets);
// Add the 'Upload Artifact' option
AddNodeDialog.prompt(validTargets)
.then(selected => {
if (selected.node.id === UPLOAD_ARTIFACT_ID) {
DeepForge.create.Artifact();
if (selected.node.id === creationNodeId) {
fn();
} else {
var item = this.items[itemId];
if (item.decorator.savePointer) {
@@ -44,7 +44,7 @@ define([
this.deletePipeline(id);
});
this.$el.on('dblclick', '.pipeline-name', event => {
this.$el.on('click', '.pipeline-name', event => {
var html = $(event.target),
id = html.data('id');
@@ -34,9 +34,11 @@ define([
this.editor.$blockScrolling = Infinity;
this.DELAY = 750;
this.silent = false;
this.saving = false;
this.editor.on('change', () => {
if (!this.silent) {
this.saving = true;
this.onChange();
}
});
@@ -107,11 +109,13 @@ define([
TextEditorWidget.prototype.saveText = function () {
var text;
this.saving = false;
if (this.readOnly) {
return;
}
text = this.editor.getValue().replace(this.currentHeader + '\n', '');
text = this.editor.getValue()
.replace(this.currentHeader + '\n', '');
if (typeof this.activeNode === 'string') {
this.saveTextFor(this.activeNode, text);
} else {
@@ -127,20 +131,17 @@ define([
};
TextEditorWidget.prototype.updateNode = function (desc) {
var shouldUpdate = this.readOnly ||
(!this.saving && !this.editor.isFocused()) ||
(this.activeNode === desc.id && this.getHeader(desc) !== this.currentHeader);
// Check for header changes
if (this.readOnly) {
this.addNode(desc);
} else if (this.activeNode === desc.id &&
this.getHeader(desc) !== this.currentHeader) {
if (shouldUpdate) {
this.addNode(desc);
}
// TODO: Handle concurrent editing... Currently, last save wins and there are no
// updates after opening the node. Supporting multiple users editing the same
// operation/layer is important but more work than it is worth for now
//var currentText = this.editor.getValue().replace(this.currentHeader, '');
//if (this.activeNode === desc.id && desc.text !== currentText) {
//this.addNode(desc);
//}
};
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
@@ -1,6 +1,7 @@
{
"deepforge": [
"Graph",
"initialize",
"image"
],
"torch": [
+38 -28
Ver Arquivo
@@ -12,8 +12,7 @@ var callRegister = {
var mocks = {
childProcess: {},
rimraf: {},
forever: {}
rimraf: {}
};
var childProcess = {
@@ -23,6 +22,14 @@ var childProcess = {
return mocks.childProcess.execSync.apply(this, arguments);
}
},
spawnSync: function(cmd) {
if (cmd === 'luarocks') {
return {
stdout: 'rnn'
};
}
return {};
},
spawn: function() {
if (mocks.childProcess.spawn) {
mocks.childProcess.spawn.apply(this, arguments);
@@ -38,16 +45,6 @@ var childProcess = {
};
}
};
var forever = {};
forever.Monitor = function() {
var res = {};
res.on = nop;
res.start = nop;
if (mocks.forever.Monitor) {
mocks.forever.Monitor.apply(this, arguments);
}
return res;
};
var rimraf = {};
rimraf.sync = function() {
if (mocks.rimraf.sync) {
@@ -63,8 +60,9 @@ describe('cli', function() {
warnOnUnregistered: false
});
mockery.registerMock('child_process', childProcess);
mockery.registerMock('forever-monitor', forever);
mockery.registerMock('rimraf', rimraf);
// Clear node's cache
delete require.cache[require.resolve('../../bin/deepforge')];
cli = require('../../bin/deepforge');
});
@@ -75,10 +73,11 @@ describe('cli', function() {
describe('start', function() {
afterEach(function() {
callRegister.childProcess.execSync = [];
mocks.childProcess.execSync = nop;
mocks.childProcess.spawn = nop;
mocks.forever.Monitor = nop;
mocks.childProcess.execSync = () => '123';
mocks.rimraf.sync = nop;
delete require.cache[require.resolve('../../bin/deepforge')];
cli = require('../../bin/deepforge');
});
it('should check for running mongo', function() {
@@ -113,21 +112,29 @@ describe('cli', function() {
cli('start --mongo');
});
it('should start local deepforge by default', function() {
mocks.forever.Monitor = main =>
assert.notEqual(main.indexOf('start-local.js'), -1);
it('should start local deepforge by default', function(done) {
mocks.childProcess.spawn = (main, args) => {
if (main === 'node') {
assert.notEqual(args[0].indexOf('start-local.js'), -1);
done();
}
};
cli('start');
});
it('should start normal deepforge if --server set', function() {
mocks.forever.Monitor = main =>
assert.notEqual(main.indexOf('app.js'), -1);
it('should start normal deepforge if --server set', function(done) {
mocks.childProcess.spawn = (main, args) => {
if (main === 'node') {
assert.notEqual(args[0].indexOf('app.js'), -1);
done();
}
};
cli('start --server');
});
it('should start worker if --worker set', function(done) {
mocks.forever.Monitor = main => {
if (main.indexOf('start-worker.js') !== -1) {
mocks.childProcess.spawn = (main, args) => {
if (args[0].indexOf('start-worker.js') !== -1) {
done();
}
};
@@ -163,17 +170,20 @@ describe('cli', function() {
describe('update', function() {
it('should update deepforge w/ npm', function() {
mocks.childProcess.spawn = (cmd, args) => {
assert.equal(cmd, 'npm');
assert.equal(args[0], 'install');
assert.notEqual(args.indexOf('deepforge'), -1);
assert.notEqual(args.indexOf('-g'), -1);
if (cmd === 'npm') {
assert.equal(args[0], 'install');
assert.notEqual(args.indexOf('deepforge'), -1);
assert.notEqual(args.indexOf('-g'), -1);
}
};
cli('update');
});
it('should update deepforge from git if --git set w/ npm', function() {
mocks.childProcess.spawn = (cmd, args) => {
assert.notEqual(args.indexOf('dfst/deepforge'), -1);
if (cmd === 'npm') {
assert.notEqual(args.indexOf('dfst/deepforge'), -1);
}
};
cli('update --git');
});
+138
Ver Arquivo
@@ -0,0 +1,138 @@
var testFixture = require('../globals'),
expect = testFixture.expect,
assert = require('assert'),
path = testFixture.path,
gmeConfig = testFixture.getGmeConfig(),
blobDir = gmeConfig.blob.fsDir,
server = testFixture.WebGME.standaloneServer(gmeConfig),
Logger = require('webgme/src/server/logger'),
logger = Logger.createWithGmeConfig('gme', gmeConfig, true),
JobLogsClient = testFixture.requirejs('deepforge/JobLogsClient'),
rm_rf = require('rimraf'),
exists = require('exists-file');
describe('JobLogsClient', function() {
var logClient = new JobLogsClient({
logger: logger,
origin: server.getUrl(),
projectId: 'testProject',
branchName: 'master'
}),
jobId = '/4/q/l',
firstLog = 'hello world';
before(function(done) {
testFixture.mkdir(blobDir);
server.start(done);
});
after(function(done) {
rm_rf.sync(blobDir);
server.stop(done);
});
describe('appendTo', function() {
before(function(done) {
logClient.appendTo(jobId, firstLog)
.then(() => done())
.catch(err => done(err));
});
it('should create job-logs directory', function() {
assert(exists.sync(path.join(blobDir, 'log-storage')));
});
describe('getLog', function() {
it('should return the logs from the job', function(done) {
logClient.getLog(jobId).then(log => {
expect(log).to.contain(firstLog);
done();
});
});
it('should append additional logs to the file', function(done) {
var secondLog = 'goodbye world';
logClient.appendTo(jobId, secondLog)
.then(() => logClient.getLog(jobId))
.then(log => {
expect(log).to.contain(secondLog);
done();
});
});
});
});
describe('delete', function() {
var delJobId = '/4/8/l';
before(function(done) {
logClient.appendTo(delJobId, firstLog).then(() => done());
});
it('should delete the file from job-logs directory', function(done) {
logClient.deleteLog(delJobId)
.then(() => logClient.getLog(delJobId))
.then(log => {
expect(log).to.equal('');
done();
});
});
});
describe('migration', function() {
var client,
jId = '/asd/4/q',
logs = 'asdfasde',
newBranch = 'otherBranch';
before(function(done) {
client = new JobLogsClient({
logger: logger,
origin: server.getUrl(),
projectId: 'migTest',
branchName: 'master'
});
// Write logs to job
client.appendTo(jId, logs)
.then(() => client.fork(newBranch))
.catch(err => done(err))
.then(() => done());
});
it('should migrate the edited nodes to the new branch', function(done) {
client.getLog(jId).then(log => {
expect(log).to.equal(logs);
done();
});
});
describe('new logs', function() {
it('should not edit old job logs', function() {
var c2 = new JobLogsClient({
logger: logger,
origin: server.getUrl(),
projectId: 'migTest',
branchName: 'master'
});
c2.getLog(jId).then(log => {
expect(log).to.equal(logs);
done();
});
});
it('should write new logs', function() {
client.appendTo(jId, 'moreStuff')
.then(() => client.getLog(jId))
.then(log => {
expect(log).to.contain('moreStuff');
done();
});
});
});
// TODO: Test that, on a fork, the logClient will copy all the current jobs to
// the new fork name
});
});
+17
Ver Arquivo
@@ -7,6 +7,9 @@
'use strict';
var testFixture = require('webgme/test/_globals'),
path = require('path'),
fs = require('fs'),
exists = require('exists-file'),
WEBGME_CONFIG_PATH = '../config';
// This flag will make sure the config.test.js is being used
@@ -34,4 +37,18 @@ testFixture.requirejs.config({
testFixture.getGmeConfig = getGmeConfig;
testFixture.DF_SEED_DIR = testFixture.path.join(__dirname, '..', 'src', 'seeds');
testFixture.mkdir = function(dir) {
var dirs = path.resolve(dir).split(path.sep),
shortDir,
i = 1;
while (i++ < dirs.length) {
shortDir = dirs.slice(0,i).join(path.sep);
if (!exists.sync(shortDir)) {
fs.mkdirSync(shortDir);
}
}
};
module.exports = testFixture;
@@ -0,0 +1,79 @@
/*jshint node:true, mocha:true*/
/**
* Generated by PluginGenerator 1.7.0 from webgme on Tue Aug 23 2016 11:02:08 GMT-0500 (CDT).
*/
'use strict';
var testFixture = require('../../globals');
describe('CheckLibraries', function () {
var gmeConfig = testFixture.getGmeConfig(),
expect = testFixture.expect,
logger = testFixture.logger.fork('CheckLibraries'),
PluginCliManager = testFixture.WebGME.PluginCliManager,
projectName = 'testProject',
pluginName = 'CheckLibraries',
project,
gmeAuth,
storage,
commitHash;
before(function (done) {
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
.then(function (gmeAuth_) {
gmeAuth = gmeAuth_;
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
return storage.openDatabase();
})
.then(function () {
var importParam = {
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
projectName: projectName,
branchName: 'master',
logger: logger,
gmeConfig: gmeConfig
};
return testFixture.importProject(storage, importParam);
})
.then(function (importResult) {
project = importResult.project;
commitHash = importResult.commitHash;
return project.createBranch('test', commitHash);
})
.nodeify(done);
});
after(function (done) {
storage.closeDatabase()
.then(function () {
return gmeAuth.unload();
})
.nodeify(done);
});
it('should not edit the model', function (done) {
var manager = new PluginCliManager(null, logger, gmeConfig),
pluginConfig = {
},
context = {
project: project,
commitHash: commitHash,
branchName: 'test',
activeNode: '/1'
};
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
expect(err).to.equal(null);
expect(typeof pluginResult).to.equal('object');
expect(pluginResult.success).to.equal(true);
project.getBranchHash('test')
.then(function (branchHash) {
expect(branchHash).to.equal(commitHash);
})
.nodeify(done);
});
});
});
+285 -4
Ver Arquivo
@@ -10,12 +10,14 @@ describe('ExecuteJob', function () {
PluginCliManager = testFixture.WebGME.PluginCliManager,
projectName = 'testProject',
pluginName = 'ExecuteJob',
manager = new PluginCliManager(null, logger, gmeConfig),
project,
gmeAuth,
storage,
commitHash;
before(function (done) {
this.timeout(10000);
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
.then(function (gmeAuth_) {
gmeAuth = gmeAuth_;
@@ -25,7 +27,7 @@ describe('ExecuteJob', function () {
})
.then(function () {
var importParam = {
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
projectSeed: testFixture.path.join(testFixture.DF_SEED_DIR, 'devProject', 'devProject.webgmex'),
projectName: projectName,
branchName: 'master',
logger: logger,
@@ -51,9 +53,7 @@ describe('ExecuteJob', function () {
});
it('should verify activeNode is "Job"', function (done) {
var manager = new PluginCliManager(null, logger, gmeConfig),
pluginConfig = {
},
var pluginConfig = {},
context = {
project: project,
commitHash: commitHash,
@@ -68,4 +68,285 @@ describe('ExecuteJob', function () {
done();
});
});
////////// Helper Functions //////////
var plugin,
node,
preparePlugin = function(done) {
var context = {
project: project,
commitHash: commitHash,
branchName: 'test',
activeNode: '/K/R/p' // hello world job
};
return manager.initializePlugin(pluginName)
.then(plugin_ => {
plugin = plugin_;
return manager.configurePlugin(plugin, {}, context);
})
.then(() => node = plugin.activeNode)
.nodeify(done);
};
////////// END Helper Functions //////////
// Race condition checks w/ saving...
describe('get/set', function() {
beforeEach(preparePlugin);
it('should get correct attribute after set', function() {
plugin.setAttribute(node, 'status', 'queued');
var attrValue = plugin.getAttribute(node, 'status');
expect(attrValue).to.equal('queued');
});
it('should get correct attribute before updating nodes', function(done) {
// Run setAttribute on some node
plugin.setAttribute(node, 'status', 'queued');
// Check that the value is correct before applying node changes
var updateNodes = plugin.updateNodes;
plugin.updateNodes = function() {
var attrValue = plugin.getAttribute(node, 'status');
expect(attrValue).to.equal('queued');
return updateNodes.apply(this, arguments);
};
plugin.save().nodeify(done);
});
it('should get correct attribute (from new node) before updating nodes', function(done) {
// Run setAttribute on some node
var graphTmp = plugin.createNode('pipeline.Graph', node),
newVal = 'testGraph',
id = 'testId';
// Get the
plugin.setAttribute(graphTmp, 'name', newVal);
plugin._metadata[id] = graphTmp;
plugin.createIdToMetadataId[graphTmp] = id;
// Check that the value is correct before applying node changes
var updateNodes = plugin.updateNodes;
plugin.updateNodes = function() {
var graph = plugin._metadata[id],
attrValue = plugin.getAttribute(graph, 'name');
expect(attrValue).to.equal(newVal);
return updateNodes.apply(this, arguments);
};
plugin.save().nodeify(done);
});
it('should get correct attribute after save', function(done) {
// Run setAttribute on some node
plugin.setAttribute(node, 'status', 'queued');
// Check that the value is correct before applying node changes
plugin.save()
.then(() => {
var attrValue = plugin.getAttribute(node, 'status');
expect(attrValue).to.equal('queued');
})
.nodeify(done);
});
it('should get correct attribute while applying node changes', function(done) {
// Run setAttribute on some node
plugin.setAttribute(node, 'status', 'queued');
// Check that the value is correct before applying node changes
var oldApplyChanges = plugin._applyNodeChanges;
plugin._applyNodeChanges = function() {
var attrValue = plugin.getAttribute(node, 'status');
expect(attrValue).to.equal('queued');
return oldApplyChanges.apply(this, arguments);
};
plugin.save().nodeify(done);
});
});
describe('createNode', function() {
beforeEach(preparePlugin);
it('should update _metadata after applying changes', function(done) {
// Run setAttribute on some node
var graphTmp = plugin.createNode('pipeline.Graph', node),
id = 'testId';
plugin._metadata[id] = graphTmp;
plugin.createIdToMetadataId[graphTmp] = id;
// Check that the value is correct before applying node changes
var applyModelChanges = plugin.applyModelChanges;
plugin.applyModelChanges = function() {
return applyModelChanges.apply(this, arguments)
.then(() => {
var graph = plugin._metadata[id];
expect(graph).to.not.equal(graphTmp);
});
};
plugin.save().nodeify(done);
});
it('should update _metadata in updateNodes', function(done) {
var id = 'testId';
plugin._metadata[id] = node;
node.old = true;
plugin.updateNodes()
.then(() => {
var graph = plugin._metadata[id];
expect(graph.old).to.not.equal(true);
})
.nodeify(done);
});
// Check that it gets the correct value from a newly created node after
// it has been saved/created
it('should get changed attribute', function(done) {
// Run setAttribute on some node
var graphTmp = plugin.createNode('pipeline.Graph', node),
id = 'testId';
plugin._metadata[id] = node;
plugin.createIdToMetadataId[graphTmp] = id;
plugin.setAttribute(graphTmp, 'name', 'firstName');
// Check that the value is correct before applying node changes
plugin.save()
.then(() => {
var graph = plugin._metadata[id],
val = plugin.getAttribute(graph, 'name');
expect(val).to.equal('firstName');
})
.nodeify(done);
});
it('should get inherited attribute', function(done) {
// Run setAttribute on some node
var graphTmp = plugin.createNode('pipeline.Graph', node),
id = 'testId',
val;
// Check that the value is correct before applying node changes
plugin._metadata[id] = node;
plugin.createIdToMetadataId[graphTmp] = id;
val = plugin.getAttribute(graphTmp, 'name');
expect(val).to.equal('Graph');
plugin.save()
.then(() => {
var graph = plugin._metadata[id];
val = plugin.getAttribute(graph, 'name');
expect(val).to.equal('Graph');
})
.nodeify(done);
});
});
// Canceling
describe('cancel', function() {
beforeEach(preparePlugin);
it('should stop the job if the execution is canceled', function(done) {
var job = node,
hash = 'abc123',
exec = {
cancelJob: jobHash => expect(jobHash).equal(hash)
};
plugin.setAttribute(node, 'secret', 'abc');
plugin.isExecutionCanceled = () => true;
plugin.onOperationCanceled = () => done();
plugin.watchOperation(exec, hash, job, job);
});
it('should stop the job if a job is canceled', function(done) {
var job = node,
hash = 'abc123',
exec = {
cancelJob: jobHash => expect(jobHash).equal(hash)
};
plugin.setAttribute(job, 'secret', 'abc');
plugin.canceled = true;
plugin.onOperationCanceled = () => done();
plugin.watchOperation(exec, hash, job, job);
});
it('should set exec to running', function(done) {
var job = node,
execNode = plugin.core.getParent(job);
// Set the execution to canceled
plugin.setAttribute(execNode, 'status', 'canceled');
plugin.prepare = () => {
var status = plugin.getAttribute(execNode, 'status');
expect(status).to.not.equal('canceled');
return {then: () => done()};
};
plugin.main();
});
});
describe('exec files', function() {
describe('attribute file', function() {
var boolString = /['"](true|false)['"]/g;
beforeEach(preparePlugin);
it('should not quote true (s) boolean values', function() {
var files = {},
content,
matches;
plugin.setAttribute(node, 'debug', 'true');
plugin.createAttributeFile(node, files);
content = files['attributes.lua'];
matches = content.match(boolString);
expect(matches).to.equal(null);
});
it('should not quote true boolean values', function() {
var files = {},
content,
matches;
plugin.setAttribute(node, 'debug', true);
plugin.createAttributeFile(node, files);
content = files['attributes.lua'];
matches = content.match(boolString);
expect(matches).to.equal(null);
});
it('should not quote false (s) boolean values', function() {
var files = {},
content,
matches;
plugin.setAttribute(node, 'debug', 'false');
plugin.createAttributeFile(node, files);
content = files['attributes.lua'];
matches = content.match(boolString);
expect(matches).to.equal(null);
});
it('should not quote false boolean values', function() {
var files = {},
content,
matches;
plugin.setAttribute(node, 'debug', false);
plugin.createAttributeFile(node, files);
content = files['attributes.lua'];
matches = content.match(boolString);
expect(matches).to.equal(null);
});
});
});
});
@@ -89,6 +89,7 @@ describe('GenerateArchitecture', function () {
//['/o', 'basic.lua'],
//['/8', 'basic-transfers.lua'],
//['/M', 'concat-parallel.lua'],
['/4', 'requiredOmitted.lua'],
['/e', 'googlenet.lua'],
['/X', 'overfeat.lua']
];
+1 -1
Ver Arquivo
@@ -14,7 +14,7 @@ var testFixture = require('../../globals'),
];
describe('ImportTorch', function () {
this.timeout(5000);
this.timeout(7500);
var gmeConfig = testFixture.getGmeConfig(),
Q = testFixture.Q,
GraphChecker = testFixture.requirejs('deepforge/GraphChecker'),
@@ -0,0 +1,76 @@
/*jshint node:true, mocha:true*/
'use strict';
var testFixture = require('../../globals');
describe.skip('UpdateLibrarySeed', function () {
var gmeConfig = testFixture.getGmeConfig(),
expect = testFixture.expect,
logger = testFixture.logger.fork('UpdateLibrarySeed'),
PluginCliManager = testFixture.WebGME.PluginCliManager,
projectName = 'testProject',
pluginName = 'UpdateLibrarySeed',
project,
gmeAuth,
storage,
commitHash;
before(function (done) {
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
.then(function (gmeAuth_) {
gmeAuth = gmeAuth_;
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
return storage.openDatabase();
})
.then(function () {
var importParam = {
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
projectName: projectName,
branchName: 'master',
logger: logger,
gmeConfig: gmeConfig
};
return testFixture.importProject(storage, importParam);
})
.then(function (importResult) {
project = importResult.project;
commitHash = importResult.commitHash;
return project.createBranch('test', commitHash);
})
.nodeify(done);
});
after(function (done) {
storage.closeDatabase()
.then(function () {
return gmeAuth.unload();
})
.nodeify(done);
});
it('should run plugin and update the branch', function (done) {
var manager = new PluginCliManager(null, logger, gmeConfig),
pluginConfig = {
},
context = {
project: project,
commitHash: commitHash,
branchName: 'test',
activeNode: '/1'
};
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
expect(err).to.equal(null);
expect(typeof pluginResult).to.equal('object');
expect(pluginResult.success).to.equal(true);
project.getBranchHash('test')
.then(function (branchHash) {
expect(branchHash).to.not.equal(commitHash);
})
.nodeify(done);
});
});
});

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais