Comparar commits

..

74 Commits

Autor SHA1 Mensagem Data
Brian Broll 5135ccef09 v0.9.0 2016-07-18 08:39:49 -05:00
Brian Broll 6314e00a8d Fixed the attribute shown in deserialize viz. Fixes #512 (#517) 2016-07-17 21:10:22 -05:00
Brian Broll 779429e24d Fixed obj changed pass thru in main view. Fixes #513 (#514) 2016-07-17 20:34:15 -05:00
Brian Broll a7f4eac09d Updated arch editor tooltip init. Fixes #515 (#516) 2016-07-17 20:34:01 -05:00
Brian Broll 7c645e9b23 Added unused op input warning. Fixes #499 (#511)
WIP #499 Added unused input detection

WIP #499. Added input highlight updating on code change

WIP #499 Added warning tooltip and fixed removal

WIP #499 Fixed warning location on position change

WIP #499 Removed unnecessary timeout

WIP #499 Added sophisticated usage checking

WIP #499 Removed code climate issues
2016-07-16 22:42:14 -05:00
Brian Broll fc3e14644f Updated the selObjChanged to update pipeline list. Fixes #507 (#508)
WIP #507 set webgme-autoviz to track master
2016-07-16 15:37:59 -05:00
Brian Broll fd48c1b480 Removed panel padding. Fixes #502 (#506)
WIP #502 Removed padding from the tiling viz's panel
2016-07-16 14:14:11 -05:00
Brian Broll 8928d0f105 Removed old 'code' attr. Fixes #93 (#505) 2016-07-16 13:53:11 -05:00
Brian Broll 6857da5ac7 Updated webgme-autoviz. Fixes #503 (#504) 2016-07-16 13:40:01 -05:00
Brian Broll fee584cfde Added lenet arch to cifar10 example. Fixes #66 (#501) 2016-07-15 20:13:24 -05:00
Brian Broll 45fcd81739 Added tracking EOF for log viewer. Fixes #304 (#500)
WIP #304 Added scroll to bottom

WIP #304 Added eof detection
2016-07-15 17:48:14 -05:00
Brian Broll d831f5e032 Added ubuntu support to install script. Fixes #395 (#498)
WIP #395 Added ubuntu/arch detection

WIP #395 added manual nvm loading

WIP #395 Added source post-installation instructions

WIP #395 Added ubuntu/arch detection
2016-07-15 16:06:18 -05:00
Brian Broll 65e938f489 Created better execution fork names. Fixes #494 (#496)
Improved execution fork name. Fixes #494
2016-07-15 10:25:33 -05:00
Brian Broll b9b5cea5a1 Added exec fork notification. Fixes #345 (#495) 2016-07-15 10:08:26 -05:00
Brian Broll 6c639376d1 Added attributes to condense for width calc. Fixes #492 (#493) 2016-07-15 09:27:03 -05:00
Brian Broll 58ed3048f8 Updated OperationDecorator transitions. Fixes #490 (#491) 2016-07-15 07:41:00 -05:00
Brian Broll f64492061d Added operation attribute support. Fixes #487 (#489)
WIP #487 Added attr edit/del fn-ality

WIP #487 Added attribute creation

WIP #487 Fixed invalid name list

WIP #487 Fixed code climate issue

WIP #487 Fixed operation only behavoirs

WIP #487 Removed 'code' attribute and added number check

WIP #487 Added scientific notation detection

WIP #487 Updated seeds
2016-07-14 12:19:04 -05:00
Brian Broll 552e71687d Added editors to preload by autoviz. Fixes #479 (#486)
WIP #479 Updated autoviz version
2016-07-13 09:37:29 -05:00
Brian Broll 448de23945 Check if instance exists before invoking ser method. Fixes #484 (#485) 2016-07-11 13:53:25 -05:00
Brian Broll dbd00e5946 Added filter for 'return to' action btns. Fixes #482 (#483) 2016-07-11 13:38:38 -05:00
Brian Broll 4d0b4ae017 Added primitive renaming support (by editing comment). Fixes #444 (#480)
WIP #444 Naming support for SerializeEditor

