mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-25 00:12:08 +08:00
Merge.
This commit is contained in:
+14
-6
@@ -1,12 +1,13 @@
|
||||
# Contributing
|
||||
|
||||
This document briefly describes how to contribute to the
|
||||
galaxy-central core project - also checkout the video of our [2013
|
||||
Galaxy Community Conference
|
||||
presentation](http://vimeo.com/channels/581875/73486255) on the
|
||||
topic. For information on contributing more broadly to the Galaxy
|
||||
ecosystem and a deeper discussion of some of these points - please see
|
||||
the [Develop](https://wiki.galaxyproject.org/Develop/) section of the
|
||||
galaxy-central core project - also checkout our 2013 Galaxy Community
|
||||
Conference presentation] on the topic
|
||||
([video](http://vimeo.com/channels/581875/73486255),
|
||||
[presentation](https://wiki.galaxyproject.org/Documents/Presentations/GCC2013?action=AttachFile&do=view&target=BakerContribute.pdf)). For
|
||||
information on contributing more broadly to the Galaxy ecosystem and a
|
||||
deeper discussion of some of these points - please see the
|
||||
[Develop](https://wiki.galaxyproject.org/Develop/) section of the
|
||||
[Galaxy Wiki](https://wiki.galaxyproject.org/).
|
||||
|
||||
## Before you Begin
|
||||
@@ -80,6 +81,13 @@ the [development mailing list](http://dev.list.galaxyproject.org/).
|
||||
|
||||
* A description of how to test the change.
|
||||
|
||||
## Ideas
|
||||
|
||||
Galaxy's [Trello board](http://bit.ly/gxytrello) is filled with bugs and ideas
|
||||
for enhancements, but we maintain a [card](https://trello.com/c/eFdPIdIB) with
|
||||
links to smaller issues we believe would make the best entry points for new
|
||||
developers.
|
||||
|
||||
## A Quick Note about Tools
|
||||
|
||||
For the most part, Galaxy tools should be published to the
|
||||
|
||||
@@ -275,10 +275,16 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
|
||||
/** Request a new model for an already created tool form and updates the form inputs
|
||||
*/
|
||||
_updateModel: function() {
|
||||
// create the request dictionary
|
||||
// link self
|
||||
var self = this;
|
||||
var current_state = this.tree.finalize();
|
||||
|
||||
|
||||
// create the request dictionary
|
||||
var current_state = {
|
||||
tool_id : this.options.id,
|
||||
tool_version : this.options.version,
|
||||
inputs : this.tree.finalize()
|
||||
}
|
||||
|
||||
// log tool state
|
||||
console.debug('tools-form-workflow::_refreshForm() - Refreshing states.');
|
||||
console.debug(current_state);
|
||||
@@ -287,11 +293,11 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
|
||||
var process_id = this.deferred.register();
|
||||
|
||||
// build model url for request
|
||||
var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id + '&__is_dynamic__=False';
|
||||
var model_url = galaxy_config.root + 'api/workflows/build_module';
|
||||
|
||||
// post job
|
||||
Utils.request({
|
||||
type : 'GET',
|
||||
type : 'POST',
|
||||
url : model_url,
|
||||
data : current_state,
|
||||
success : function(data) {
|
||||
|
||||
@@ -34,8 +34,7 @@ define([], function() {
|
||||
this.field.skip = false;
|
||||
var v = this.field.value && this.field.value();
|
||||
this.field.skip = Boolean(options.optional &&
|
||||
((this.default_value === undefined) ||
|
||||
((this.field.validate && !this.field.validate()) || !v ||
|
||||
(((this.field.validate && !this.field.validate()) || !v ||
|
||||
(v == this.default_value) || (Number(v) == Number(this.default_value)) ||
|
||||
(JSON.stringify(v) == JSON.stringify(this.default_value)))));
|
||||
|
||||
|
||||
@@ -294,17 +294,20 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
|
||||
// get id
|
||||
var id = input_def.id;
|
||||
|
||||
// add regular/default value if missing
|
||||
if (input_def.value === undefined) {
|
||||
input_def.value = null;
|
||||
}
|
||||
if (input_def.default_value === undefined) {
|
||||
input_def.default_value = input_def.value;
|
||||
}
|
||||
|
||||
// create input field
|
||||
var field = this._createField(input_def);
|
||||
|
||||
// add to field list
|
||||
this.app.field_list[id] = field;
|
||||
|
||||
// fix default value if missing
|
||||
if (input_def.default_value === undefined) {
|
||||
input_def.default_value = input_def.value;
|
||||
}
|
||||
|
||||
// create input field wrapper
|
||||
var input_element = new InputElement(this.app, {
|
||||
label : input_def.label,
|
||||
|
||||
@@ -10,13 +10,13 @@ return Backbone.Model.extend({
|
||||
initialize: function(app) {
|
||||
this.app = app;
|
||||
},
|
||||
|
||||
|
||||
/** Convert dictionary representation into tool api specific flat dictionary format.
|
||||
*/
|
||||
finalize: function(patch) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// dictionary with api specific identifiers
|
||||
this.map_dict = {};
|
||||
|
||||
@@ -24,24 +24,24 @@ return Backbone.Model.extend({
|
||||
if (!this.app.section) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// ensure that dictionary with patching functions exists
|
||||
patch = patch || {};
|
||||
|
||||
|
||||
// dictionary formatted for job submission or tool form update
|
||||
var result_dict = {};
|
||||
|
||||
// prepare full dictionary
|
||||
var dict = {};
|
||||
|
||||
|
||||
// fill dictionary from dom
|
||||
this._iterate(this.app.section.$el, dict);
|
||||
|
||||
|
||||
// add identifier and value to job definition
|
||||
function add(job_input_id, input_id, input_value) {
|
||||
// add entry to result dictionary
|
||||
result_dict[job_input_id] = input_value;
|
||||
|
||||
|
||||
// backup id mapping
|
||||
self.map_dict[job_input_id] = input_id;
|
||||
};
|
||||
@@ -53,21 +53,21 @@ return Backbone.Model.extend({
|
||||
if (node.input) {
|
||||
// get node
|
||||
var input = node.input;
|
||||
|
||||
|
||||
// create identifier
|
||||
var job_input_id = identifier;
|
||||
if (identifier != '') {
|
||||
job_input_id += '|';
|
||||
}
|
||||
job_input_id += input.name;
|
||||
|
||||
|
||||
// process input type
|
||||
switch (input.type) {
|
||||
// handle repeats
|
||||
case 'repeat':
|
||||
// section identifier
|
||||
var section_label = 'section-';
|
||||
|
||||
|
||||
// collect repeat block identifiers
|
||||
var block_indices = [];
|
||||
var block_prefix = null;
|
||||
@@ -81,10 +81,10 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sort repeat blocks
|
||||
block_indices.sort(function(a,b) { return a - b; });
|
||||
|
||||
|
||||
// add to response dictionary in created order
|
||||
var index = 0;
|
||||
for (var i in block_indices) {
|
||||
@@ -98,10 +98,10 @@ return Backbone.Model.extend({
|
||||
if (patch[input.test_param.type]) {
|
||||
value = patch[input.test_param.type](value);
|
||||
}
|
||||
|
||||
|
||||
// add conditional value
|
||||
add (job_input_id + '|' + input.test_param.name, input.id, value);
|
||||
|
||||
|
||||
// identify selected case
|
||||
var selectedCase = self.matchCase(input, value);
|
||||
if (selectedCase != -1) {
|
||||
@@ -116,22 +116,17 @@ return Backbone.Model.extend({
|
||||
// get field
|
||||
var field = self.app.field_list[input.id];
|
||||
if (field && field.value) {
|
||||
// get and patch field value
|
||||
// validate field value
|
||||
var value = field.value();
|
||||
if (patch[input.type]) {
|
||||
value = patch[input.type](value);
|
||||
}
|
||||
|
||||
// validate field value
|
||||
if (field.skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// validate field value
|
||||
if (field.validate && !field.validate()) {
|
||||
value = null;
|
||||
}
|
||||
|
||||
// get and patch field value
|
||||
if (patch[input.type]) {
|
||||
value = patch[input.type](value);
|
||||
}
|
||||
|
||||
// ignore certain values
|
||||
if (input.ignore === undefined || (value !== null && input.ignore != value)) {
|
||||
// add value to submission
|
||||
@@ -149,20 +144,20 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// start conversion
|
||||
convert('', dict);
|
||||
|
||||
|
||||
// return result
|
||||
return result_dict;
|
||||
},
|
||||
|
||||
|
||||
/** Match job definition identifier to input element identifier
|
||||
*/
|
||||
match: function (job_input_id) {
|
||||
return this.map_dict && this.map_dict[job_input_id];
|
||||
},
|
||||
|
||||
|
||||
/** Match conditional values to selected cases
|
||||
*/
|
||||
matchCase: function(input, value) {
|
||||
@@ -174,27 +169,27 @@ return Backbone.Model.extend({
|
||||
value = input.test_param.falsevalue || 'false';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find selected case
|
||||
for (var i in input.cases) {
|
||||
if (input.cases[i].value == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// selected case not found
|
||||
return -1;
|
||||
},
|
||||
|
||||
|
||||
/** Matches identifier from api model to input elements
|
||||
*/
|
||||
matchModel: function(model, callback) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
for (var i in head) {
|
||||
@@ -224,23 +219,23 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// match all ids and return messages
|
||||
search('', model.inputs);
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/** Matches identifier from api response to input elements
|
||||
*/
|
||||
matchResponse: function(response) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
if (typeof head === 'string') {
|
||||
@@ -262,14 +257,14 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// match all ids and return messages
|
||||
search('', response);
|
||||
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/** Iterate through the tool form dom and map it to the dictionary.
|
||||
*/
|
||||
_iterate: function(parent, dict) {
|
||||
@@ -279,15 +274,15 @@ return Backbone.Model.extend({
|
||||
children.each(function() {
|
||||
// get child element
|
||||
var child = this;
|
||||
|
||||
|
||||
// get id
|
||||
var id = $(child).attr('id');
|
||||
|
||||
|
||||
// create new branch
|
||||
if ($(child).hasClass('section-row')) {
|
||||
// create sub dictionary
|
||||
dict[id] = {};
|
||||
|
||||
|
||||
// add input element if it exists
|
||||
var input = self.app.input_list[id];
|
||||
if (input) {
|
||||
@@ -295,7 +290,7 @@ return Backbone.Model.extend({
|
||||
input : input
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fill sub dictionary
|
||||
self._iterate(child, dict[id]);
|
||||
} else {
|
||||
|
||||
@@ -34,7 +34,7 @@ function MetricsLogger( options ){
|
||||
var self = this;
|
||||
|
||||
///** get the current user's id from bootstrapped data or options */
|
||||
self.userId = window.bootstrapped? window.bootstrapped.user.id: null;
|
||||
self.userId = ( window.bootstrapped && window.bootstrapped.user )? window.bootstrapped.user.id: null;
|
||||
self.userId = self.userId || options.userId || null;
|
||||
|
||||
/** the (optional) console to emit logs to */
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-contrib-handlebars": "~0.5.10",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-handlebars": "^0.9.3",
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"grunt-contrib-watch": "~0.5.3"
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,6 +3,9 @@ Providers that provide lists of lists generally where each line of a source
|
||||
is further subdivided into multiple data (e.g. columns from a line).
|
||||
"""
|
||||
|
||||
import urllib
|
||||
import re
|
||||
|
||||
import line
|
||||
|
||||
_TODO = """
|
||||
@@ -34,12 +37,13 @@ class ColumnarDataProvider( line.RegexLineDataProvider ):
|
||||
'column_count' : 'int',
|
||||
'column_types' : 'list:str',
|
||||
'parse_columns' : 'bool',
|
||||
'deliminator' : 'str'
|
||||
'deliminator' : 'str',
|
||||
'filters' : 'list:str'
|
||||
}
|
||||
|
||||
def __init__( self, source, indeces=None,
|
||||
column_count=None, column_types=None, parsers=None, parse_columns=True,
|
||||
deliminator='\t', **kwargs ):
|
||||
deliminator='\t', filters=None, **kwargs ):
|
||||
"""
|
||||
:param indeces: a list of indeces of columns to gather from each row
|
||||
Optional: will default to `None`.
|
||||
@@ -103,6 +107,104 @@ class ColumnarDataProvider( line.RegexLineDataProvider ):
|
||||
# overwrite with user desired parsers
|
||||
self.parsers.update( parsers or {} )
|
||||
|
||||
filters = filters or []
|
||||
self.column_filters = []
|
||||
for filter_ in filters:
|
||||
parsed = self.parse_filter( filter_ )
|
||||
#TODO: might be better to error on bad filter/None here
|
||||
if callable( parsed ):
|
||||
self.column_filters.append( parsed )
|
||||
|
||||
def parse_filter( self, filter_param_str ):
|
||||
split = filter_param_str.split( '-', 3 )
|
||||
if not len( split ) == 3:
|
||||
return None
|
||||
column, op, val = split
|
||||
|
||||
# better checking v. len and indeces
|
||||
column = int( column )
|
||||
if column > len( self.column_types ):
|
||||
return None
|
||||
if self.column_types[ column ] in ( 'float', 'int' ):
|
||||
return self.create_numeric_filter( column, op, val )
|
||||
if self.column_types[ column ] in ( 'str' ):
|
||||
return self.create_string_filter( column, op, val )
|
||||
if self.column_types[ column ] in ( 'list' ):
|
||||
return self.create_list_filter( column, op, val )
|
||||
return None
|
||||
|
||||
def create_numeric_filter( self, column, op, val ):
|
||||
"""
|
||||
Return an anonymous filter function that will be passed the array
|
||||
of parsed columns. Return None if no filter function can be
|
||||
created for the given params.
|
||||
|
||||
The function will compare the column at index `column` against `val`
|
||||
using the given op where op is one of:
|
||||
lt: less than, le: less than or equal to,
|
||||
eq: equal to, ne: not equal to,
|
||||
ge: greather than or equal to, gt: greater than
|
||||
|
||||
`val` is cast as float here and will return None if there's a parsing error.
|
||||
"""
|
||||
try:
|
||||
val = float( val )
|
||||
except ValueError:
|
||||
return None
|
||||
if 'lt' == op:
|
||||
return lambda d: d[column] < val
|
||||
elif 'le' == op:
|
||||
return lambda d: d[column] <= val
|
||||
elif 'eq' == op:
|
||||
return lambda d: d[column] == val
|
||||
elif 'ne' == op:
|
||||
return lambda d: d[column] != val
|
||||
elif 'ge' == op:
|
||||
return lambda d: d[column] >= val
|
||||
elif 'gt' == op:
|
||||
return lambda d: d[column] > val
|
||||
return None
|
||||
|
||||
def create_string_filter( self, column, op, val ):
|
||||
"""
|
||||
Return an anonymous filter function that will be passed the array
|
||||
of parsed columns. Return None if no filter function can be
|
||||
created for the given params.
|
||||
|
||||
The function will compare the column at index `column` against `val`
|
||||
using the given op where op is one of:
|
||||
eq: exactly matches,
|
||||
has: the column contains the substring `val`,
|
||||
re: the column matches the regular expression in `val`
|
||||
"""
|
||||
if 'eq' == op:
|
||||
return lambda d: d[column] == val
|
||||
elif 'has' == op:
|
||||
return lambda d: val in d[column]
|
||||
elif 're' == op:
|
||||
val = urllib.unquote_plus( val )
|
||||
val = re.compile( val )
|
||||
return lambda d: val.match( d[column] ) is not None
|
||||
return None
|
||||
|
||||
def create_list_filter( self, column, op, val ):
|
||||
"""
|
||||
Return an anonymous filter function that will be passed the array
|
||||
of parsed columns. Return None if no filter function can be
|
||||
created for the given params.
|
||||
|
||||
The function will compare the column at index `column` against `val`
|
||||
using the given op where op is one of:
|
||||
eq: the list `val` exactly matches the list in the column,
|
||||
has: the list in the column contains the sublist `val`,
|
||||
"""
|
||||
if 'eq' == op:
|
||||
val = self.parse_value( val, 'list' )
|
||||
return lambda d: d[column] == val
|
||||
elif 'has' == op:
|
||||
return lambda d: val in d[column]
|
||||
return None
|
||||
|
||||
def get_default_parsers( self ):
|
||||
"""
|
||||
Return parser dictionary keyed for each columnar type
|
||||
@@ -140,6 +242,39 @@ class ColumnarDataProvider( line.RegexLineDataProvider ):
|
||||
#'gffstrand': # -, +, ?, or '.' for None, etc.
|
||||
}
|
||||
|
||||
def filter( self, line ):
|
||||
line = super( ColumnarDataProvider, self ).filter( line )
|
||||
if line == None:
|
||||
return line
|
||||
columns = self.parse_columns_from_line( line )
|
||||
return self.filter_by_columns( columns )
|
||||
|
||||
def parse_columns_from_line( self, line ):
|
||||
"""
|
||||
Returns a list of the desired, parsed columns.
|
||||
:param line: the line to parse
|
||||
:type line: str
|
||||
"""
|
||||
#TODO: too much going on in this loop - the above should all be precomputed AMAP...
|
||||
all_columns = line.split( self.deliminator )
|
||||
# if no indeces were passed to init, return all columns
|
||||
selected_indeces = self.selected_column_indeces or list( xrange( len( all_columns ) ) )
|
||||
parsed_columns = []
|
||||
for parser_index, column_index in enumerate( selected_indeces ):
|
||||
parsed_columns.append( self.parse_column_at_index( all_columns, parser_index, column_index ) )
|
||||
return parsed_columns
|
||||
|
||||
def parse_column_at_index( self, columns, parser_index, index ):
|
||||
"""
|
||||
Get the column type for the parser from `self.column_types` or `None`
|
||||
if the type is unavailable.
|
||||
"""
|
||||
try:
|
||||
return self.parse_value( columns[ index ], self.get_column_type( parser_index ) )
|
||||
# if a selected index is not within columns, return None
|
||||
except IndexError, index_err:
|
||||
return None
|
||||
|
||||
def parse_value( self, val, type ):
|
||||
"""
|
||||
Attempt to parse and return the given value based on the given type.
|
||||
@@ -173,51 +308,11 @@ class ColumnarDataProvider( line.RegexLineDataProvider ):
|
||||
except IndexError, ind_err:
|
||||
return None
|
||||
|
||||
def parse_column_at_index( self, columns, parser_index, index ):
|
||||
"""
|
||||
Get the column type for the parser from `self.column_types` or `None`
|
||||
if the type is unavailable.
|
||||
"""
|
||||
try:
|
||||
return self.parse_value( columns[ index ], self.get_column_type( parser_index ) )
|
||||
# if a selected index is not within columns, return None
|
||||
except IndexError, index_err:
|
||||
return None
|
||||
|
||||
def parse_columns_from_line( self, line ):
|
||||
"""
|
||||
Returns a list of the desired, parsed columns.
|
||||
:param line: the line to parse
|
||||
:type line: str
|
||||
"""
|
||||
#TODO: too much going on in this loop - the above should all be precomputed AMAP...
|
||||
all_columns = line.split( self.deliminator )
|
||||
# if no indeces were passed to init, return all columns
|
||||
selected_indeces = self.selected_column_indeces or list( xrange( len( all_columns ) ) )
|
||||
parsed_columns = []
|
||||
for parser_index, column_index in enumerate( selected_indeces ):
|
||||
parsed_columns.append( self.parse_column_at_index( all_columns, parser_index, column_index ) )
|
||||
return parsed_columns
|
||||
|
||||
def __iter__( self ):
|
||||
parent_gen = super( ColumnarDataProvider, self ).__iter__()
|
||||
for line in parent_gen:
|
||||
columns = self.parse_columns_from_line( line )
|
||||
yield columns
|
||||
|
||||
#TODO: implement column filters here and not below - flatten hierarchy
|
||||
|
||||
class FilteredByColumnDataProvider( ColumnarDataProvider ):
|
||||
"""
|
||||
Data provider that provide a list of columns from the lines of its source
|
||||
_only_ if they pass a given filter function.
|
||||
|
||||
e.g. column #3 is type int and > N
|
||||
"""
|
||||
# TODO: how to do this and still have limit and offset work?
|
||||
def __init__( self, source, **kwargs ):
|
||||
raise NotImplementedError()
|
||||
super( FilteredByColumnDataProvider, self ).__init__( source, **kwargs )
|
||||
def filter_by_columns( self, columns ):
|
||||
for filter_fn in self.column_filters:
|
||||
if not filter_fn( columns ):
|
||||
return None
|
||||
return columns
|
||||
|
||||
|
||||
class DictDataProvider( ColumnarDataProvider ):
|
||||
|
||||
@@ -7,7 +7,7 @@ try:
|
||||
except ImportError:
|
||||
# Not in Galaxy, map Galaxy job states to Pulsar ones.
|
||||
from galaxy.util import enum
|
||||
job_states = enum(RUNNING='running', OK='complete', QUEUED='queued')
|
||||
job_states = enum(RUNNING='running', OK='complete', QUEUED='queued', ERROR="failed")
|
||||
|
||||
from ..job import BaseJobExec
|
||||
|
||||
@@ -59,10 +59,10 @@ class Slurm(BaseJobExec):
|
||||
return 'scancel %s' % job_id
|
||||
|
||||
def get_status(self, job_ids=None):
|
||||
return 'squeue -a -o \\"%A %t\\"'
|
||||
return "squeue -a -o '%A %t'"
|
||||
|
||||
def get_single_status(self, job_id):
|
||||
return 'squeue -a -o \\"%A %t\\" -j ' + job_id
|
||||
return "squeue -a -o '%A %t' -j " + job_id
|
||||
|
||||
def parse_status(self, status, job_ids):
|
||||
# Get status for each job, skipping header.
|
||||
@@ -80,6 +80,7 @@ class Slurm(BaseJobExec):
|
||||
# Job still on cluster and has state.
|
||||
id, state = status[1].split()
|
||||
return self._get_job_state(state)
|
||||
# else line like "slurm_load_jobs error: Invalid job id specified"
|
||||
return job_states.OK
|
||||
|
||||
def _get_job_state(self, state):
|
||||
|
||||
@@ -199,6 +199,42 @@ class UserManager( base.ModelManager, deletable.PurgableManagerMixin ):
|
||||
#TODO: use quota manager
|
||||
return self.app.quota_agent.get_percent( user=user )
|
||||
|
||||
def tags_used( self, trans, user, tag_models=None ):
|
||||
"""
|
||||
Return a list of distinct 'user_tname:user_value' strings that the
|
||||
given user has used.
|
||||
"""
|
||||
#TODO: simplify and unify with tag manager
|
||||
if self.is_anonymous( user ):
|
||||
return []
|
||||
|
||||
# get all the taggable model TagAssociations
|
||||
if not tag_models:
|
||||
tag_models = [ v.tag_assoc_class for v in self.app.tag_handler.item_tag_assoc_info.values() ]
|
||||
# create a union of subqueries for each for this user - getting only the tname and user_value
|
||||
all_tags_query = None
|
||||
for tag_model in tag_models:
|
||||
subq = ( self.app.model.context.query( tag_model.user_tname, tag_model.user_value )
|
||||
.filter( tag_model.user == trans.user ) )
|
||||
all_tags_query = subq if all_tags_query is None else all_tags_query.union( subq )
|
||||
|
||||
# if nothing init'd the query, bail
|
||||
if all_tags_query is None:
|
||||
return []
|
||||
|
||||
# boil the tag tuples down into a sorted list of DISTINCT name:val strings
|
||||
tags = all_tags_query.distinct().all()
|
||||
tags = [( ( name + ':' + val ) if val else name ) for name, val in tags ]
|
||||
return sorted( tags )
|
||||
|
||||
def has_requests( self, trans, user ):
|
||||
"""
|
||||
"""
|
||||
if self.is_anonymous( user ):
|
||||
return False
|
||||
request_types = self.app.security_agent.get_accessible_request_types( trans, user )
|
||||
return ( user.requests or request_types )
|
||||
|
||||
|
||||
class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
|
||||
|
||||
@@ -214,21 +250,22 @@ class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
|
||||
'id', 'email', 'username'
|
||||
])
|
||||
self.add_view( 'detailed', [
|
||||
'update_time',
|
||||
'create_time',
|
||||
|
||||
'deleted',
|
||||
'purged',
|
||||
'active',
|
||||
#'update_time',
|
||||
#'create_time',
|
||||
|
||||
'total_disk_usage',
|
||||
'nice_total_disk_usage',
|
||||
'quota_percent'
|
||||
# 'preferences',
|
||||
# # all tags
|
||||
# 'tags',
|
||||
# # all annotations
|
||||
# 'annotations'
|
||||
|
||||
#'deleted',
|
||||
#'purged',
|
||||
#'active',
|
||||
|
||||
#'preferences',
|
||||
# all tags
|
||||
'tags_used',
|
||||
## all annotations
|
||||
#'annotations'
|
||||
], include_keys_from='summary' )
|
||||
|
||||
def add_serializers( self ):
|
||||
@@ -240,7 +277,13 @@ class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
|
||||
'create_time' : self.serialize_date,
|
||||
'update_time' : self.serialize_date,
|
||||
'is_admin' : lambda t, i, k: self.user_manager.is_admin( t, i ),
|
||||
'quota_percent' : lambda t, i, k: self.user_manager.quota( t, i )
|
||||
|
||||
'total_disk_usage' : lambda t, i, k: float( i.total_disk_usage ),
|
||||
'quota_percent' : lambda t, i, k: self.user_manager.quota( t, i ),
|
||||
|
||||
'tags_used' : lambda t, i, k: self.user_manager.tags_used( t, i ),
|
||||
#TODO: 'has_requests' is more apt
|
||||
'requests' : lambda t, i, k: self.user_manager.has_requests( t, i )
|
||||
})
|
||||
|
||||
def serialize_current_anonymous_user( self, trans, user, keys ):
|
||||
|
||||
@@ -2250,13 +2250,12 @@ class Tool( object, Dictifiable ):
|
||||
|
||||
return tool_dict
|
||||
|
||||
def to_json (self, trans, **kwd):
|
||||
def to_json (self, trans, kwd={}, is_dynamic=True):
|
||||
"""
|
||||
Recursively creates a tool dictionary containing repeats, dynamic options and updated states.
|
||||
"""
|
||||
job_id = kwd.get('__job_id__', None)
|
||||
dataset_id = kwd.get('__dataset_id__', None)
|
||||
is_dynamic = string_as_bool(kwd.get('__is_dynamic__', True))
|
||||
|
||||
# load job details if provided
|
||||
job = None
|
||||
|
||||
@@ -1618,6 +1618,8 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
|
||||
return UnvalidatedValue( None )
|
||||
initial_values = []
|
||||
recurse_options( initial_values, self.get_options( trans=trans, other_values=context ) )
|
||||
if len( initial_values ) == 0:
|
||||
initial_values = None
|
||||
return initial_values
|
||||
|
||||
def value_to_display_text( self, value, app ):
|
||||
|
||||
@@ -19,6 +19,7 @@ from framework.decorators import _future_expose_api_anonymous
|
||||
from framework.decorators import _future_expose_api_raw
|
||||
from framework.decorators import _future_expose_api_raw_anonymous
|
||||
from framework.decorators import _future_expose_api_anonymous_and_sessionless
|
||||
from framework.decorators import _future_expose_api_raw_anonymous_and_sessionless
|
||||
|
||||
from framework.formbuilder import form
|
||||
from framework.formbuilder import FormBuilder
|
||||
|
||||
@@ -344,3 +344,6 @@ def _future_expose_api_raw( func ):
|
||||
|
||||
def _future_expose_api_raw_anonymous( func ):
|
||||
return _future_expose_api( func, to_json=False, user_required=False )
|
||||
|
||||
def _future_expose_api_raw_anonymous_and_sessionless( func ):
|
||||
return _future_expose_api( func, to_json=False, user_required=False, user_or_session_required=False )
|
||||
|
||||
@@ -8,8 +8,8 @@ from galaxy import exceptions
|
||||
from galaxy import util
|
||||
from galaxy import model
|
||||
from galaxy.web.base.controller import BaseAPIController
|
||||
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
|
||||
from galaxy.web import _future_expose_api_raw_anonymous as expose_api_raw_anonymous
|
||||
from galaxy.web import _future_expose_api_anonymous_and_sessionless as expose_api_anonymous_and_sessionless
|
||||
from galaxy.web import _future_expose_api_raw_anonymous_and_sessionless as expose_api_raw_anonymous_and_sessionless
|
||||
|
||||
|
||||
import logging
|
||||
@@ -28,7 +28,7 @@ class JobFilesAPIController( BaseAPIController ):
|
||||
security model for tool execution.
|
||||
"""
|
||||
|
||||
@expose_api_raw_anonymous
|
||||
@expose_api_raw_anonymous_and_sessionless
|
||||
def index( self, trans, job_id, **kwargs ):
|
||||
"""
|
||||
index( self, trans, job_id, **kwargs )
|
||||
@@ -54,7 +54,7 @@ class JobFilesAPIController( BaseAPIController ):
|
||||
path = kwargs.get("path", None)
|
||||
return open(path, 'rb')
|
||||
|
||||
@expose_api_anonymous
|
||||
@expose_api_anonymous_and_sessionless
|
||||
def create( self, trans, job_id, payload, **kwargs ):
|
||||
"""
|
||||
create( self, trans, job_id, payload, **kwargs )
|
||||
|
||||
@@ -76,14 +76,10 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin ):
|
||||
GET /api/tools/{tool_id}/build
|
||||
Returns a tool model including dynamic parameters and updated values, repeats block etc.
|
||||
"""
|
||||
tool_id = urllib.unquote_plus( id )
|
||||
tool_version = kwd.get( 'tool_version', None )
|
||||
tool = self.app.toolbox.get_tool( tool_id, tool_version )
|
||||
if not tool:
|
||||
trans.response.status = 500
|
||||
return { 'error': 'Could not find tool with id \'%s\'' % tool_id }
|
||||
return tool.to_json(trans, **kwd)
|
||||
|
||||
tool = self._get_tool( id, tool_version=tool_version, user=trans.user )
|
||||
return tool.to_json(trans, kwd)
|
||||
|
||||
@_future_expose_api
|
||||
@web.require_admin
|
||||
def reload( self, trans, tool_id, **kwd ):
|
||||
|
||||
@@ -6,6 +6,8 @@ from __future__ import absolute_import
|
||||
|
||||
import uuid
|
||||
import logging
|
||||
import copy
|
||||
import urllib
|
||||
from sqlalchemy import desc, or_, and_
|
||||
from galaxy import exceptions, util
|
||||
from galaxy.model.item_attrs import UsesAnnotations
|
||||
@@ -17,6 +19,7 @@ from galaxy.web.base.controller import SharableMixin
|
||||
from galaxy.workflow.extract import extract_workflow
|
||||
from galaxy.workflow.run import invoke, queue_invoke
|
||||
from galaxy.workflow.run_request import build_workflow_run_config
|
||||
from galaxy.workflow.modules import module_factory
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -305,6 +308,52 @@ class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesAnn
|
||||
raise exceptions.RequestParameterInvalidException( message )
|
||||
return self.workflow_contents_manager.workflow_to_dict( trans, stored_workflow, style="instance" )
|
||||
|
||||
@expose_api
|
||||
def build_module( self, trans, payload={}):
|
||||
"""
|
||||
POST /api/workflows/build_module
|
||||
Builds module details including a tool model for the workflow editor.
|
||||
"""
|
||||
tool_id = payload.get( 'tool_id', None )
|
||||
tool_version = payload.get( 'tool_version', None )
|
||||
tool_inputs = payload.get( 'inputs', None )
|
||||
annotation = payload.get( 'annotation', '' )
|
||||
|
||||
# load tool
|
||||
tool = self._get_tool( tool_id, tool_version=tool_version, user=trans.user )
|
||||
|
||||
# initialize module
|
||||
trans.workflow_building_mode = True
|
||||
module = module_factory.from_dict( trans, {
|
||||
'type' : 'tool',
|
||||
'tool_id' : tool.id,
|
||||
'tool_state' : None
|
||||
} )
|
||||
|
||||
# create tool model and default tool state (if missing)
|
||||
tool_model = module.tool.to_json(trans, tool_inputs, is_dynamic=False)
|
||||
module.state.inputs = copy.deepcopy(tool_model['state_inputs'])
|
||||
return {
|
||||
'tool_model' : tool_model,
|
||||
'tool_state' : module.get_state(),
|
||||
'data_inputs' : module.get_data_inputs(),
|
||||
'data_outputs' : module.get_data_outputs(),
|
||||
'tool_errors' : module.get_errors(),
|
||||
'form_html' : module.get_config_form(),
|
||||
'annotation' : annotation,
|
||||
'post_job_actions' : module.get_post_job_actions(tool_inputs)
|
||||
}
|
||||
|
||||
#
|
||||
# -- Helper methods --
|
||||
#
|
||||
def _get_tool( self, id, tool_version=None, user=None ):
|
||||
id = urllib.unquote_plus( id )
|
||||
tool = self.app.toolbox.get_tool( id, tool_version )
|
||||
if not tool or not tool.allow_user_access( user ):
|
||||
raise exceptions.ObjectNotFound("Could not find tool with id '%s'" % id)
|
||||
return tool
|
||||
|
||||
def __api_import_new_workflow( self, trans, payload, **kwd ):
|
||||
data = payload['workflow']
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ def populate_api_routes( webapp, app ):
|
||||
webapp.mapper.resource_with_deleted( 'user', 'users', path_prefix='/api' )
|
||||
webapp.mapper.resource( 'genome', 'genomes', path_prefix='/api' )
|
||||
webapp.mapper.resource( 'visualization', 'visualizations', path_prefix='/api' )
|
||||
webapp.mapper.connect( '/api/workflows/build_module', action='build_module', controller="workflows" )
|
||||
webapp.mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
|
||||
webapp.mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
|
||||
webapp.mapper.connect( '/api/histories/{history_id}/citations', action='citations', controller="histories" )
|
||||
|
||||
@@ -609,7 +609,6 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
This is used for the form shown in the right pane when a node
|
||||
is selected.
|
||||
"""
|
||||
|
||||
tool_state = incoming.pop('tool_state', None)
|
||||
trans.workflow_building_mode = True
|
||||
module = module_factory.from_dict( trans, {
|
||||
@@ -617,22 +616,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
'tool_id': tool_id,
|
||||
'tool_state': tool_state
|
||||
} )
|
||||
|
||||
# create tool model and default tool state (if missing)
|
||||
if type == 'tool' and not tool_state:
|
||||
tool_model = module.tool.to_json(trans, **incoming)
|
||||
module.state.inputs = copy.deepcopy(tool_model['state_inputs'])
|
||||
return {
|
||||
'tool_model': tool_model,
|
||||
'tool_state': module.get_state(),
|
||||
'data_inputs': module.get_data_inputs(),
|
||||
'data_outputs': module.get_data_outputs(),
|
||||
'tool_errors': module.get_errors(),
|
||||
'form_html': module.get_config_form(),
|
||||
'annotation': annotation,
|
||||
'post_job_actions': module.get_post_job_actions(incoming)
|
||||
}
|
||||
|
||||
|
||||
# update module state
|
||||
module.update_state( incoming )
|
||||
|
||||
@@ -669,7 +653,8 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
module = module_factory.new( trans, type, **kwargs )
|
||||
tool_model = None
|
||||
if type == 'tool':
|
||||
tool_model = module.tool.to_json(trans)
|
||||
tool_model = module.tool.to_json(trans, is_dynamic=False)
|
||||
module.state.inputs = copy.deepcopy(tool_model['state_inputs'])
|
||||
return {
|
||||
'type': module.type,
|
||||
'name': module.get_name(),
|
||||
|
||||
@@ -275,10 +275,16 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
|
||||
/** Request a new model for an already created tool form and updates the form inputs
|
||||
*/
|
||||
_updateModel: function() {
|
||||
// create the request dictionary
|
||||
// link self
|
||||
var self = this;
|
||||
var current_state = this.tree.finalize();
|
||||
|
||||
|
||||
// create the request dictionary
|
||||
var current_state = {
|
||||
tool_id : this.options.id,
|
||||
tool_version : this.options.version,
|
||||
inputs : this.tree.finalize()
|
||||
}
|
||||
|
||||
// log tool state
|
||||
console.debug('tools-form-workflow::_refreshForm() - Refreshing states.');
|
||||
console.debug(current_state);
|
||||
@@ -287,11 +293,11 @@ define(['utils/utils', 'mvc/tools/tools-form-base'],
|
||||
var process_id = this.deferred.register();
|
||||
|
||||
// build model url for request
|
||||
var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id + '&__is_dynamic__=False';
|
||||
var model_url = galaxy_config.root + 'api/workflows/build_module';
|
||||
|
||||
// post job
|
||||
Utils.request({
|
||||
type : 'GET',
|
||||
type : 'POST',
|
||||
url : model_url,
|
||||
data : current_state,
|
||||
success : function(data) {
|
||||
|
||||
@@ -34,8 +34,7 @@ define([], function() {
|
||||
this.field.skip = false;
|
||||
var v = this.field.value && this.field.value();
|
||||
this.field.skip = Boolean(options.optional &&
|
||||
((this.default_value === undefined) ||
|
||||
((this.field.validate && !this.field.validate()) || !v ||
|
||||
(((this.field.validate && !this.field.validate()) || !v ||
|
||||
(v == this.default_value) || (Number(v) == Number(this.default_value)) ||
|
||||
(JSON.stringify(v) == JSON.stringify(this.default_value)))));
|
||||
|
||||
|
||||
@@ -294,17 +294,20 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
|
||||
// get id
|
||||
var id = input_def.id;
|
||||
|
||||
// add regular/default value if missing
|
||||
if (input_def.value === undefined) {
|
||||
input_def.value = null;
|
||||
}
|
||||
if (input_def.default_value === undefined) {
|
||||
input_def.default_value = input_def.value;
|
||||
}
|
||||
|
||||
// create input field
|
||||
var field = this._createField(input_def);
|
||||
|
||||
// add to field list
|
||||
this.app.field_list[id] = field;
|
||||
|
||||
// fix default value if missing
|
||||
if (input_def.default_value === undefined) {
|
||||
input_def.default_value = input_def.value;
|
||||
}
|
||||
|
||||
// create input field wrapper
|
||||
var input_element = new InputElement(this.app, {
|
||||
label : input_def.label,
|
||||
|
||||
@@ -10,13 +10,13 @@ return Backbone.Model.extend({
|
||||
initialize: function(app) {
|
||||
this.app = app;
|
||||
},
|
||||
|
||||
|
||||
/** Convert dictionary representation into tool api specific flat dictionary format.
|
||||
*/
|
||||
finalize: function(patch) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// dictionary with api specific identifiers
|
||||
this.map_dict = {};
|
||||
|
||||
@@ -24,24 +24,24 @@ return Backbone.Model.extend({
|
||||
if (!this.app.section) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// ensure that dictionary with patching functions exists
|
||||
patch = patch || {};
|
||||
|
||||
|
||||
// dictionary formatted for job submission or tool form update
|
||||
var result_dict = {};
|
||||
|
||||
// prepare full dictionary
|
||||
var dict = {};
|
||||
|
||||
|
||||
// fill dictionary from dom
|
||||
this._iterate(this.app.section.$el, dict);
|
||||
|
||||
|
||||
// add identifier and value to job definition
|
||||
function add(job_input_id, input_id, input_value) {
|
||||
// add entry to result dictionary
|
||||
result_dict[job_input_id] = input_value;
|
||||
|
||||
|
||||
// backup id mapping
|
||||
self.map_dict[job_input_id] = input_id;
|
||||
};
|
||||
@@ -53,21 +53,21 @@ return Backbone.Model.extend({
|
||||
if (node.input) {
|
||||
// get node
|
||||
var input = node.input;
|
||||
|
||||
|
||||
// create identifier
|
||||
var job_input_id = identifier;
|
||||
if (identifier != '') {
|
||||
job_input_id += '|';
|
||||
}
|
||||
job_input_id += input.name;
|
||||
|
||||
|
||||
// process input type
|
||||
switch (input.type) {
|
||||
// handle repeats
|
||||
case 'repeat':
|
||||
// section identifier
|
||||
var section_label = 'section-';
|
||||
|
||||
|
||||
// collect repeat block identifiers
|
||||
var block_indices = [];
|
||||
var block_prefix = null;
|
||||
@@ -81,10 +81,10 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sort repeat blocks
|
||||
block_indices.sort(function(a,b) { return a - b; });
|
||||
|
||||
|
||||
// add to response dictionary in created order
|
||||
var index = 0;
|
||||
for (var i in block_indices) {
|
||||
@@ -98,10 +98,10 @@ return Backbone.Model.extend({
|
||||
if (patch[input.test_param.type]) {
|
||||
value = patch[input.test_param.type](value);
|
||||
}
|
||||
|
||||
|
||||
// add conditional value
|
||||
add (job_input_id + '|' + input.test_param.name, input.id, value);
|
||||
|
||||
|
||||
// identify selected case
|
||||
var selectedCase = self.matchCase(input, value);
|
||||
if (selectedCase != -1) {
|
||||
@@ -116,22 +116,17 @@ return Backbone.Model.extend({
|
||||
// get field
|
||||
var field = self.app.field_list[input.id];
|
||||
if (field && field.value) {
|
||||
// get and patch field value
|
||||
// validate field value
|
||||
var value = field.value();
|
||||
if (patch[input.type]) {
|
||||
value = patch[input.type](value);
|
||||
}
|
||||
|
||||
// validate field value
|
||||
if (field.skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// validate field value
|
||||
if (field.validate && !field.validate()) {
|
||||
value = null;
|
||||
}
|
||||
|
||||
// get and patch field value
|
||||
if (patch[input.type]) {
|
||||
value = patch[input.type](value);
|
||||
}
|
||||
|
||||
// ignore certain values
|
||||
if (input.ignore === undefined || (value !== null && input.ignore != value)) {
|
||||
// add value to submission
|
||||
@@ -149,20 +144,20 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// start conversion
|
||||
convert('', dict);
|
||||
|
||||
|
||||
// return result
|
||||
return result_dict;
|
||||
},
|
||||
|
||||
|
||||
/** Match job definition identifier to input element identifier
|
||||
*/
|
||||
match: function (job_input_id) {
|
||||
return this.map_dict && this.map_dict[job_input_id];
|
||||
},
|
||||
|
||||
|
||||
/** Match conditional values to selected cases
|
||||
*/
|
||||
matchCase: function(input, value) {
|
||||
@@ -174,27 +169,27 @@ return Backbone.Model.extend({
|
||||
value = input.test_param.falsevalue || 'false';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find selected case
|
||||
for (var i in input.cases) {
|
||||
if (input.cases[i].value == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// selected case not found
|
||||
return -1;
|
||||
},
|
||||
|
||||
|
||||
/** Matches identifier from api model to input elements
|
||||
*/
|
||||
matchModel: function(model, callback) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
for (var i in head) {
|
||||
@@ -224,23 +219,23 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// match all ids and return messages
|
||||
search('', model.inputs);
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/** Matches identifier from api response to input elements
|
||||
*/
|
||||
matchResponse: function(response) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
if (typeof head === 'string') {
|
||||
@@ -262,14 +257,14 @@ return Backbone.Model.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// match all ids and return messages
|
||||
search('', response);
|
||||
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/** Iterate through the tool form dom and map it to the dictionary.
|
||||
*/
|
||||
_iterate: function(parent, dict) {
|
||||
@@ -279,15 +274,15 @@ return Backbone.Model.extend({
|
||||
children.each(function() {
|
||||
// get child element
|
||||
var child = this;
|
||||
|
||||
|
||||
// get id
|
||||
var id = $(child).attr('id');
|
||||
|
||||
|
||||
// create new branch
|
||||
if ($(child).hasClass('section-row')) {
|
||||
// create sub dictionary
|
||||
dict[id] = {};
|
||||
|
||||
|
||||
// add input element if it exists
|
||||
var input = self.app.input_list[id];
|
||||
if (input) {
|
||||
@@ -295,7 +290,7 @@ return Backbone.Model.extend({
|
||||
input : input
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fill sub dictionary
|
||||
self._iterate(child, dict[id]);
|
||||
} else {
|
||||
|
||||
@@ -1 +1 @@
|
||||
define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.post_job_actions=this.node.post_job_actions||{};this.options=e;this.options.text_enable="In Advance";this.options.text_disable="At Runtime";this.options.is_dynamic=false;this.options.narrow=true;this.options.initial_errors=true;this.options.cls_portlet="ui-portlet-narrow";b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down","repeat","conditional"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or note for this step. It will be shown with the workflow.",value:this.node.annotation};var f=this.node.output_terminals&&Object.keys(this.node.output_terminals)[0];if(f){d[b.uuid()]={name:"pja__"+f+"__EmailAction",label:"Email notification",type:"boolean",value:String(Boolean(this.post_job_actions["EmailAction"+f])),ignore:"false",help:"An email notification will be send when the job has completed.",payload:{host:window.location.host}};d[b.uuid()]={name:"pja__"+f+"__DeleteIntermediatesAction",label:"Output cleanup",type:"boolean",value:String(Boolean(this.post_job_actions["DeleteIntermediatesAction"+f])),ignore:"false",help:"Delete intermediate outputs if they are not used as input for another job."};for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:""});var f={label:"Add Actions: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"integer",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id+"&__is_dynamic__=False";b.request({type:"GET",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
|
||||
define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.post_job_actions=this.node.post_job_actions||{};this.options=e;this.options.text_enable="In Advance";this.options.text_disable="At Runtime";this.options.is_dynamic=false;this.options.narrow=true;this.options.initial_errors=true;this.options.cls_portlet="ui-portlet-narrow";b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down","repeat","conditional"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or note for this step. It will be shown with the workflow.",value:this.node.annotation};var f=this.node.output_terminals&&Object.keys(this.node.output_terminals)[0];if(f){d[b.uuid()]={name:"pja__"+f+"__EmailAction",label:"Email notification",type:"boolean",value:String(Boolean(this.post_job_actions["EmailAction"+f])),ignore:"false",help:"An email notification will be send when the job has completed.",payload:{host:window.location.host}};d[b.uuid()]={name:"pja__"+f+"__DeleteIntermediatesAction",label:"Output cleanup",type:"boolean",value:String(Boolean(this.post_job_actions["DeleteIntermediatesAction"+f])),ignore:"false",help:"Delete intermediate outputs if they are not used as input for another job."};for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:""});var f={label:"Add Actions: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"integer",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(){var d=this;var e={tool_id:this.options.id,tool_version:this.options.version,inputs:this.tree.finalize()};console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"api/workflows/build_module";b.request({type:"POST",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
|
||||
@@ -1 +1 @@
|
||||
define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.text_enable=d.options.text_enable||"Enable";this.text_disable=d.options.text_disable||"Disable";this.field=c.field;this.default_value=c.default_value;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&((this.default_value===undefined)||((this.field.validate&&!this.field.validate())||!b||(b==this.default_value)||(Number(b)==Number(this.default_value))||(JSON.stringify(b)==JSON.stringify(this.default_value)))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.show();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html(this.text_disable)}else{this.reset();this.$field.hide();this.$title_optional.html(this.text_enable);this.field.value&&this.field.value(this.default_value)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+=a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
|
||||
define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.text_enable=d.options.text_enable||"Enable";this.text_disable=d.options.text_disable||"Disable";this.field=c.field;this.default_value=c.default_value;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&(((this.field.validate&&!this.field.validate())||!b||(b==this.default_value)||(Number(b)==Number(this.default_value))||(JSON.stringify(b)==JSON.stringify(this.default_value)))));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh()})},error:function(a){this.$error_text.html(a);this.$error.show();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html(this.text_disable)}else{this.reset();this.$field.hide();this.$title_optional.html(this.text_enable);this.field.value&&this.field.value(this.default_value)}this.app.trigger("refresh")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+=a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})});
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(g[u.type]){v=g[u.type](v)}if(t.skip){continue}if(t.validate&&!t.validate()){v=null}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
|
||||
define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(p,s){for(var n in s){var k=s[n];if(k.input){var u=k.input;var o=p;if(p!=""){o+="|"}o+=u.name;switch(u.type){case"repeat":var j="section-";var x=[];var r=null;for(var w in k){var q=w.indexOf(j);if(q!=-1){q+=j.length;x.push(parseInt(w.substr(q)));if(!r){r=w.substr(0,q)}}}x.sort(function(y,i){return y-i});var n=0;for(var l in x){c(o+"_"+n++,k[r+x[l]])}break;case"conditional":var v=b.app.field_list[u.id].value();if(g[u.test_param.type]){v=g[u.test_param.type](v)}d(o+"|"+u.test_param.name,u.id,v);var h=b.matchCase(u,v);if(h!=-1){c(o,s[u.id+"-section-"+h])}break;case"section":c("",k);break;default:var t=b.app.field_list[u.id];if(t&&t.value){var v=t.value();if(t.validate&&!t.validate()){v=null}if(g[u.type]){v=g[u.type](v)}if(u.ignore===undefined||(v!==null&&u.ignore!=v)){d(o,u.id,v);if(u.payload){for(var m in u.payload){d(m,u.id,u.payload[m])}}}}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
|
||||
File diff suppressed because one or more lines are too long
@@ -34,7 +34,7 @@ function MetricsLogger( options ){
|
||||
var self = this;
|
||||
|
||||
///** get the current user's id from bootstrapped data or options */
|
||||
self.userId = window.bootstrapped? window.bootstrapped.user.id: null;
|
||||
self.userId = ( window.bootstrapped && window.bootstrapped.user )? window.bootstrapped.user.id: null;
|
||||
self.userId = self.userId || options.userId || null;
|
||||
|
||||
/** the (optional) console to emit logs to */
|
||||
|
||||
@@ -10,7 +10,7 @@ ${h.css('base', 'jquery-ui/smoothness/jquery-ui')}
|
||||
## This avoids making two separate requests since the classic form requires the mako anyway.
|
||||
params = dict(trans.request.params)
|
||||
params['__dataset_id__'] = params.get('id', None)
|
||||
self.form_config = tool.to_json(trans, **params)
|
||||
self.form_config = tool.to_json(trans, params)
|
||||
self.form_config.update({
|
||||
'id' : tool.id,
|
||||
'job_id' : trans.security.encode_id( job.id ) if job else None,
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
## TEMPORARY: create tool dictionary in mako while both tool forms are in use.
|
||||
## This avoids making two separate requests since the classic form requires the mako anyway.
|
||||
from galaxy.tools.parameters import params_to_incoming
|
||||
incoming = {
|
||||
'__is_dynamic__' : False
|
||||
}
|
||||
incoming = {}
|
||||
params_to_incoming( incoming, tool.inputs, module.state.inputs, trans.app, to_html=False)
|
||||
self.form_config = tool.to_json(trans, **incoming)
|
||||
self.form_config = tool.to_json(trans, incoming, is_dynamic=False)
|
||||
self.form_config.update({
|
||||
'id' : tool.id,
|
||||
'job_id' : trans.security.encode_id( job.id ) if job else None,
|
||||
|
||||
Reference in New Issue
Block a user