WIP #444 Added renaming functionality for the deserialize editor

WIP #444 Fixed code climate issues
2016-07-11 13:03:20 -05:00
Brian Broll d6c201cce6 Retrieve the deser fn from source node. Fixes #245 (#478) 2016-07-11 12:12:08 -05:00
Brian Broll b8bc3af524 Escaped quoted operation name in log. Fixes #470 (#475) 2016-07-11 11:48:54 -05:00
Brian Broll 72de1d44da Set inputs/outputs for all nodes in pipeline editor. Fixes #411 (#473) 2016-07-11 10:51:02 -05:00
Brian Broll da6f186b52 Added string, boolean types. Fixes #471 (#474) 2016-07-11 10:50:57 -05:00
Brian Broll 5f1c50beb6 Removed territory on text editor destory. Fixes #409 (#472) 2016-07-11 10:50:52 -05:00
Brian Broll 3a79afbc41 v0.8.0 2016-07-11 10:30:22 -05:00
Brian Broll ba210e4b27 Updated icons. Fixes #406 (#469)
WIP #406 Updated some icons

WIP #406 Updated the terminal icon

WIP #406 Updated operation interface icons

WIP #406 terminal -> monitor icon

WIP #406 Fixed code climate issue
2016-07-09 17:15:44 -05:00
Brian Broll bdb21a5262 Set title to regular case. Fixes #467 (#468) 2016-07-09 16:05:30 -05:00
Brian Broll 4b6471efbc Updated buttons and methods for webgme-easydag update. Fixes #465 (#466)
WIP #465 Updated onAddButtonClicked

WIP #465 Updated callbacks for webgme-easydag update

WIP #465 Fixing code climate issue
2016-07-09 15:42:04 -05:00
JimnyCricket beeb1deb3c Merge pull request #457 from dfst/456-simple-cifar
Split cifar10 example into 4 pipelines. Fixes #456
2016-07-08 17:37:19 -05:00
Brian Broll 0bc6846c32 Optimized the arch editor layer selection. Fixes #78 (#463)
WIP #78 ~3x speedup in arch editor

WIP #78 Removed unused var
2016-07-08 10:00:47 -06:00
Brian Broll 8a40cb95fb Updated and configured breadcrumbheader. Fixes #441 (#462) 2016-07-08 07:29:45 -06:00
Brian Broll 92ea4b2ff5 Removed ptrs from op desc in OpIntEditor. Fixes #433 (#461) 2016-07-07 17:48:56 -06:00
Brian Broll e0a83b4d6c Added 'print', 'SGD' ops. Fixes #368 (#460) 2016-07-07 17:41:58 -06:00
Brian Broll 49268b9554 Fixed arch update on main screen. Fixes #458 (#459) 2016-07-07 17:41:51 -06:00
Brian Broll 65164bcb76 Merge branch 'master' into 456-simple-cifar 2016-07-07 17:31:43 -05:00
Brian Broll 1afcaf9238 Split cifar10 example into 4 pipelines. Fixes #456 2016-07-07 17:30:34 -05:00
Brian Broll 92021a06ba Decreased cifar10 max iterations. Fixes #424 (#455) 2016-07-07 15:48:18 -06:00
Brian Broll be1e4fa388 Added 'Data' to op input options. Fixes #376 (#454)
WIP #376 Removed 'Data' from output options
2016-07-07 15:17:27 -06:00
JimnyCricket 09505c9989 Clears jobs on restart of server Fixes #452 (#453) 2016-07-07 14:57:34 -06:00
Brian Broll b96f2a845a Added criterion reference support. Fixes #369 (#450)
WIP #369 Removed criterion filter

WIP #396 Added criterion layers to nn seed

WIP #369 Added GenerateCriterion plugin

WIP #369 Added GenerateCriterion to criterion meta

WIP #369 Filtered criterion from the ArchEditor

WIP Removed old css

WIP #369 filtered criterion types

WIP #369. Fixed criterion pointer assignment

WIP #369 Fixed criterion execution problems

WIP #369 Updated seeds

WIP #369 Fixed failing test
2016-07-07 11:54:09 -06:00
Brian Broll 14c0af86c9 Added import torch action to arch editor. Fixes #447 (#449) 2016-07-07 10:29:13 -06:00
Brian Broll 56a0b788ee Added editable title for architecture. Fixes #445 (#448)
WIP #445 Refactoring the panel title renaming

WIP #445 Made arch editor renameable

WIP #445 Fixed capitalization for consistency
2016-07-07 10:28:54 -06:00
Brian Broll 873cbc2145 Updated main view to have nav bar and pipeline index. Fixes #440 (#446)
WIP #440 Added MainView

WIP #440 Removed unneeded files

WIP #440 Added basic left bar

WIP #440 Added root node actions

WIP #440 Embedded PipelineIndex

WIP #440 Removed unused js

WIP #440 Removed setTimeout

WIP #440 Fixed some layout issues. css reduction

WIP #440 Added glyphicon

WIP #440 Fixed menu control icon placement, size, color

WIP

WIP #440 Added opening/closing of the nav bar

WIP #440 Added grey background-color

WIP #440 Fixed hide on small screens

WIP #440. Added action buttons

WIP #440 Fixed arch-content list

WIP #440 Removed bullet points

WIP #440 Fixed resize positioning

WIP #440 Increased font size for headers

WIP #440 italic actions

WIP #440 Added some structure for the artifacts

WIP #440 Added download artifact link

WIP #440 Fixed lingering territory rules

WIP #440 removed unused lib files

WIP #440 Fixed code climate issues
2016-07-07 09:21:35 -06:00
Brian Broll 3e3326688c Added meaningful error if retrieving nil val from layer. Fixes #386 (#442)
WIP #386 Added googlenet-setters for testing error messages

WIP #386 Commented out tacking in extra values

WIP #386 Ignore "nil gets" if in "set" operation
2016-07-01 13:14:06 -05:00
Brian Broll 6e32394e01 Added pipeline index viz. Fixes #429 (#438)
WIP #429 Added basic boilerplate for the pipeline index viz

WIP #429 Removed the title

WIP #429 Fixed columns (and text)

WIP #429 Added open, delete actions

WIP #429 Added double click to edit pipeline name

WIP #429 Added check for empty, same name

WIP #429 Added comment for thing to add next

WIP #429 Added some thumbnail support and embedded support

WIP #429 Fixed the thumbnail

WIP #429 thumbnail updates

WIP #429 Set background color and fixed updateNode bug

WIP #429 Fixed update thumbnail deletion

WIP #429 Added preview click-to-open

WIP #429 Added empty message

WIP #429 slight refactor

WIP #429 Added executions text (better phrasing)

WIP #429 Removed toolbar items

WIP #429 Fixed remove undefined bug

WIP #429 Updated seeds

WIP #429 Added pipeline index css to ignore

WIP #429 Fixed code climate issues

WIP #429 Added csslint ignore file

WIP #429 Fixed code climate issues

WIP #429 Added csslint ignore block for materialize

WIP #429 Added thumbnails to cifar10 example
2016-06-30 15:33:05 -05:00
Brian Broll afed957af8 Set artifact loader to remove data handle on "unset". Fixes #437 (#439) 2016-06-30 15:24:42 -05:00
Brian Broll 4c100ac001 Added support for creating primitive types from op editor. Fixes #432 (#435)
WIP #432 Added basic support for primitive/complex coloring and creation

WIP #432 Added tabs
2016-06-30 14:46:06 -05:00
Brian Broll 29724551f0 Updated reference selection btns in op editor. Fixes #434 (#436) 2016-06-29 14:50:18 -05:00
Brian Broll 1f5c8d7423 Updated ImportArtifact result checking. Fixes #427 (#431) 2016-06-29 13:24:18 -05:00
Brian Broll a613a1e8f7 Added artifact upload from ArtifactLoader. Fixes #422 (#428)
WIP #422 Added upload artifact icon

WIP #422 Added upload artifact functionality
2016-06-29 13:10:09 -05:00
JimnyCricket 7fce6e98dd Merge pull request #426 from dfst/425-port-must-be-num
Casted PORT to num. Fixes #425
2016-06-29 11:04:09 -07:00
Brian Broll ea572e8f6c Casted PORT to num. Fixes #425 2016-06-29 12:26:24 -05:00
Brian Broll 36290d8dc7 Removed the data type card. Fixes #420 (#421) 2016-06-29 09:32:50 -05:00
Brian Broll dadc09e0e1 Added delete, return-to-op fab actions for Primitive editing. Fixes #418 (#419) 2016-06-29 09:07:17 -05:00
Brian Broll be3d278d13 Added GoToBase btn for data in op editor. Fixes #414 (#417) 2016-06-29 09:00:22 -05:00
Brian Broll 32a96fbf2b Added class def -> op editor pivots and del btn. Fixes #413 (#416)
WIP #413. Fixed code climate issue
2016-06-29 08:51:38 -05:00
Brian Broll ebe391c948 Added 'Create Class' node in OperationEditor. Fixes #171 (#415)
WIP #171 Adding support for new classes

WIP #171. Fixed "New Class" tooltip

WIP #171 Fixed eslint error
2016-06-29 08:41:15 -05:00
Brian Broll e30ebf3a45 Added os not recognized message. Fixes #404 (#405)
WIP #404 Added "install mongo" message at end

WIP #404 Fixed message when mongo installed
2016-06-28 15:43:37 -05:00
Brian Broll 9e0a780ed2 Updated new op name to conform to new layer name. Fixes #399 (#403) 2016-06-28 15:17:58 -05:00
Brian Broll 841637e804 Updated plugin names and icons. Fixes #401 (#402) 2016-06-28 15:01:44 -05:00
Brian Broll 75241262c4 Added delete custom layer def. Fixes #389 (#400)
WIP #389 code climate fix
2016-06-28 14:37:40 -05:00
Brian Broll b39ac022b6 Added operation deletion button. Fixes #390 (#398)
WIP #390 Added delete button (non-func)

WIP #390 Added deletion func for deleting current node
2016-06-28 14:20:05 -05:00
Brian Broll 8486b86a05 Added pivot back to last arch from custom layer. Fixes #388 (#396)
WIP #388 Refactored op -> pipeline pivoting
2016-06-28 13:53:36 -05:00
Brian Broll 322af8a4f5 Removed 'MyLayers' card. Fixes #391 (#394) 2016-06-28 13:39:49 -05:00
Brian Broll 5e1930f096 Added tabs to initial layer dialog. Fixes #392 (#393) 2016-06-28 13:09:28 -05:00
Brian Broll c0f1348a14 Added sponsor info and removed caffe support comment 2016-06-28 13:06:35 -05:00
Brian Broll 383f5f9fa0 Added (tabbed) custom layer creation from arch editor. Fixes #385 (#387)
WIP #385 Added node icons to arch creator.

WIP #385 Updated for new AddNodeDialog.prompt interface

WIP #385 Added tabs to layers and create layer support

WIP #385 Added code climate ignore dup (non) issue

WIP Added codeclimate, csslint configs
2016-06-28 10:50:40 -05:00
Brian Broll 5cf592e103 removed old 'demo' seed. Fixes #365 (#384) 2016-06-28 07:46:26 -05:00
Brian Broll a14e750b6f Made pipeline title editable. Fixes #375 (#383) 2016-06-27 16:12:25 -05:00
Brian Broll 73e165197f Added editable operation title & better header comment. Fixes #380 (#381)
WIP #380 Added editable title

WIP #380 Updated the operation header comment

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