galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
October 2014
- 2 participants
- 174 discussions
[galaxyproject/usegalaxy-playbook] cf32b4: Dropped survey slide; added training network slide...
by GitHub 17 Oct '14
by GitHub 17 Oct '14
17 Oct '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: cf32b45543bd46b62761071bc2af8ca73906ea07
https://github.com/galaxyproject/usegalaxy-playbook/commit/cf32b45543bd46b6…
Author: Dave Clements <clements(a)Dave-Clementss-MacBook-Pro.local>
Date: 2014-10-17 (Fri, 17 Oct 2014)
Changed paths:
A files/galaxy/common/static/welcome_img/GTN.png
M templates/galaxy/common/static/welcome.html.j2
Log Message:
-----------
Dropped survey slide; added training network slide.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3d030de0c470/
Changeset: 3d030de0c470
User: dannon
Date: 2014-10-17 12:07:24+00:00
Summary: Merge stable.
Affected #: 3 files
diff -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef -r 3d030de0c4708214f7add0c6391e0bd9024c045a .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-cb0c2ea402e4c82c7872177e874ce59de29c9c13 latest_2014.10.06
+e1404e285ccb9e52bd09c5827934cd0da1974acc latest_2014.10.06
diff -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef -r 3d030de0c4708214f7add0c6391e0bd9024c045a lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1336,6 +1336,7 @@
self.purged = False
self.purgable = purgable
self.external_filename = external_filename
+ self.external_extra_files_path = None
self._extra_files_path = extra_files_path
self.file_size = file_size
if uuid is None:
@@ -1359,9 +1360,20 @@
else:
self.external_filename = filename
file_name = property( get_file_name, set_file_name )
- @property
- def extra_files_path( self ):
- return self.object_store.get_filename( self, dir_only=True, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id )
+ def get_extra_files_path( self ):
+ # Unlike get_file_name - extrnal_extra_files_path is not backed by an
+ # actual database column so if SA instantiates this object - the
+ # attribute won't exist yet.
+ if not getattr( self, "external_extra_files_path", None ):
+ return self.object_store.get_filename( self, dir_only=True, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id )
+ else:
+ return os.path.abspath( self.external_extra_files_path )
+ def set_extra_files_path( self, extra_files_path ):
+ if not extra_files_path:
+ self.external_extra_files_path = None
+ else:
+ self.external_extra_files_path = extra_files_path
+ extra_files_path = property( get_extra_files_path, set_extra_files_path)
def _calculate_size( self ):
if self.external_filename:
try:
diff -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef -r 3d030de0c4708214f7add0c6391e0bd9024c045a scripts/set_metadata.py
--- a/scripts/set_metadata.py
+++ b/scripts/set_metadata.py
@@ -110,6 +110,8 @@
dataset = cPickle.load( open( filename_in ) ) # load DatasetInstance
if dataset_filename_override:
dataset.dataset.external_filename = dataset_filename_override
+ files_path = os.path.abspath(os.path.join( tool_job_working_directory, "dataset_%s_files" % (dataset.dataset.id) ))
+ dataset.dataset.external_extra_files_path = files_path
if dataset.dataset.id in existing_job_metadata_dict:
dataset.extension = existing_job_metadata_dict[ dataset.dataset.id ].get( 'ext', dataset.extension )
# Metadata FileParameter types may not be writable on a cluster node, and are therefore temporarily substituted with MetadataTempFiles
https://bitbucket.org/galaxy/galaxy-central/commits/acb838d9af91/
Changeset: acb838d9af91
User: dannon
Date: 2014-10-17 12:08:08+00:00
Summary: Fix typo noticed by nsoranzo.
Affected #: 1 file
diff -r 3d030de0c4708214f7add0c6391e0bd9024c045a -r acb838d9af911cfc7c79328ffa87472913e5529c lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1361,7 +1361,7 @@
self.external_filename = filename
file_name = property( get_file_name, set_file_name )
def get_extra_files_path( self ):
- # Unlike get_file_name - extrnal_extra_files_path is not backed by an
+ # Unlike get_file_name - external_extra_files_path is not backed by an
# actual database column so if SA instantiates this object - the
# attribute won't exist yet.
if not getattr( self, "external_extra_files_path", None ):
@@ -2449,7 +2449,7 @@
file_size = int( ldda.get_size() )
except OSError:
file_size = 0
-
+
rval = dict( id = ldda.id,
hda_ldda = 'ldda',
model_class = self.__class__.__name__,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Upload: Handle ftp api errors on client side
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0e8235a516d1/
Changeset: 0e8235a516d1
User: guerler
Date: 2014-10-16 23:59:08+00:00
Summary: Upload: Handle ftp api errors on client side
Affected #: 4 files
diff -r d404a6f6d01e6af5cbd35a427c474cee47fe963a -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef client/galaxy/scripts/mvc/upload/upload-ftp.js
--- a/client/galaxy/scripts/mvc/upload/upload-ftp.js
+++ b/client/galaxy/scripts/mvc/upload/upload-ftp.js
@@ -23,7 +23,8 @@
// load extension
Utils.get({
url : galaxy_config.root + 'api/ftp_files',
- success : function(ftp_files) { self._fill(ftp_files); }
+ success : function(ftp_files) { self._fill(ftp_files); },
+ error : function() { self._fill(); }
});
},
@@ -34,7 +35,7 @@
// fill table
_fill: function(ftp_files) {
- if (ftp_files.length > 0) {
+ if (ftp_files && ftp_files.length > 0) {
// add table
this.$el.find('#upload-ftp-content').html($(this._templateTable()));
diff -r d404a6f6d01e6af5cbd35a427c474cee47fe963a -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef lib/galaxy/webapps/galaxy/api/ftp_files.py
--- a/lib/galaxy/webapps/galaxy/api/ftp_files.py
+++ b/lib/galaxy/webapps/galaxy/api/ftp_files.py
@@ -112,7 +112,8 @@
response.append( dict( path = path,
size = statinfo.st_size,
ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
-
+ else:
+ raise exceptions.ConfigDoesNotAllowException( 'The given directory does not exist.' )
# sort by path
response = sorted(response, key=itemgetter("path"))
return response
diff -r d404a6f6d01e6af5cbd35a427c474cee47fe963a -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef static/scripts/mvc/upload/upload-ftp.js
--- a/static/scripts/mvc/upload/upload-ftp.js
+++ b/static/scripts/mvc/upload/upload-ftp.js
@@ -23,7 +23,8 @@
// load extension
Utils.get({
url : galaxy_config.root + 'api/ftp_files',
- success : function(ftp_files) { self._fill(ftp_files); }
+ success : function(ftp_files) { self._fill(ftp_files); },
+ error : function() { self._fill(); }
});
},
@@ -34,7 +35,7 @@
// fill table
_fill: function(ftp_files) {
- if (ftp_files.length > 0) {
+ if (ftp_files && ftp_files.length > 0) {
// add table
this.$el.find('#upload-ftp-content').html($(this._templateTable()));
diff -r d404a6f6d01e6af5cbd35a427c474cee47fe963a -r 0e8235a516d16724fbe1ba2dababb18f4b53c6ef static/scripts/packed/mvc/upload/upload-ftp.js
--- a/static/scripts/packed/mvc/upload/upload-ftp.js
+++ b/static/scripts/packed/mvc/upload/upload-ftp.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());a.get({url:galaxy_config.root+"api/ftp_files",success:function(d){b._fill(d)}})},events:{mousedown:function(b){b.preventDefault()}},_fill:function(c){if(c.length>0){this.$el.find("#upload-ftp-content").html($(this._templateTable()));var b=0;for(key in c){this.add(c[key]);b+=c[key].size}this.$el.find("#upload-ftp-number").html(c.length+" files");this.$el.find("#upload-ftp-disk").html(a.bytesToString(b,true))}else{this.$el.find("#upload-ftp-content").html($(this._templateInfo()))}this.$el.find("#upload-ftp-wait").hide()},add:function(f){var d=this;var e=$(this._templateRow(f));var b=e.find(".icon");$(this.el).find("tbody").append(e);var c="";if(this._find(f)){c=this.options.class_remove}else{c=this.options.class_add}b.addClass(c);e.on("click",function(){var g=d._find(f);b.removeClass();if(!g){d.app.uploadbox.add([{mode:"ftp",name:f.path,size:f.size,path:f.path}]);b.addClass(d.options.class_remove)}else{d.app.collection.remove(g);b.addClass(d.options.class_add)}})},_find:function(f){var c=this.app.collection.where({file_path:f.path});var b=null;for(var d in c){var e=c[d];if(e.get("status")=="init"&&e.get("file_mode")=="ftp"){b=e.get("id")}}return b},_templateRow:function(b){return'<tr class="upload-ftp-row" style="cursor: pointer;"><td><div class="icon"/></td><td style="width: 200px"><p style="width: inherit; word-wrap: break-word;">'+b.path+'</p></td><td style="white-space: nowrap;">'+a.bytesToString(b.size)+'</td><td style="white-space: nowrap;">'+b.ctime+"</td></tr>"},_templateTable:function(){return'<span style="whitespace: nowrap; float: left;">Available files: </span><span style="whitespace: nowrap; float: right;"><span class="upload-icon fa fa-file-text-o"/><span id="upload-ftp-number"/> <span class="upload-icon fa fa-hdd-o"/><span id="upload-ftp-disk"/></span><table class="grid" style="float: left;"><thead><tr><th></th><th>Name</th><th>Size</th><th>Created</th></tr></thead><tbody></tbody></table>'},_templateInfo:function(){return'<div class="upload-ftp-warning warningmessage">Your FTP directory does not contain any files.</div>'},_template:function(){return'<div class="upload-ftp"><div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/><div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>'+this.app.options.ftp_upload_site+'</strong> using your Galaxy credentials (email address and password).</div><div id="upload-ftp-content"></div><div>'}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());a.get({url:galaxy_config.root+"api/ftp_files",success:function(d){b._fill(d)},error:function(){b._fill()}})},events:{mousedown:function(b){b.preventDefault()}},_fill:function(c){if(c&&c.length>0){this.$el.find("#upload-ftp-content").html($(this._templateTable()));var b=0;for(key in c){this.add(c[key]);b+=c[key].size}this.$el.find("#upload-ftp-number").html(c.length+" files");this.$el.find("#upload-ftp-disk").html(a.bytesToString(b,true))}else{this.$el.find("#upload-ftp-content").html($(this._templateInfo()))}this.$el.find("#upload-ftp-wait").hide()},add:function(f){var d=this;var e=$(this._templateRow(f));var b=e.find(".icon");$(this.el).find("tbody").append(e);var c="";if(this._find(f)){c=this.options.class_remove}else{c=this.options.class_add}b.addClass(c);e.on("click",function(){var g=d._find(f);b.removeClass();if(!g){d.app.uploadbox.add([{mode:"ftp",name:f.path,size:f.size,path:f.path}]);b.addClass(d.options.class_remove)}else{d.app.collection.remove(g);b.addClass(d.options.class_add)}})},_find:function(f){var c=this.app.collection.where({file_path:f.path});var b=null;for(var d in c){var e=c[d];if(e.get("status")=="init"&&e.get("file_mode")=="ftp"){b=e.get("id")}}return b},_templateRow:function(b){return'<tr class="upload-ftp-row" style="cursor: pointer;"><td><div class="icon"/></td><td style="width: 200px"><p style="width: inherit; word-wrap: break-word;">'+b.path+'</p></td><td style="white-space: nowrap;">'+a.bytesToString(b.size)+'</td><td style="white-space: nowrap;">'+b.ctime+"</td></tr>"},_templateTable:function(){return'<span style="whitespace: nowrap; float: left;">Available files: </span><span style="whitespace: nowrap; float: right;"><span class="upload-icon fa fa-file-text-o"/><span id="upload-ftp-number"/> <span class="upload-icon fa fa-hdd-o"/><span id="upload-ftp-disk"/></span><table class="grid" style="float: left;"><thead><tr><th></th><th>Name</th><th>Size</th><th>Created</th></tr></thead><tbody></tbody></table>'},_templateInfo:function(){return'<div class="upload-ftp-warning warningmessage">Your FTP directory does not contain any files.</div>'},_template:function(){return'<div class="upload-ftp"><div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/><div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>'+this.app.options.ftp_upload_site+'</strong> using your Galaxy credentials (email address and password).</div><div id="upload-ftp-content"></div><div>'}})});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Api: Ftp files return empty list instead of raising error if directory is missing
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d404a6f6d01e/
Changeset: d404a6f6d01e
User: guerler
Date: 2014-10-16 23:47:55+00:00
Summary: Api: Ftp files return empty list instead of raising error if directory is missing
Affected #: 1 file
diff -r eb28a9bcb4d9ca99613b667300095ce8a52f7ae3 -r d404a6f6d01e6af5cbd35a427c474cee47fe963a lib/galaxy/webapps/galaxy/api/ftp_files.py
--- a/lib/galaxy/webapps/galaxy/api/ftp_files.py
+++ b/lib/galaxy/webapps/galaxy/api/ftp_files.py
@@ -112,8 +112,7 @@
response.append( dict( path = path,
size = statinfo.st_size,
ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
- else:
- raise exceptions.ConfigDoesNotAllowException( 'The given directory does not exist.' )
+
# sort by path
response = sorted(response, key=itemgetter("path"))
return response
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Tool's command might be separated by a newline, so we should use the general form split here, not specifically on spaces. Pointed out by @kellrott.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/eb28a9bcb4d9/
Changeset: eb28a9bcb4d9
User: dannon
Date: 2014-10-16 23:37:30+00:00
Summary: Tool's command might be separated by a newline, so we should use the general form split here, not specifically on spaces. Pointed out by @kellrott.
Affected #: 1 file
diff -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 -r eb28a9bcb4d9ca99613b667300095ce8a52f7ae3 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -699,7 +699,7 @@
def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
- recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
@@ -825,7 +825,7 @@
tool_tup = ( os.path.abspath( tool.config_file ), os.path.split( tool.config_file )[-1] )
tarball_files.append( tool_tup )
# TODO: This feels hacky.
- tool_command = tool.command.strip().split( ' ' )[0]
+ tool_command = tool.command.strip().split()[0]
tool_path = os.path.dirname( os.path.abspath( tool.config_file ) )
# Add the tool XML to the tuple that will be used to populate the tarball.
if os.path.exists( os.path.join( tool_path, tool_command ) ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Fix Circster background bug in Firefox by correctly specifying colors.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d09b44c5f228/
Changeset: d09b44c5f228
User: jgoecks
Date: 2014-10-16 18:15:50+00:00
Summary: Fix Circster background bug in Firefox by correctly specifying colors.
Affected #: 3 files
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 client/galaxy/scripts/viz/circster.js
--- a/client/galaxy/scripts/viz/circster.js
+++ b/client/galaxy/scripts/viz/circster.js
@@ -404,11 +404,11 @@
/* ----------------------- Public Methods ------------------------- */
initialize: function(options) {
- this.bg_stroke = 'ddd';
+ this.bg_stroke = '#ddd';
// Fill color when loading data.
- this.loading_bg_fill = 'ffc';
+ this.loading_bg_fill = '#ffc';
// Fill color when data has been loaded.
- this.bg_fill = 'ddd';
+ this.bg_fill = '#ddd';
this.total_gap = options.total_gap;
this.track = options.track;
this.radius_bounds = options.radius_bounds;
@@ -688,8 +688,8 @@
// Use a single arc for rendering data.
this.innerRadius = this.radius_bounds[0];
this.radius_bounds[0] = this.radius_bounds[1];
- this.bg_stroke = 'fff';
- this.bg_fill = 'fff';
+ this.bg_stroke = '#fff';
+ this.bg_fill = '#fff';
// Minimum arc distance for labels to be applied.
this.min_arc_len = 0.05;
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 static/scripts/packed/viz/circster.js
--- a/static/scripts/packed/viz/circster.js
+++ b/static/scripts/packed/viz/circster.js
@@ -1,1 +1,1 @@
-require(["utils/utils","libs/farbtastic",],function(a){a.cssLoadFile("static/style/circster.css")});define(["libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,m,j,c){var n=Backbone.Model.extend({is_visible:function(r,o){var p=r.getBoundingClientRect(),q=$("svg")[0].getBoundingClientRect();if(p.right<0||p.left>q.right||p.bottom<0||p.top>q.bottom){return false}return true}});var i={drawTicks:function(s,r,w,q,o){var v=s.append("g").selectAll("g").data(r).enter().append("g").selectAll("g").data(w).enter().append("g").attr("class","tick").attr("transform",function(x){return"rotate("+(x.angle*180/Math.PI-90)+")translate("+x.radius+",0)"});var u=[],t=[],p=function(x){return x.angle>Math.PI?"end":null};if(o){u=[0,0,0,-4];t=[4,0,"",".35em"];p=null}else{u=[1,0,4,0];t=[0,4,".35em",""]}v.append("line").attr("x1",u[0]).attr("y1",u[1]).attr("x2",u[2]).attr("y1",u[3]).style("stroke","#000");return v.append("text").attr("x",t[0]).attr("y",t[1]).attr("dx",t[2]).attr("dy",t[3]).attr("text-anchor",p).attr("transform",q).text(function(x){return x.label})},formatNum:function(p,o){if(o===undefined){o=2}if(p===null){return null}var r=null;if(Math.abs(p)<1){r=p.toPrecision(o)}else{var q=Math.round(p.toPrecision(o));p=Math.abs(p);if(p<1000){r=q}else{if(p<1000000){r=Math.round((q/1000).toPrecision(3)).toFixed(0)+"K"}else{if(p<1000000000){r=Math.round((q/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return r}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(o){this.genome=o.genome;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var p=this.model.get("config");p.get("arc_dataset_height").on("change:value",this.update_track_bounds,this);p.get("track_gap").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var q=this.get_circular_tracks(),s=this.model.get("config").get_value("arc_dataset_height"),r=this.model.get("config").get_value("track_gap"),o=Math.min(this.$el.width(),this.$el.height())-20,u=o/2-q.length*(s+r)+r-this.label_arc_height,t=m.range(u,o/2,s+r);var p=this;return h.map(t,function(v){return[v,v+s]})},render:function(){var x=this,o=x.$el.width(),w=x.$el.height(),t=this.get_circular_tracks(),r=this.get_chord_tracks(),q=x.model.get("config").get_value("total_gap"),s=this.get_tracks_bounds(),p=m.select(x.$el[0]).append("svg").attr("width",o).attr("height",w).attr("pointer-events","all").append("svg:g").call(m.behavior.zoom().on("zoom",function(){var y=m.event.scale;p.attr("transform","translate("+m.event.translate+") scale("+y+")");if(x.scale!==y){if(x.zoom_drag_timeout){clearTimeout(x.zoom_drag_timeout)}x.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+o/2+","+w/2+")").append("svg:g").attr("class","tracks");this.circular_views=t.map(function(z,A){var y=new e({el:p.append("g")[0],track:z,radius_bounds:s[A],genome:x.genome,total_gap:q});y.render();return y});this.chords_views=r.map(function(z){var y=new k({el:p.append("g")[0],track:z,radius_bounds:s[0],genome:x.genome,total_gap:q});y.render();return y});var v=this.circular_views[this.circular_views.length-1].radius_bounds[1],u=[v,v+this.label_arc_height];this.label_track_view=new b({el:p.append("g")[0],track:new d(),radius_bounds:u,genome:x.genome,total_gap:q});this.label_track_view.render()},add_track:function(u){var p=this.model.get("config").get_value("total_gap");if(u.get("track_type")==="DiagonalHeatmapTrack"){var q=this.circular_views[0].radius_bounds,t=new k({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:q,genome:this.genome,total_gap:p});t.render();this.chords_views.push(t)}else{var s=this.get_tracks_bounds();h.each(this.circular_views,function(v,w){v.update_radius_bounds(s[w])});h.each(this.chords_views,function(v){v.update_radius_bounds(s[0])});var r=this.circular_views.length,o=new e({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:s[r],genome:this.genome,total_gap:p});o.render();this.circular_views.push(o)}},remove_track:function(p,r,q){var o=this.circular_views[q.index];this.circular_views.splice(q.index,1);o.$el.remove();var s=this.get_tracks_bounds();h.each(this.circular_views,function(t,u){t.update_radius_bounds(s[u])})},update_track_bounds:function(){var o=this.get_tracks_bounds();h.each(this.circular_views,function(p,q){p.update_radius_bounds(o[q])});h.each(this.chords_views,function(p){p.update_radius_bounds(o[0])})}});var l=Backbone.View.extend({tagName:"g",initialize:function(o){this.bg_stroke="ddd";this.loading_bg_fill="ffc";this.bg_fill="ddd";this.total_gap=o.total_gap;this.track=o.track;this.radius_bounds=o.radius_bounds;this.genome=o.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=m.select(this.$el[0])},get_fill_color:function(){var o=this.track.get("config").get_value("block_color");if(!o){o=this.track.get("config").get_value("color")}return o},render:function(){var s=this.parent_elt;var r=this.chroms_layout,u=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),o=s.selectAll("g").data(r).enter().append("svg:g"),q=o.append("path").attr("d",u).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);q.append("title").text(function(w){return w.data.chrom});var p=this,t=p.track.get("data_manager"),v=(t?t.data_is_ready():true);$.when(v).then(function(){$.when(p._render_data(s)).then(function(){q.style("fill",p.bg_fill);p.render_labels()})})},render_labels:function(){},update_radius_bounds:function(p){this.radius_bounds=p;var o=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",o);this._transition_chrom_data();this._transition_labels()},update_scale:function(r){var q=this.scale;this.scale=r;if(r<=q){return}var p=this,o=new n();this.parent_elt.selectAll("path.chrom-data").filter(function(t,s){return o.is_visible(this)}).each(function(y,u){var x=m.select(this),t=x.attr("chrom"),w=p.genome.get_chrom_region(t),v=p.track.get("data_manager"),s;if(!v.can_get_more_detailed_data(w)){return}s=p.track.get("data_manager").get_more_detailed_data(w,"Coverage",0,r);$.when(s).then(function(B){x.remove();p._update_data_bounds();var A=h.find(p.chroms_layout,function(C){return C.data.chrom===t});var z=p.get_fill_color();p._render_chrom_data(p.parent_elt,A,B).style("stroke",z).style("fill",z)})});return p},_transition_chrom_data:function(){var p=this.track,r=this.chroms_layout,o=this.parent_elt.selectAll("g>path.chrom-data"),s=o[0].length;if(s>0){var q=this;$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=h.reject(h.map(v,function(w,x){var y=null,z=q._get_path_function(r[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});var t=p.get("config").get_value("color");o.each(function(x,w){m.select(this).transition().duration(1000).style("stroke",t).style("fill",t).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(p){var o=this.data_bounds;this.data_bounds=p||this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));this._transition_chrom_data()},_render_data:function(r){var q=this,p=this.chroms_layout,o=this.track,s=$.Deferred();$.when(o.get("data_manager").get_genome_wide_data(this.genome)).then(function(u){q.data_bounds=q.get_data_bounds(u);o.get("config").set_value("min_value",q.data_bounds[0],{silent:true});o.get("config").set_value("max_value",q.data_bounds[1],{silent:true});layout_and_data=h.zip(p,u),chroms_data_layout=h.map(layout_and_data,function(v){var w=v[0],x=v[1];return q._render_chrom_data(r,w,x)});var t=q.get_fill_color();q.parent_elt.selectAll("path.chrom-data").style("stroke",t).style("fill",t);s.resolve(r)});return s},_render_chrom_data:function(o,p,q){},_get_path_function:function(p,o){},_chroms_layout:function(){var p=this.genome.get_chroms_info(),r=m.layout.pie().value(function(t){return t.len}).sort(null),s=r(p),o=2*Math.PI*this.total_gap/p.length,q=h.map(s,function(v,u){var t=v.endAngle-o;v.endAngle=(t>v.startAngle?t:v.startAngle);return v});return q}});var b=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.05},_render_data:function(q){var p=this,o=q.selectAll("g");o.selectAll("path").attr("id",function(u){return"label-"+u.data.chrom});o.append("svg:text").filter(function(u){return u.endAngle-u.startAngle>p.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(u){return"#label-"+u.data.chrom}).attr("startOffset","25%").text(function(u){return u.data.chrom});var r=function(w){var u=(w.endAngle-w.startAngle)/w.value,v=m.range(0,w.value,25000000).map(function(x,y){return{radius:p.innerRadius,angle:x*u+w.startAngle,label:y===0?0:(y%3?null:p.formatNum(x))}});if(v.length<4){v[v.length-1].label=p.formatNum(Math.round((v[v.length-1].angle-w.startAngle)/u))}return v};var t=function(u){return u.angle>Math.PI?"rotate(180)translate(-16)":null};var s=h.filter(this.chroms_layout,function(u){return u.endAngle-u.startAngle>p.min_arc_len});this.drawTicks(this.parent_elt,s,r,t)}});h.extend(b.prototype,i);var g=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);var p=this.track.get("config");p.get("min_value").on("change:value",this._update_min_max,this);p.get("max_value").on("change:value",this._update_min_max,this);p.get("color").on("change:value",this._transition_chrom_data,this)},_update_min_max:function(){var p=this.track.get("config"),o=[p.get_value("min_value"),p.get_value("max_value")];this._update_data_bounds(o);this.parent_elt.selectAll(".min_max").text(function(r,q){return o[q]})},_quantile:function(p,o){p.sort(m.ascending);return m.quantile(p,o)},_render_chrom_data:function(o,r,p){var s=this._get_path_function(r,p);if(!s){return null}var q=o.datum(p.data),t=q.append("path").attr("class","chrom-data").attr("chrom",r.data.chrom).attr("d",s);return t},_get_path_function:function(r,q){if(typeof q==="string"||!q.data||q.data.length===0){return null}var o=m.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var s=m.scale.linear().domain([0,q.data.length]).range([r.startAngle,r.endAngle]);var p=m.svg.line.radial().interpolate("linear").radius(function(t){return o(t[1])}).angle(function(u,t){return s(t)});return m.svg.area.radial().interpolate(p.interpolate()).innerRadius(o(0)).outerRadius(p.radius()).angle(p.angle())},render_labels:function(){var o=this,q=function(){return"rotate(90)"};var p=this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true).classed("min_max",true);h.each(p,function(r){$(r).click(function(){var s=new c.ConfigSettingCollectionView({collection:o.track.get("config")});s.render_in_modal("Configure Track")})})},_transition_labels:function(){if(this.data_bounds.length===0){return}var p=this,r=h.filter(this.chroms_layout,function(s){return s.endAngle-s.startAngle>0.08}),q=h.filter(r,function(t,s){return s%3===0}),o=h.flatten(h.map(q,function(s){return p._data_bounds_ticks_fn()(s)}));this.parent_elt.selectAll("g.tick").data(o).transition().attr("transform",function(s){return"rotate("+(s.angle*180/Math.PI-90)+")translate("+s.radius+",0)"})},_data_bounds_ticks_fn:function(){var o=this;visibleChroms=0;return function(p){return[{radius:o.radius_bounds[0],angle:p.startAngle,label:o.formatNum(o.data_bounds[0])},{radius:o.radius_bounds[1],angle:p.startAngle,label:o.formatNum(o.data_bounds[1])}]}},get_data_bounds:function(o){}});h.extend(g.prototype,i);var e=g.extend({get_data_bounds:function(p){var o=h.flatten(h.map(p,function(q){if(q){return h.map(q.data,function(r){return parseInt(r[1],10)||0})}else{return 0}}));return[h.min(o),this._quantile(o,0.98)||h.max(o)]}});var k=l.extend({render:function(){var o=this;$.when(o.track.get("data_manager").data_is_ready()).then(function(){$.when(o.track.get("data_manager").get_genome_wide_data(o.genome)).then(function(r){var q=[],p=o.genome.get_chroms_info();h.each(r,function(v,u){var s=p[u].chrom;var t=h.map(v.data,function(x){var w=o._get_region_angle(s,x[1]),y=o._get_region_angle(x[3],x[4]);return{source:{startAngle:w,endAngle:w+0.01},target:{startAngle:y,endAngle:y+0.01}}});q=q.concat(t)});o.parent_elt.append("g").attr("class","chord").selectAll("path").data(q).enter().append("path").style("fill",o.get_fill_color()).attr("d",m.svg.chord().radius(o.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(o){this.radius_bounds=o;this.parent_elt.selectAll("path").transition().attr("d",m.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(q,o){var p=h.find(this.chroms_layout,function(r){return r.data.chrom===q});return p.endAngle-((p.endAngle-p.startAngle)*(p.data.len-o)/p.data.len)}});var f=Backbone.View.extend({initialize:function(){var o=new j.Genome(galaxy_config.app.genome),p=new j.GenomeVisualization(galaxy_config.app.viz_config);p.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"track_gap",label:"Gap Between Tracks",type:"int",value:5,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var r=new a({el:$("#center .unified-panel-body"),genome:o,model:p});r.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var q=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){j.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",p.get("dbkey"),function(s){p.add_tracks(s)})}},{icon_class:"gear",title:"Settings",on_click:function(){var s=new c.ConfigSettingCollectionView({collection:p.get("config")});s.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:p.get("vis_id"),title:p.get("title"),dbkey:p.get("dbkey"),type:"trackster",vis_json:JSON.stringify(p)}}).success(function(s){Galaxy.modal.hide();p.set("vis_id",s.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});q.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(q.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
+require(["utils/utils","libs/farbtastic",],function(a){a.cssLoadFile("static/style/circster.css")});define(["libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,m,j,c){var n=Backbone.Model.extend({is_visible:function(r,o){var p=r.getBoundingClientRect(),q=$("svg")[0].getBoundingClientRect();if(p.right<0||p.left>q.right||p.bottom<0||p.top>q.bottom){return false}return true}});var i={drawTicks:function(s,r,w,q,o){var v=s.append("g").selectAll("g").data(r).enter().append("g").selectAll("g").data(w).enter().append("g").attr("class","tick").attr("transform",function(x){return"rotate("+(x.angle*180/Math.PI-90)+")translate("+x.radius+",0)"});var u=[],t=[],p=function(x){return x.angle>Math.PI?"end":null};if(o){u=[0,0,0,-4];t=[4,0,"",".35em"];p=null}else{u=[1,0,4,0];t=[0,4,".35em",""]}v.append("line").attr("x1",u[0]).attr("y1",u[1]).attr("x2",u[2]).attr("y1",u[3]).style("stroke","#000");return v.append("text").attr("x",t[0]).attr("y",t[1]).attr("dx",t[2]).attr("dy",t[3]).attr("text-anchor",p).attr("transform",q).text(function(x){return x.label})},formatNum:function(p,o){if(o===undefined){o=2}if(p===null){return null}var r=null;if(Math.abs(p)<1){r=p.toPrecision(o)}else{var q=Math.round(p.toPrecision(o));p=Math.abs(p);if(p<1000){r=q}else{if(p<1000000){r=Math.round((q/1000).toPrecision(3)).toFixed(0)+"K"}else{if(p<1000000000){r=Math.round((q/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return r}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(o){this.genome=o.genome;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var p=this.model.get("config");p.get("arc_dataset_height").on("change:value",this.update_track_bounds,this);p.get("track_gap").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var q=this.get_circular_tracks(),s=this.model.get("config").get_value("arc_dataset_height"),r=this.model.get("config").get_value("track_gap"),o=Math.min(this.$el.width(),this.$el.height())-20,u=o/2-q.length*(s+r)+r-this.label_arc_height,t=m.range(u,o/2,s+r);var p=this;return h.map(t,function(v){return[v,v+s]})},render:function(){var x=this,o=x.$el.width(),w=x.$el.height(),t=this.get_circular_tracks(),r=this.get_chord_tracks(),q=x.model.get("config").get_value("total_gap"),s=this.get_tracks_bounds(),p=m.select(x.$el[0]).append("svg").attr("width",o).attr("height",w).attr("pointer-events","all").append("svg:g").call(m.behavior.zoom().on("zoom",function(){var y=m.event.scale;p.attr("transform","translate("+m.event.translate+") scale("+y+")");if(x.scale!==y){if(x.zoom_drag_timeout){clearTimeout(x.zoom_drag_timeout)}x.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+o/2+","+w/2+")").append("svg:g").attr("class","tracks");this.circular_views=t.map(function(z,A){var y=new e({el:p.append("g")[0],track:z,radius_bounds:s[A],genome:x.genome,total_gap:q});y.render();return y});this.chords_views=r.map(function(z){var y=new k({el:p.append("g")[0],track:z,radius_bounds:s[0],genome:x.genome,total_gap:q});y.render();return y});var v=this.circular_views[this.circular_views.length-1].radius_bounds[1],u=[v,v+this.label_arc_height];this.label_track_view=new b({el:p.append("g")[0],track:new d(),radius_bounds:u,genome:x.genome,total_gap:q});this.label_track_view.render()},add_track:function(u){var p=this.model.get("config").get_value("total_gap");if(u.get("track_type")==="DiagonalHeatmapTrack"){var q=this.circular_views[0].radius_bounds,t=new k({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:q,genome:this.genome,total_gap:p});t.render();this.chords_views.push(t)}else{var s=this.get_tracks_bounds();h.each(this.circular_views,function(v,w){v.update_radius_bounds(s[w])});h.each(this.chords_views,function(v){v.update_radius_bounds(s[0])});var r=this.circular_views.length,o=new e({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:s[r],genome:this.genome,total_gap:p});o.render();this.circular_views.push(o)}},remove_track:function(p,r,q){var o=this.circular_views[q.index];this.circular_views.splice(q.index,1);o.$el.remove();var s=this.get_tracks_bounds();h.each(this.circular_views,function(t,u){t.update_radius_bounds(s[u])})},update_track_bounds:function(){var o=this.get_tracks_bounds();h.each(this.circular_views,function(p,q){p.update_radius_bounds(o[q])});h.each(this.chords_views,function(p){p.update_radius_bounds(o[0])})}});var l=Backbone.View.extend({tagName:"g",initialize:function(o){this.bg_stroke="#ddd";this.loading_bg_fill="#ffc";this.bg_fill="#ddd";this.total_gap=o.total_gap;this.track=o.track;this.radius_bounds=o.radius_bounds;this.genome=o.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=m.select(this.$el[0])},get_fill_color:function(){var o=this.track.get("config").get_value("block_color");if(!o){o=this.track.get("config").get_value("color")}return o},render:function(){var s=this.parent_elt;var r=this.chroms_layout,u=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),o=s.selectAll("g").data(r).enter().append("svg:g"),q=o.append("path").attr("d",u).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);q.append("title").text(function(w){return w.data.chrom});var p=this,t=p.track.get("data_manager"),v=(t?t.data_is_ready():true);$.when(v).then(function(){$.when(p._render_data(s)).then(function(){q.style("fill",p.bg_fill);p.render_labels()})})},render_labels:function(){},update_radius_bounds:function(p){this.radius_bounds=p;var o=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",o);this._transition_chrom_data();this._transition_labels()},update_scale:function(r){var q=this.scale;this.scale=r;if(r<=q){return}var p=this,o=new n();this.parent_elt.selectAll("path.chrom-data").filter(function(t,s){return o.is_visible(this)}).each(function(y,u){var x=m.select(this),t=x.attr("chrom"),w=p.genome.get_chrom_region(t),v=p.track.get("data_manager"),s;if(!v.can_get_more_detailed_data(w)){return}s=p.track.get("data_manager").get_more_detailed_data(w,"Coverage",0,r);$.when(s).then(function(B){x.remove();p._update_data_bounds();var A=h.find(p.chroms_layout,function(C){return C.data.chrom===t});var z=p.get_fill_color();p._render_chrom_data(p.parent_elt,A,B).style("stroke",z).style("fill",z)})});return p},_transition_chrom_data:function(){var p=this.track,r=this.chroms_layout,o=this.parent_elt.selectAll("g>path.chrom-data"),s=o[0].length;if(s>0){var q=this;$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=h.reject(h.map(v,function(w,x){var y=null,z=q._get_path_function(r[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});var t=p.get("config").get_value("color");o.each(function(x,w){m.select(this).transition().duration(1000).style("stroke",t).style("fill",t).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(p){var o=this.data_bounds;this.data_bounds=p||this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));this._transition_chrom_data()},_render_data:function(r){var q=this,p=this.chroms_layout,o=this.track,s=$.Deferred();$.when(o.get("data_manager").get_genome_wide_data(this.genome)).then(function(u){q.data_bounds=q.get_data_bounds(u);o.get("config").set_value("min_value",q.data_bounds[0],{silent:true});o.get("config").set_value("max_value",q.data_bounds[1],{silent:true});layout_and_data=h.zip(p,u),chroms_data_layout=h.map(layout_and_data,function(v){var w=v[0],x=v[1];return q._render_chrom_data(r,w,x)});var t=q.get_fill_color();q.parent_elt.selectAll("path.chrom-data").style("stroke",t).style("fill",t);s.resolve(r)});return s},_render_chrom_data:function(o,p,q){},_get_path_function:function(p,o){},_chroms_layout:function(){var p=this.genome.get_chroms_info(),r=m.layout.pie().value(function(t){return t.len}).sort(null),s=r(p),o=2*Math.PI*this.total_gap/p.length,q=h.map(s,function(v,u){var t=v.endAngle-o;v.endAngle=(t>v.startAngle?t:v.startAngle);return v});return q}});var b=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="#fff";this.bg_fill="#fff";this.min_arc_len=0.05},_render_data:function(q){var p=this,o=q.selectAll("g");o.selectAll("path").attr("id",function(u){return"label-"+u.data.chrom});o.append("svg:text").filter(function(u){return u.endAngle-u.startAngle>p.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(u){return"#label-"+u.data.chrom}).attr("startOffset","25%").text(function(u){return u.data.chrom});var r=function(w){var u=(w.endAngle-w.startAngle)/w.value,v=m.range(0,w.value,25000000).map(function(x,y){return{radius:p.innerRadius,angle:x*u+w.startAngle,label:y===0?0:(y%3?null:p.formatNum(x))}});if(v.length<4){v[v.length-1].label=p.formatNum(Math.round((v[v.length-1].angle-w.startAngle)/u))}return v};var t=function(u){return u.angle>Math.PI?"rotate(180)translate(-16)":null};var s=h.filter(this.chroms_layout,function(u){return u.endAngle-u.startAngle>p.min_arc_len});this.drawTicks(this.parent_elt,s,r,t)}});h.extend(b.prototype,i);var g=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);var p=this.track.get("config");p.get("min_value").on("change:value",this._update_min_max,this);p.get("max_value").on("change:value",this._update_min_max,this);p.get("color").on("change:value",this._transition_chrom_data,this)},_update_min_max:function(){var p=this.track.get("config"),o=[p.get_value("min_value"),p.get_value("max_value")];this._update_data_bounds(o);this.parent_elt.selectAll(".min_max").text(function(r,q){return o[q]})},_quantile:function(p,o){p.sort(m.ascending);return m.quantile(p,o)},_render_chrom_data:function(o,r,p){var s=this._get_path_function(r,p);if(!s){return null}var q=o.datum(p.data),t=q.append("path").attr("class","chrom-data").attr("chrom",r.data.chrom).attr("d",s);return t},_get_path_function:function(r,q){if(typeof q==="string"||!q.data||q.data.length===0){return null}var o=m.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var s=m.scale.linear().domain([0,q.data.length]).range([r.startAngle,r.endAngle]);var p=m.svg.line.radial().interpolate("linear").radius(function(t){return o(t[1])}).angle(function(u,t){return s(t)});return m.svg.area.radial().interpolate(p.interpolate()).innerRadius(o(0)).outerRadius(p.radius()).angle(p.angle())},render_labels:function(){var o=this,q=function(){return"rotate(90)"};var p=this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true).classed("min_max",true);h.each(p,function(r){$(r).click(function(){var s=new c.ConfigSettingCollectionView({collection:o.track.get("config")});s.render_in_modal("Configure Track")})})},_transition_labels:function(){if(this.data_bounds.length===0){return}var p=this,r=h.filter(this.chroms_layout,function(s){return s.endAngle-s.startAngle>0.08}),q=h.filter(r,function(t,s){return s%3===0}),o=h.flatten(h.map(q,function(s){return p._data_bounds_ticks_fn()(s)}));this.parent_elt.selectAll("g.tick").data(o).transition().attr("transform",function(s){return"rotate("+(s.angle*180/Math.PI-90)+")translate("+s.radius+",0)"})},_data_bounds_ticks_fn:function(){var o=this;visibleChroms=0;return function(p){return[{radius:o.radius_bounds[0],angle:p.startAngle,label:o.formatNum(o.data_bounds[0])},{radius:o.radius_bounds[1],angle:p.startAngle,label:o.formatNum(o.data_bounds[1])}]}},get_data_bounds:function(o){}});h.extend(g.prototype,i);var e=g.extend({get_data_bounds:function(p){var o=h.flatten(h.map(p,function(q){if(q){return h.map(q.data,function(r){return parseInt(r[1],10)||0})}else{return 0}}));return[h.min(o),this._quantile(o,0.98)||h.max(o)]}});var k=l.extend({render:function(){var o=this;$.when(o.track.get("data_manager").data_is_ready()).then(function(){$.when(o.track.get("data_manager").get_genome_wide_data(o.genome)).then(function(r){var q=[],p=o.genome.get_chroms_info();h.each(r,function(v,u){var s=p[u].chrom;var t=h.map(v.data,function(x){var w=o._get_region_angle(s,x[1]),y=o._get_region_angle(x[3],x[4]);return{source:{startAngle:w,endAngle:w+0.01},target:{startAngle:y,endAngle:y+0.01}}});q=q.concat(t)});o.parent_elt.append("g").attr("class","chord").selectAll("path").data(q).enter().append("path").style("fill",o.get_fill_color()).attr("d",m.svg.chord().radius(o.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(o){this.radius_bounds=o;this.parent_elt.selectAll("path").transition().attr("d",m.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(q,o){var p=h.find(this.chroms_layout,function(r){return r.data.chrom===q});return p.endAngle-((p.endAngle-p.startAngle)*(p.data.len-o)/p.data.len)}});var f=Backbone.View.extend({initialize:function(){var o=new j.Genome(galaxy_config.app.genome),p=new j.GenomeVisualization(galaxy_config.app.viz_config);p.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"track_gap",label:"Gap Between Tracks",type:"int",value:5,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var r=new a({el:$("#center .unified-panel-body"),genome:o,model:p});r.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var q=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){j.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",p.get("dbkey"),function(s){p.add_tracks(s)})}},{icon_class:"gear",title:"Settings",on_click:function(){var s=new c.ConfigSettingCollectionView({collection:p.get("config")});s.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:p.get("vis_id"),title:p.get("title"),dbkey:p.get("dbkey"),type:"trackster",vis_json:JSON.stringify(p)}}).success(function(s){Galaxy.modal.hide();p.set("vis_id",s.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});q.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(q.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 static/scripts/viz/circster.js
--- a/static/scripts/viz/circster.js
+++ b/static/scripts/viz/circster.js
@@ -404,11 +404,11 @@
/* ----------------------- Public Methods ------------------------- */
initialize: function(options) {
- this.bg_stroke = 'ddd';
+ this.bg_stroke = '#ddd';
// Fill color when loading data.
- this.loading_bg_fill = 'ffc';
+ this.loading_bg_fill = '#ffc';
// Fill color when data has been loaded.
- this.bg_fill = 'ddd';
+ this.bg_fill = '#ddd';
this.total_gap = options.total_gap;
this.track = options.track;
this.radius_bounds = options.radius_bounds;
@@ -688,8 +688,8 @@
// Use a single arc for rendering data.
this.innerRadius = this.radius_bounds[0];
this.radius_bounds[0] = this.radius_bounds[1];
- this.bg_stroke = 'fff';
- this.bg_fill = 'fff';
+ this.bg_stroke = '#fff';
+ this.bg_fill = '#fff';
// Minimum arc distance for labels to be applied.
this.min_arc_len = 0.05;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: S3ObjectStore will create the bucket for you when possible if it does not exist.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/70c404e681a0/
Changeset: 70c404e681a0
User: dannon
Date: 2014-10-16 17:54:46+00:00
Summary: S3ObjectStore will create the bucket for you when possible if it does not exist.
Affected #: 1 file
diff -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 -r 70c404e681a0f4c347eaca75d65f23a11edcb823 lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -167,8 +167,12 @@
log.debug("Using cloud object store with bucket '%s'" % bucket.name)
return bucket
except S3ResponseError:
- log.debug("Could not get bucket '%s', attempt %s/5" % (bucket_name, i + 1))
- time.sleep(2)
+ try:
+ log.debug("Bucket not found, creating s3 bucket with handle '%s'" % bucket_name)
+ self.conn.create_bucket(bucket_name)
+ except S3ResponseError:
+ log.exception("Could not get bucket '%s', attempt %s/5" % (bucket_name, i + 1))
+ time.sleep(2)
# All the attempts have been exhausted and connection was not established,
# raise error
raise S3ResponseError
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/921aa1c775b5/
Changeset: 921aa1c775b5
User: dannon
Date: 2014-10-16 17:41:10+00:00
Summary: Slightly better handling of s3 object store conf, allowing connection element to be optional
Affected #: 1 file
diff -r 9f5491972e72ee38e011d49e891303e47bca29d9 -r 921aa1c775b54911c149fe3c8a1dc9645945a83d lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -77,7 +77,11 @@
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
self.use_rr = b_xml.get('use_reduced_redundancy', False)
- cn_xml = config_xml.findall('connection')[0]
+ cn_xml = config_xml.findall('connection')
+ if not cn_xml:
+ cn_xml = {}
+ else:
+ cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
self.is_secure = cn_xml.get('is_secure', True)
https://bitbucket.org/galaxy/galaxy-central/commits/b1d9b4f49abb/
Changeset: b1d9b4f49abb
User: dannon
Date: 2014-10-16 17:41:22+00:00
Summary: Merge.
Affected #: 65 files
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/collection/collection-li.js
--- a/client/galaxy/scripts/mvc/collection/collection-li.js
+++ b/client/galaxy/scripts/mvc/collection/collection-li.js
@@ -100,8 +100,6 @@
/** add the DCE class to the list item */
className : ListItemView.prototype.className + " dataset-collection-element",
- /** jq fx speed for this view */
- fxSpeed : 'fast',
/** set up */
initialize : function( attributes ){
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/history/history-structure-view.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/history/history-structure-view.js
@@ -0,0 +1,421 @@
+define([
+ 'mvc/job/job-model',
+ 'mvc/job/job-li',
+ 'mvc/history/history-content-model',
+ 'mvc/history/job-dag',
+ 'mvc/base-mvc',
+ 'utils/localization',
+ 'libs/d3'
+], function( JOB, JOB_LI, HISTORY_CONTENT, JobDAG, BASE_MVC, _l ){
+// ============================================================================
+/* TODO:
+change component = this to something else
+
+*/
+// ============================================================================
+/**
+ *
+ */
+var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ //logger : console,
+
+ className : 'history-structure-component',
+
+ initialize : function( attributes ){
+ this.log( this + '(HistoryStructureComponent).initialize:', attributes );
+ this.component = attributes.component;
+
+ this._jobLiMap = {};
+ this._createJobModels();
+
+ this.layout = this._createLayout( attributes.layoutOptions );
+ },
+
+ _createJobModels : function(){
+ var view = this;
+ view.component.eachVertex( function( vertex ){
+ var jobJSON = vertex.data.job,
+ job = new JOB.Job( jobJSON );
+
+ // get the models of the outputs for this job from the history
+ var outputModels = _.map( job.get( 'outputs' ), function( output ){
+ //note: output is { src: 'hda/dataset_collection', id: <some id> }
+ // job output doesn't *quite* match up to normal typeId
+ var type = output.src === 'hda'? 'dataset' : 'dataset_collection',
+ typeId = HISTORY_CONTENT.typeIdStr( type, output.id );
+ return view.model.contents.get( typeId );
+ });
+ // set the collection (HistoryContents) for the job to that json (setting historyId for proper ajax urls)
+ job.outputCollection.reset( outputModels );
+ job.outputCollection.historyId = view.model.id;
+ //this.debug( job.outputCollection );
+
+ // create the bbone view for the job (to be positioned later accrd. to the layout) and cache
+ var li = new JOB_LI.JobListItemView({ model: job });
+ //var li = new JOB_LI.JobListItemView({ model: job });
+ li.render( 0 ).$el.appendTo( view.$el );
+ view._jobLiMap[ job.id ] = li;
+ view._setUpJobListeners( li );
+
+ });
+ return view.jobs;
+ },
+
+ _setUpJobListeners : function( jobLi ){
+ // update the layout during expansion and collapsing of job and output li's
+ jobLi.on( 'expanding expanded collapsing collapsed', this.render, this );
+ jobLi.foldout.on( 'view:expanding view:expanded view:collapsing view:collapsed', this.render, this );
+ },
+
+ layoutDefaults : {
+ paddingTop : 8,
+ paddingLeft : 20,
+ linkSpacing : 16,
+ jobHeight : 308,
+ jobWidthSpacing : 320,
+ linkAdjX : 4,
+ linkAdjY : 0
+ },
+
+ _createLayout : function( options ){
+ options = _.defaults( _.clone( options || {} ), this.layoutDefaults );
+ var view = this,
+ vertices = _.values( view.component.vertices ),
+ layout = _.extend( options, {
+ nodeMap : {},
+ links : [],
+ el : { width: 0, height: 0 },
+ svg : { width: 0, height: 0, top: 0, left: 0 }
+ });
+
+ vertices.forEach( function( v, j ){
+ var node = { name: v.name, x: 0, y: 0 };
+ layout.nodeMap[ v.name ] = node;
+ });
+
+ view.component.edges( function( e ){
+ var link = {
+ source: e.source,
+ target: e.target
+ };
+ layout.links.push( link );
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ return layout;
+ },
+
+ _updateLayout : function(){
+ var view = this,
+ layout = view.layout;
+
+ layout.svg.height = layout.paddingTop + ( layout.linkSpacing * _.size( layout.nodeMap ) );
+ layout.el.height = layout.svg.height + layout.jobHeight;
+
+//TODO:?? can't we just alter the component v and e's directly?
+ // layout the job views putting jobWidthSpacing btwn each
+ var x = layout.paddingLeft,
+ y = layout.svg.height;
+ _.each( layout.nodeMap, function( node, jobId ){
+ //this.debug( node, jobId );
+ node.x = x;
+ node.y = y;
+ x += layout.jobWidthSpacing;
+ });
+ layout.el.width = layout.svg.width = Math.max( layout.el.width, x );
+
+ // layout the links - connecting each job by it's main coords (currently)
+//TODO: somehow adjust the svg height based on the largest distance the longest connection needs
+ layout.links.forEach( function( link ){
+ var source = layout.nodeMap[ link.source ],
+ target = layout.nodeMap[ link.target ];
+ link.x1 = source.x + layout.linkAdjX;
+ link.y1 = source.y + layout.linkAdjY;
+ link.x2 = target.x + layout.linkAdjX;
+ link.y2 = target.y + layout.linkAdjY;
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ return this.layout;
+ },
+
+ render : function( options ){
+ this.debug( this + '.render:', options );
+ var view = this;
+
+ function _render(){
+ view._updateLayout();
+ // set up the display containers
+ view.$el
+ .width( view.layout.el.width )
+ .height( view.layout.el.height );
+ view.renderSVG();
+
+ // position the job views accrd. to the layout
+ view.component.eachVertex( function( v ){
+//TODO:? liMap needed - can't we attach to vertex?
+ var li = view._jobLiMap[ v.name ],
+ position = view.layout.nodeMap[ li.model.id ];
+ //this.debug( position );
+ li.$el.css({ top: position.y, left: position.x });
+ });
+ }
+//TODO: hack - li's invisible in updateLayout without this delay
+ if( !this.$el.is( ':visible' ) ){
+ _.delay( _render, 0 );
+ } else {
+ _render();
+ }
+ return this;
+ },
+
+ renderSVG : function(){
+ var view = this,
+ layout = view.layout;
+
+ var svg = d3.select( this.el ).select( 'svg' );
+ if( svg.empty() ){
+ svg = d3.select( this.el ).append( 'svg' );
+ }
+
+ svg
+ .attr( 'width', layout.svg.width )
+ .attr( 'height', layout.svg.height );
+
+ function highlightConnect( d ){
+ d3.select( this ).classed( 'highlighted', true );
+ view._jobLiMap[ d.source ].$el.addClass( 'highlighted' );
+ view._jobLiMap[ d.target ].$el.addClass( 'highlighted' );
+ }
+
+ function unhighlightConnect( d ){
+ d3.select( this ).classed( 'highlighted', false );
+ view._jobLiMap[ d.source ].$el.removeClass( 'highlighted' );
+ view._jobLiMap[ d.target ].$el.removeClass( 'highlighted' );
+ }
+
+ var connections = svg.selectAll( '.connection' )
+ .data( layout.links );
+
+ connections
+ .enter().append( 'path' )
+ .attr( 'class', 'connection' )
+ .attr( 'id', function( d ){ return d.source + '-' + d.target; })
+ .on( 'mouseover', highlightConnect )
+ .on( 'mouseout', unhighlightConnect );
+
+ connections
+ .attr( 'd', function( d ){ return view._connectionPath( d ); });
+
+//TODO: ? can we use tick here to update the links?
+
+ return svg.node();
+ },
+
+ _connectionPath : function( d ){
+ var CURVE_X = 0,
+ controlY = ( ( d.x2 - d.x1 ) / this.layout.svg.width ) * this.layout.svg.height;
+ return [
+ 'M', d.x1, ',', d.y1, ' ',
+ 'C',
+ d.x1 + CURVE_X, ',', d.y1 - controlY, ' ',
+ d.x2 - CURVE_X, ',', d.y2 - controlY, ' ',
+ d.x2, ',', d.y2
+ ].join( '' );
+ },
+
+ events : {
+ 'mouseover .job.list-item' : function( ev ){ this.highlightConnected( ev.currentTarget, true ); },
+ 'mouseout .job.list-item' : function( ev ){ this.highlightConnected( ev.currentTarget, false ); }
+ },
+
+ highlightConnected : function( jobElement, highlight ){
+ highlight = highlight !== undefined? highlight : true;
+
+ var view = this,
+ component = view.component,
+ jobClassFn = highlight? jQuery.prototype.addClass : jQuery.prototype.removeClass,
+ connectionClass = highlight? 'connection highlighted' : 'connection';
+
+ //console.debug( 'mouseover', this );
+ var $jobs = jobClassFn.call( $( jobElement ), 'highlighted' ),
+ id = $jobs.attr( 'id' ).replace( 'job-', '' );
+
+ // immed. ancestors
+ component.edges({ target: id }).forEach( function( edge ){
+ jobClassFn.call( view.$( '#job-' + edge.source ), 'highlighted' );
+ view.$( '#' + edge.source + '-' + id ).attr( 'class', connectionClass );
+ });
+ // descendants
+ component.vertices[ id ].eachEdge( function( edge ){
+ jobClassFn.call( view.$( '#job-' + edge.target ), 'highlighted' );
+ view.$( '#' + id + '-' + edge.target ).attr( 'class', connectionClass );
+ });
+ },
+
+ toString : function(){
+ return 'HistoryStructureComponent(' + this.model.id + ')';
+ }
+});
+
+
+// ============================================================================
+/**
+ *
+ */
+var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
+
+ //logger : console,
+
+ className : HistoryStructureComponent.prototype.className + ' vertical',
+
+ layoutDefaults : {
+ paddingTop : 8,
+ paddingLeft : 20,
+ linkSpacing : 16,
+ jobWidth : 308,
+ jobHeight : 308,
+ initialSpacing : 64,
+ jobSpacing : 16,
+ linkAdjX : 0,
+ linkAdjY : 4
+ },
+
+//TODO: how can we use the dom height of the job li's - they're not visible when this is called?
+ _updateLayout : function(){
+ var view = this,
+ layout = view.layout;
+ //this.info( this.cid, '_updateLayout' )
+
+ layout.svg.width = layout.paddingLeft + ( layout.linkSpacing * _.size( layout.nodeMap ) );
+ layout.el.width = layout.svg.width + layout.jobWidth;
+
+ // reset height - we'll get the max Y below to assign to it
+ layout.el.height = 0;
+
+//TODO:?? can't we just alter the component v and e's directly?
+ var x = layout.svg.width,
+ y = layout.paddingTop;
+ _.each( layout.nodeMap, function( node, jobId ){
+ //this.debug( node, jobId );
+ node.x = x;
+ node.y = y;
+ var li = view._jobLiMap[ jobId ];
+ if( li.$el.is( ':visible' ) ){
+ y += li.$el.height() + layout.jobSpacing;
+ } else {
+ y += layout.initialSpacing + layout.jobSpacing;
+ }
+ });
+ layout.el.height = layout.svg.height = Math.max( layout.el.height, y );
+
+ // layout the links - connecting each job by it's main coords (currently)
+ layout.links.forEach( function( link ){
+ var source = layout.nodeMap[ link.source ],
+ target = layout.nodeMap[ link.target ];
+ link.x1 = source.x + layout.linkAdjX;
+ link.y1 = source.y + layout.linkAdjY;
+ link.x2 = target.x + layout.linkAdjX;
+ link.y2 = target.y + layout.linkAdjY;
+ view.debug( 'link:', link.x1, link.y1, link.x2, link.y2, link );
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ view.debug( 'el:', layout.el );
+ view.debug( 'svg:', layout.svg );
+ return layout;
+ },
+
+ _connectionPath : function( d ){
+ var CURVE_Y = 0,
+ controlX = ( ( d.y2 - d.y1 ) / this.layout.svg.height ) * this.layout.svg.width;
+ return [
+ 'M', d.x1, ',', d.y1, ' ',
+ 'C',
+ d.x1 - controlX, ',', d.y1 + CURVE_Y, ' ',
+ d.x2 - controlX, ',', d.y2 - CURVE_Y, ' ',
+ d.x2, ',', d.y2
+ ].join( '' );
+ },
+
+ toString : function(){
+ return 'VerticalHistoryStructureComponent(' + this.model.id + ')';
+ }
+});
+
+
+// ============================================================================
+/**
+ *
+ */
+var HistoryStructureView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ //logger : console,
+
+ className : 'history-structure',
+
+ initialize : function( attributes ){
+ this.log( this + '(HistoryStructureView).initialize:', attributes, this.model );
+//TODO: to model
+ this.jobs = attributes.jobs;
+ this._createDAG();
+ },
+
+ _createDAG : function(){
+ this.dag = new JobDAG({
+ historyContents : this.model.contents.toJSON(),
+ jobs : this.jobs,
+ excludeSetMetadata : true,
+ excludeErroredJobs : true
+ });
+//window.dag = this.dag;
+ this.log( this + '.dag:', this.dag );
+
+ this._createComponents();
+ },
+
+ _createComponents : function(){
+ this.log( this + '._createComponents' );
+ var structure = this;
+//window.structure = structure;
+
+ structure.componentViews = structure.dag.weakComponentGraphArray().map( function( componentGraph ){
+ return structure._createComponent( componentGraph );
+ });
+ },
+
+ _createComponent : function( component ){
+ this.log( this + '._createComponent:', component );
+ //return new HistoryStructureComponent({
+ return new VerticalHistoryStructureComponent({
+ model : this.model,
+ component : component
+ });
+ },
+
+ render : function( options ){
+ this.log( this + '.render:', options );
+ var structure = this;
+
+ structure.$el.html([
+ '<div class="controls"></div>',
+ '<div class="components"></div>'
+ ].join( '' ));
+
+ structure.componentViews.forEach( function( component ){
+ component.render().$el.appendTo( structure.$components() );
+ });
+ return structure;
+ },
+
+ $components : function(){
+ return this.$( '.components' );
+ },
+
+ toString : function(){
+ return 'HistoryStructureView(' + ')';
+ }
+});
+
+
+// ============================================================================
+ return HistoryStructureView;
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/history/job-dag.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/history/job-dag.js
@@ -0,0 +1,219 @@
+define([
+ 'utils/graph',
+ 'utils/add-logging'
+],function( GRAPH, addLogging ){
+// ============================================================================
+var _super = GRAPH.Graph;
+/** A Directed acyclic Graph built from a history's job data.
+ * Reads in job json, filters and process that json, and builds a graph
+ * using the connections between job inputs and outputs.
+ */
+var JobDAG = function( options ){
+ var self = this;
+ //this.logger = console;
+
+ // instance vars
+//TODO: needed?
+ self._historyContentsMap = {};
+ self.filters = [];
+
+ self._idMap = {};
+ self.noInputJobs = [];
+ self.noOutputJobs = [];
+
+//TODO: save these?
+ self.filteredSetMetadata = [];
+ self.filteredErroredJobs = [];
+
+ _super.call( self, true, null, options );
+};
+JobDAG.prototype = new GRAPH.Graph();
+JobDAG.prototype.constructor = JobDAG;
+
+// add logging ability - turn off/on using the this.logger statement above
+addLogging( JobDAG );
+
+// ----------------------------------------------------------------------------
+/** process jobs, options, filters, and any history data, then create the graph */
+JobDAG.prototype.init = function _init( options ){
+ options = options || {};
+ _super.prototype.init.call( this, options );
+
+ var self = this,
+ historyContentsJSON = options.historyContents || [];
+ jobsJSON = options.jobs || [];
+
+ historyContentsJSON.forEach( function( content, i ){
+ self._historyContentsMap[ content.id ] = _.clone( content );
+ });
+
+ self.options = _.defaults( _.omit( options, 'historyContents', 'jobs' ), {
+ excludeSetMetadata : false
+ });
+ self.filters = self._initFilters();
+
+//TODO: O( 3N )
+ self.preprocessJobs( _.clone( jobsJSON ) );
+ self.createGraph();
+
+ return self;
+};
+
+/** add job filters based on options */
+JobDAG.prototype._initFilters = function __initFilters(){
+ var self = this,
+ filters = [];
+
+ if( self.options.excludeSetMetadata ){
+ self.filteredSetMetadata = [];
+ filters.push( function filterSetMetadata( jobData ){
+ if( jobData.job.tool_id !== '__SET_METADATA__' ){ return true; }
+ self.filteredSetMetadata.push( jobData.job.id );
+ return false;
+ });
+ }
+
+ if( self.options.excludeErroredJobs ){
+ self.filteredErroredJobs = [];
+ filters.push( function filterErrored( jobData ){
+ if( jobData.job.state !== 'error' ){ return true; }
+ self.filteredErroredJobs.push( jobData.job.id );
+ return false;
+ });
+ }
+
+ // all outputs deleted
+ // all outputs hidden
+
+ if( _.isArray( self.options.filters ) ){
+ filters = filters.concat( self.options.filters );
+ }
+ self.debug( 'filters len:', filters.length );
+ return filters;
+};
+
+/** sort the jobs and cache any that pass all filters into _idMap by job.id */
+JobDAG.prototype.preprocessJobs = function _preprocessJobs( jobs ){
+ this.info( 'processing jobs' );
+
+ var self = this;
+//TODO:? sorting neccessary?
+ self.sort( jobs ).forEach( function( job, i ){
+ var jobData = self.preprocessJob( job, i );
+ if( jobData ){
+ self._idMap[ job.id ] = jobData;
+ }
+ });
+ return self;
+};
+
+/** sort the jobs based on update time */
+JobDAG.prototype.sort = function _sort( jobs ){
+ function cmpCreate( a, b ){
+ if( a.update_time > b.update_time ){ return 1; }
+ if( a.update_time < b.update_time ){ return -1; }
+ return 0;
+ }
+ return jobs.sort( cmpCreate );
+};
+
+/** proces input/output, filter based on job data returning data if passing, null if not */
+JobDAG.prototype.preprocessJob = function _preprocessJob( job, index ){
+ //this.info( 'preprocessJob', job, index );
+ var self = this,
+ jobData = { index: index, job: job };
+
+ jobData.inputs = self.datasetMapToIdArray( job.inputs, function( dataset, nameInJob ){
+ //TODO:? store output name in self._datasets[ output.id ] from creating job?
+ });
+ if( jobData.inputs.length === 0 ){
+ self.noInputJobs.push( job.id );
+ }
+ jobData.outputs = self.datasetMapToIdArray( job.outputs, function( dataset, nameInJob ){
+
+ });
+ if( jobData.outputs.length === 0 ){
+ self.noOutputJobs.push( job.id );
+ }
+
+ //self.debug( JSON.stringify( jobData, null, ' ' ) );
+ // apply filters after processing job allowing access to the additional data above in the filters
+ for( var i=0; i<self.filters.length; i++ ){
+ if( !self.filters[i].call( self, jobData ) ){
+ self.debug( 'job', job.id, ' has been filtered out by function:\n', self.filters[i] );
+ return null;
+ }
+ }
+
+ //self.info( 'preprocessJob returning', jobData );
+ return jobData;
+};
+
+/** make verbose input/output lists more concise, sanity checking along the way
+ * processFn is called on each input/output and passed the dataset obj (id,src) and the input/output name.
+ */
+JobDAG.prototype.datasetMapToIdArray = function _datasetMapToIdArray( datasetMap, processFn ){
+ var self = this;
+ return _.map( datasetMap, function( dataset, nameInJob ){
+ if( !dataset.id ){
+ throw new Error( 'No id on datasetMap: ', JSON.stringify( dataset ) );
+ }
+ if( !dataset.src || dataset.src !== 'hda' ){
+ throw new Error( 'Bad src on datasetMap: ', JSON.stringify( dataset ) );
+ }
+ processFn.call( self, dataset, nameInJob );
+ return dataset.id;
+ });
+};
+
+/** Walk all the jobs (vertices), attempting to find connections
+ * between datasets used as both inputs and outputs (edges)
+ */
+JobDAG.prototype.createGraph = function _createGraph(){
+ var self = this;
+ self.debug( 'connections:' );
+
+ _.each( self._idMap, function( sourceJobData, sourceJobId ){
+ self.debug( '\t', sourceJobId, sourceJobData );
+ self.createVertex( sourceJobId, sourceJobData );
+
+ sourceJobData.usedIn = [];
+ _.each( sourceJobData.outputs, function( outputDatasetId ){
+//TODO: O(n^2)
+ _.each( self._idMap, function( targetJobData, targetJobId ){
+ if( targetJobData === sourceJobData ){ return; }
+
+ if( targetJobData.inputs.indexOf( outputDatasetId ) !== -1 ){
+ self.info( '\t\t\t found connection: ', sourceJobId, targetJobId );
+ sourceJobData.usedIn.push({ job: targetJobId, output: outputDatasetId });
+
+ self.createVertex( targetJobId, targetJobData );
+
+ self.createEdge( sourceJobId, targetJobId, self.directed, {
+ dataset : outputDatasetId
+ });
+ }
+ });
+ });
+ });
+ self.debug( 'job data: ', JSON.stringify( self._idMap, null, ' ' ) );
+ return self;
+};
+
+/** Override to re-sort (ugh) jobs in each component by update time */
+Graph.prototype.weakComponentGraphArray = function(){
+ return this.weakComponents().map( function( component ){
+//TODO: this seems to belong above (in sort) - why isn't it preserved?
+ component.vertices.sort( function cmpCreate( a, b ){
+ if( a.data.job.update_time > b.data.job.update_time ){ return 1; }
+ if( a.data.job.update_time < b.data.job.update_time ){ return -1; }
+ return 0;
+ });
+ return new Graph( this.directed, component );
+ });
+};
+
+
+// ============================================================================
+ return JobDAG;
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/job/job-li.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/job/job-li.js
@@ -0,0 +1,129 @@
+define([
+ 'mvc/list/list-item',
+ 'mvc/dataset/dataset-list',
+ "mvc/base-mvc",
+ "utils/localization"
+], function( LIST_ITEM, DATASET_LIST, BASE_MVC, _l ){
+//==============================================================================
+var _super = LIST_ITEM.FoldoutListItemView;
+/** @class A job view used from within a larger list of jobs.
+ * Each job itself is a foldout panel of history contents displaying the outputs of this job.
+ */
+var JobListItemView = _super.extend(/** @lends JobListItemView.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+
+ className : _super.prototype.className + " job",
+ id : function(){
+ return [ 'job', this.model.get( 'id' ) ].join( '-' );
+ },
+
+ foldoutPanelClass : DATASET_LIST.DatasetList,
+
+ /** Set up: instance vars, options, and event handlers */
+ initialize : function( attributes ){
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+ this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+
+ /** where should pages from links be displayed? (default to new tab/window) */
+ this.linkTarget = attributes.linkTarget || '_blank';
+ },
+
+ /** In this override, add the state as a class for use with state-based CSS */
+ _swapNewRender : function( $newRender ){
+ _super.prototype._swapNewRender.call( this, $newRender );
+ if( this.model.has( 'state' ) ){
+ this.$el.addClass( 'state-' + this.model.get( 'state' ) );
+ }
+ return this.$el;
+ },
+
+ /** Stub to return proper foldout panel options */
+ _getFoldoutPanelOptions : function(){
+ var options = _super.prototype._getFoldoutPanelOptions.call( this );
+ return _.extend( options, {
+ collection : this.model.outputCollection,
+ selecting : false
+ });
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ return 'JobListItemView(' + this.model + ')';
+ }
+});
+
+// ............................................................................ TEMPLATES
+/** underscore templates */
+JobListItemView.prototype.templates = (function(){
+//TODO: move to require text! plugin
+
+ var elTemplate = BASE_MVC.wrapTemplate([
+ '<div class="list-element">',
+ '<div class="id"><%= model.id %></div>',
+ // errors, messages, etc.
+ '<div class="warnings"></div>',
+
+ // multi-select checkbox
+ '<div class="selector">',
+ '<span class="fa fa-2x fa-square-o"></span>',
+ '</div>',
+ // space for title bar buttons - gen. floated to the right
+ '<div class="primary-actions"></div>',
+ '<div class="title-bar"></div>',
+
+ // expandable area for more details
+ '<div class="details"></div>',
+ '</div>'
+ ]);
+
+ var titleBarTemplate = BASE_MVC.wrapTemplate([
+ // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display
+ '<div class="title-bar clear" tabindex="0">',
+ //'<span class="state-icon"></span>',
+ '<div class="title">',
+ '<span class="name"><%- job.tool_id %></span>',
+ '</div>',
+ '<div class="subtitle"></div>',
+ '</div>'
+ ], 'job' );
+
+ //var subtitleTemplate = BASE_MVC.wrapTemplate([
+ // // override this
+ // '<div class="subtitle">',
+ // _l( 'Created' ), ': <%= new Date( job.create_time ).toString() %>, ',
+ // _l( 'Updated' ), ': <%= new Date( job.update_time ).toString() %>',
+ // '</div>'
+ //], 'job' );
+ //
+ //var detailsTemplate = BASE_MVC.wrapTemplate([
+ // '<div class="details">',
+ // '<div class="params">',
+ // '<% _.each( job.params, function( param, paramName ){ %>',
+ // '<div class="param">',
+ // '<label class="prompt"><%= paramName %></label>',
+ // '<span class="value"><%= param %></span>',
+ // '</div>',
+ // '<% }) %>',
+ // '</div>',
+ // '</div>'
+ //], 'job' );
+
+ return _.extend( {}, _super.prototype.templates, {
+ //el : elTemplate,
+ titleBar : titleBarTemplate,
+ //subtitle : subtitleTemplate,
+ //details : detailsTemplate
+ });
+}());
+
+
+//=============================================================================
+ return {
+ JobListItemView : JobListItemView
+ };
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/job/job-model.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/job/job-model.js
@@ -0,0 +1,203 @@
+define([
+ "mvc/history/history-contents",
+ "mvc/dataset/states",
+ "utils/ajax-queue",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HISTORY_CONTENTS, STATES, AJAX_QUEUE, BASE_MVC, _l ){
+//==============================================================================
+var searchableMixin = BASE_MVC.SearchableModelMixin;
+/** @class Represents a job running or ran on the server job handlers.
+ */
+var Job = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+ BASE_MVC.mixin( searchableMixin, /** @lends Job.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ model_class : 'Job',
+
+ tool : null,
+ exit_code : null,
+
+ inputs : {},
+ outputs : {},
+ params : {},
+
+ create_time : null,
+ update_time : null,
+ state : STATES.NEW
+ },
+
+ /** instance vars and listeners */
+ initialize : function( attributes, options ){
+ this.debug( this + '(Job).initialize', attributes, options );
+ this.outputCollection = attributes.outputCollection || new HISTORY_CONTENTS.HistoryContents([]);
+ this._setUpListeners();
+ },
+
+ /** set up any event listeners
+ * event: state:ready fired when this DA moves into/is already in a ready state
+ */
+ _setUpListeners : function(){
+ // if the state has changed and the new state is a ready state, fire an event
+ this.on( 'change:state', function( currModel, newState ){
+ this.log( this + ' has changed state:', currModel, newState );
+ if( this.inReadyState() ){
+ this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) );
+ }
+ });
+ },
+
+ // ........................................................................ common queries
+ /** Is this job in a 'ready' state; where 'Ready' states are states where no
+ * processing is left to do on the server.
+ */
+ inReadyState : function(){
+ return _.contains( STATES.READY_STATES, this.get( 'state' ) );
+ },
+
+ /** Does this model already contain detailed data (as opposed to just summary level data)? */
+ hasDetails : function(){
+ //?? this may not be reliable
+ return _.isEmpty( this.get( 'outputs' ) );
+ },
+
+ // ........................................................................ ajax
+ /** root api url */
+ urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
+ //url : function(){ return this.urlRoot; },
+
+ // ........................................................................ searching
+ // see base-mvc, SearchableModelMixin
+ /** what attributes of an Job will be used in a text search */
+ searchAttributes : [
+ 'tool'
+ ],
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ return [ 'Job(', this.get( 'id' ), ':', this.get( 'tool_id' ), ')' ].join( '' );
+ }
+}));
+
+
+//==============================================================================
+/** @class Backbone collection for Jobs.
+ */
+var JobCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends JobCollection.prototype */{
+ model : Job,
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** root api url */
+ urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
+ url : function(){ return this.urlRoot; },
+
+ intialize : function( models, options ){
+ console.debug( models, options );
+ },
+
+ // ........................................................................ common queries
+ /** Get the ids of every item in this collection
+ * @returns array of encoded ids
+ */
+ ids : function(){
+ return this.map( function( item ){ return item.get( 'id' ); });
+ },
+
+ /** Get jobs that are not ready
+ * @returns array of content models
+ */
+ notReady : function(){
+ return this.filter( function( job ){
+ return !job.inReadyState();
+ });
+ },
+
+ /** return true if any jobs don't have details */
+ haveDetails : function(){
+ return this.all( function( job ){ return job.hasDetails(); });
+ },
+
+ // ........................................................................ ajax
+ /** fetches all details for each job in the collection using a queue */
+ queueDetailFetching : function(){
+ var collection = this,
+ queue = new AJAX_QUEUE.AjaxQueue( this.map( function( job ){
+ return function(){
+ return job.fetch({ silent: true });
+ };
+ }));
+ queue.done( function(){
+ collection.trigger( 'details-loaded' );
+ });
+ return queue;
+ },
+
+ //toDAG : function(){
+ // return new JobDAG( this.toJSON() );
+ //},
+
+ // ........................................................................ sorting/filtering
+ /** return a new collection of jobs whose attributes contain the substring matchesWhat */
+ matches : function( matchesWhat ){
+ return this.filter( function( job ){
+ return job.matches( matchesWhat );
+ });
+ },
+
+ // ........................................................................ misc
+ /** override to get a correct/smarter merge when incoming data is partial */
+ set : function( models, options ){
+ // arrrrrrrrrrrrrrrrrg...
+ // (e.g. stupid backbone)
+ // w/o this partial models from the server will fill in missing data with model defaults
+ // and overwrite existing data on the client
+ // see Backbone.Collection.set and _prepareModel
+ var collection = this;
+ models = _.map( models, function( model ){
+ if( !collection.get( model.id ) ){ return model; }
+
+ // merge the models _BEFORE_ calling the superclass version
+ var merged = existing.toJSON();
+ _.extend( merged, model );
+ return merged;
+ });
+ // now call superclass when the data is filled
+ Backbone.Collection.prototype.set.call( this, models, options );
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'JobCollection(', this.length, ')' ].join( '' ));
+ }
+
+//----------------------------------------------------------------------------- class vars
+}, {
+ /** class level fn for fetching the job details for all jobs in a history */
+ fromHistory : function( historyId ){
+ console.debug( this );
+ var Collection = this,
+ collection = new Collection([]);
+ collection.fetch({ data: { history_id: historyId }})
+ .done( function(){
+ window.queue = collection.queueDetailFetching();
+
+ });
+ return collection;
+ }
+});
+
+
+//=============================================================================
+ return {
+ Job : Job,
+ JobCollection : JobCollection
+ };
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/list/list-item.js
--- a/client/galaxy/scripts/mvc/list/list-item.js
+++ b/client/galaxy/scripts/mvc/list/list-item.js
@@ -16,8 +16,8 @@
initialize : function( attributes ){
/** are the details of this view expanded/shown or not? */
this.expanded = attributes.expanded || false;
- //this.log( '\t expanded:', this.expanded );
- this.fxSpeed = attributes.fxSpeed || this.fxSpeed;
+ this.log( '\t expanded:', this.expanded );
+ this.fxSpeed = attributes.fxSpeed !== undefined? attributes.fxSpeed : this.fxSpeed;
},
// ........................................................................ render main
@@ -70,7 +70,9 @@
/** empty out the current el, move the $newRender's children in */
_swapNewRender : function( $newRender ){
- return this.$el.empty().attr( 'class', this.className ).append( $newRender.children() );
+ return this.$el.empty()
+ .attr( 'class', _.isFunction( this.className )? this.className(): this.className )
+ .append( $newRender.children() );
},
/** set up js behaviors, event handlers for elements within the given container
@@ -117,15 +119,8 @@
*/
expand : function(){
var view = this;
- return view._fetchModelDetails()
- .always(function(){
- var $newDetails = view._renderDetails();
- view.$details().replaceWith( $newDetails );
- // needs to be set after the above or the slide will not show
- view.expanded = true;
- view.$details().slideDown( view.fxSpeed, function(){
- view.trigger( 'expanded', view );
- });
+ return view._fetchModelDetails().always( function(){
+ view._expand();
});
},
@@ -139,6 +134,24 @@
return jQuery.when();
},
+ /** Inner fn called when expand (public) has fetched the details */
+ _expand : function(){
+ var view = this,
+ $newDetails = view._renderDetails();
+ view.$details().replaceWith( $newDetails );
+ // needs to be set after the above or the slide will not show
+ view.expanded = true;
+ view.$details().slideDown({
+ duration : view.fxSpeed,
+ step: function(){
+ view.trigger( 'expanding', view );
+ },
+ complete: function(){
+ view.trigger( 'expanded', view );
+ }
+ });
+ },
+
/** Hide the body/details of an HDA.
* @fires collapsed when a body has been collapsed
*/
@@ -146,8 +159,14 @@
this.debug( this + '(ExpandableView).collapse' );
var view = this;
view.expanded = false;
- this.$details().slideUp( view.fxSpeed, function(){
- view.trigger( 'collapsed', view );
+ this.$details().slideUp({
+ duration : view.fxSpeed,
+ step: function(){
+ view.trigger( 'collapsing', view );
+ },
+ complete: function(){
+ view.trigger( 'collapsed', view );
+ }
});
}
@@ -204,7 +223,7 @@
$newRender.children( '.warnings' ).replaceWith( this._renderWarnings() );
$newRender.children( '.title-bar' ).replaceWith( this._renderTitleBar() );
$newRender.children( '.primary-actions' ).append( this._renderPrimaryActions() );
- $newRender.find( '.title-bar .subtitle' ).replaceWith( this._renderSubtitle() );
+ $newRender.find( '> .title-bar .subtitle' ).replaceWith( this._renderSubtitle() );
return $newRender;
},
@@ -375,11 +394,13 @@
* disrespect attributes.expanded if drilldown
*/
initialize : function( attributes ){
- ListItemView.prototype.initialize.call( this, attributes );
//TODO: hackish
if( this.foldoutStyle === 'drilldown' ){ this.expanded = false; }
this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;
this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;
+
+ ListItemView.prototype.initialize.call( this, attributes );
+ this.foldout = this._createFoldoutPanel();
},
//TODO:?? override to exclude foldout scope?
@@ -393,7 +414,7 @@
//TODO: hackish
if( this.foldoutStyle === 'drilldown' ){ return $(); }
var $newDetails = ListItemView.prototype._renderDetails.call( this );
- return this._attachFoldout( this._createFoldoutPanel(), $newDetails );
+ return this._attachFoldout( this.foldout, $newDetails );
},
/** In this override, handle collection expansion. */
@@ -417,7 +438,8 @@
_getFoldoutPanelOptions : function(){
return {
// propagate foldout style down
- foldoutStyle : this.foldoutStyle
+ foldoutStyle : this.foldoutStyle,
+ fxSpeed : this.fxSpeed
};
},
@@ -436,25 +458,13 @@
return view._fetchModelDetails()
.always(function(){
if( view.foldoutStyle === 'foldout' ){
- view._expandByFoldout();
+ view._expand();
} else if( view.foldoutStyle === 'drilldown' ){
view._expandByDrilldown();
}
});
},
- /** For foldout, call render details then slide down */
- _expandByFoldout : function(){
- var view = this;
- var $newDetails = view._renderDetails();
- view.$details().replaceWith( $newDetails );
- // needs to be set after the above or the slide will not show
- view.expanded = true;
- view.$details().slideDown( view.fxSpeed, function(){
- view.trigger( 'expanded', view );
- });
- },
-
/** For drilldown, set up close handler and fire expanded:drilldown
* containing views can listen to this and handle other things
* (like hiding themselves) by listening for expanded/collapsed:drilldown
@@ -462,7 +472,6 @@
_expandByDrilldown : function(){
var view = this;
// attachment and rendering done by listener
- view.foldout = this._createFoldoutPanel();
view.foldout.on( 'close', function(){
view.trigger( 'collapsed:drilldown', view, view.foldout );
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-content.js
@@ -22,11 +22,16 @@
// get history summary
Utils.get({
- url : self.base_url + '?deleted=false',
+ url : self.base_url + '?deleted=false&state=ok',
success : function(response) {
// backup summary
self.summary = response;
+ // sort by id
+ self.summary.sort(function(a, b) {
+ return a.hid > b.hid ? -1 : (a.hid < b.hid ? 1 : 0);
+ });
+
// log
console.debug('tools-content::initialize() - Completed.');
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -27,10 +27,8 @@
this.modal = new Ui.Modal.View();
}
- // link model/inputs and all options
- this.options = options;
- this.model = options.model;
- this.inputs = options.model.inputs;
+ // link options
+ this.options = options;
// set element
this.setElement('<div/>');
@@ -53,9 +51,13 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize contents
+ // for now the initial tool model is parsed through the mako
+ this.model = this.options;
+ this.inputs = this.options.inputs;
+
+ // request history content and build form
this.content = new ToolContent({
- history_id : this.options.history_id,
+ history_id : self.options.history_id,
success : function() {
self._buildForm();
}
@@ -89,6 +91,51 @@
console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
+ // build tool model through api call
+ _buildModel: function() {
+ // link this
+ var self = this;
+
+ // construct url
+ var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?';
+ if (this.options.job_id) {
+ model_url += 'job_id=' + this.options.job_id;
+ } else {
+ if (this.options.dataset_id) {
+ model_url += 'dataset_id=' + this.options.dataset_id;
+ } else {
+ var loc = top.location.href;
+ var pos = loc.indexOf('?');
+ if (loc.indexOf('tool_id=') != -1 && pos !== -1) {
+ model_url += loc.slice(pos + 1);
+ }
+ }
+ }
+
+ // get initial model
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ success : function(response) {
+ // link model data update options
+ self.options = $.extend(self.options, response);
+ self.model = response;
+ self.inputs = response.inputs;
+
+ // log success
+ console.debug('tools-form::initialize() - Initial tool model ready.');
+ console.debug(response);
+
+ // build form
+ self._buildForm();
+ },
+ error : function(response) {
+ console.debug('tools-form::initialize() - Initial tool model request failed.');
+ console.debug(response);
+ }
+ });
+ },
+
// refresh form data
_refreshForm: function() {
// link this
@@ -97,7 +144,7 @@
// finalize data
var current_state = this.tree.finalize({
data : function(dict) {
- if (dict.values.length > 0 && dict.values[0].src === 'hda') {
+ if (dict.values.length > 0 && dict.values[0] && dict.values[0].src === 'hda') {
return self.content.get({id: dict.values[0].id}).dataset_id;
}
return null;
@@ -111,7 +158,7 @@
// post job
Utils.request({
type : 'GET',
- url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True',
+ url : galaxy_config.root + 'api/tools/' + this.options.id + '/build',
data : current_state,
success : function(response) {
console.debug('tools-form::_refreshForm() - Refreshed inputs/states.');
@@ -132,28 +179,31 @@
// button menu
var menu = new Ui.ButtonMenu({
icon : 'fa-gear',
- tooltip : 'Click to see a list of available operations.'
+ tooltip : 'Click to see a list of options.'
});
- // add question option
- menu.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
- }
- });
+ // configure button selection
+ if(this.options.biostar_url) {
+ // add question option
+ menu.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
+ }
+ });
+ };
// create share button
menu.addMenu({
@@ -185,11 +235,11 @@
});
// switch to classic tool form mako if the form definition is incompatible
- //if (this.incompatible) {
+ if (this.incompatible) {
this.$el.hide();
$('#tool-form-classic').show();
return;
- //}
+ }
// create portlet
this.portlet = new Portlet.View({
@@ -213,12 +263,6 @@
}
});
- // configure button selection
- if(!this.options.biostar_url) {
- button_question.$el.hide();
- button_search.$el.hide();
- }
-
// append form
this.$el.append(this.portlet.$el);
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-jobs.js
--- a/client/galaxy/scripts/mvc/tools/tools-jobs.js
+++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js
@@ -37,7 +37,7 @@
console.debug(job_def);
// show progress modal
- this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () {self.app.modal.hide();} }});
+ this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () {self.app.modal.hide();} }});
// post job
Utils.request({
@@ -55,10 +55,20 @@
var error_messages = self.app.tree.matchResponse(response.message.data);
for (var input_id in error_messages) {
self._foundError(input_id, error_messages[input_id]);
+ break;
}
} else {
// show error message with details
console.debug(response);
+ self.app.modal.show({
+ title : 'Job submission failed',
+ body : ToolTemplate.error(job_def),
+ buttons : {
+ 'Close' : function() {
+ self.app.modal.hide();
+ }
+ }
+ });
}
}
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -529,22 +529,12 @@
/** Slider field
*/
_fieldSlider: function(input_def) {
- // set min/max
- input_def.min = input_def.min || 0;
- input_def.max = input_def.max || 100000;
-
- // calculate step size
- var step = 1;
- if (input_def.type == 'float') {
- step = (input_def.max - input_def.min) / 10000;
- }
-
// create slider
return new Ui.Slider.View({
id : 'field-' + input_def.id,
+ precise : input_def.type == 'float',
min : input_def.min,
- max : input_def.max,
- step : step
+ max : input_def.max
});
},
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-select-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-select-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js
@@ -40,7 +40,7 @@
var dataset_options = [];
for (var i in datasets) {
dataset_options.push({
- label: datasets[i].name,
+ label: datasets[i].hid + ': ' + datasets[i].name,
value: datasets[i].id
});
}
@@ -67,7 +67,7 @@
var collection_options = [];
for (var i in collections) {
collection_options.push({
- label: collections[i].name,
+ label: collections[i].hid + ': ' + collections[i].name,
value: collections[i].id
});
}
@@ -103,20 +103,36 @@
},
/** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
+ value : function (dict) {
+ // update current value
+ if (dict !== undefined) {
+ try {
+ // set source
+ this.current = dict.values[0].src;
+ this.refresh();
+
+ // create list
+ var list = [];
+ for (var i in dict.values) {
+ list.push(dict.values[i].id);
+ }
+
+ // identify select element
+ switch(this.current) {
+ case 'hda':
+ this.select_datasets.value(list);
+ break;
+ case 'hdca':
+ this.select_collection.value(list[0]);
+ break;
+ }
+ } catch (err) {
+ console.debug('tools-select-content::value() - Skipped.');
+ }
}
// transform into an array
- var id_list = select.value();
+ var id_list = this._select().value();
if (!(id_list instanceof Array)) {
id_list = [id_list];
}
@@ -142,12 +158,7 @@
/** Validate current selection
*/
validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
+ return this._select().validate();
},
/** Refreshes data selection view */
@@ -162,6 +173,16 @@
this.select_collection.$el.fadeIn();
break;
}
+ },
+
+ /** Assists in selecting the current field */
+ _select: function() {
+ switch(this.current) {
+ case 'hdca':
+ return this.select_collection;
+ default:
+ return this.select_datasets;
+ }
}
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-template.js
--- a/client/galaxy/scripts/mvc/tools/tools-template.js
+++ b/client/galaxy/scripts/mvc/tools/tools-template.js
@@ -49,7 +49,7 @@
error: function(job_def) {
return '<div>' +
'<p>' +
- 'Sorry, the server could not complete the request. Please contact the Galaxy Team if this error is persistent.' +
+ 'The server could not complete the request. Please contact the Galaxy Team if this error persists.' +
'</p>' +
'<textarea class="ui-textarea" disabled style="color: black;" rows="6">' +
JSON.stringify(job_def, undefined, 4) +
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/ui/ui-slider.js
--- a/client/galaxy/scripts/mvc/ui/ui-slider.js
+++ b/client/galaxy/scripts/mvc/ui/ui-slider.js
@@ -6,9 +6,11 @@
// options
optionsDefault: {
value : '',
- min : 1,
- max : 100,
- step : 1
+ min : null,
+ max : null,
+ step : null,
+ precise : false,
+ split : 10000
},
// initialize
@@ -18,19 +20,35 @@
// configure options
this.options = Utils.merge(options, this.optionsDefault);
-
+
// create new element
this.setElement(this._template(this.options));
- // backup slider
- this.$slider = this.$el.find('#slider');
+ // determine wether to use the slider
+ this.useslider = this.options.max !== null && this.options.min !== null && this.options.max > this.options.min;
+
+ // set default step size
+ if (this.options.step === null) {
+ this.options.step = 1;
+ if (this.options.precise && this.useslider) {
+ this.options.step = (this.options.max - this.options.min) / this.options.split;
+ }
+ }
+
+ // create slider if min and max are defined properly
+ if (this.useslider) {
+ this.$slider = this.$el.find('#slider');
+ this.$slider.slider(this.options);
+ this.$slider.on('slide', function (event, ui) {
+ self.value(ui.value);
+ });
+ } else {
+ this.$el.find('.ui-form-slider-text').css('width', '100%');
+ }
// backup integer field
this.$text = this.$el.find('#text');
- // load slider plugin
- this.$slider.slider(this.options);
-
// add text field event
this.$text.on('change', function () {
self.value($(this).val());
@@ -39,24 +57,23 @@
// add text field event
this.$text.on('keydown', function (event) {
var v = event.which;
- console.log(v);
if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || v == 189 || (v >= 48 && v <= 57)
- || (self.options.step != 1 && $(this).val().indexOf('.') == -1) && v == 190)) {
+ || (self.options.precise && $(this).val().indexOf('.') == -1) && v == 190)) {
event.preventDefault();
}
});
-
- // add slider event
- this.$slider.on('slide', function (event, ui) {
- self.value(ui.value);
- });
},
// value
value : function (new_val) {
if (new_val !== undefined) {
- // limit
- new_val = Math.max(Math.min(new_val, this.options.max), this.options.min);
+ // apply limit
+ if (this.options.max !== null) {
+ new_val = Math.min(new_val, this.options.max);
+ }
+ if (this.options.min !== null) {
+ new_val = Math.max(new_val, this.options.min);
+ }
// trigger on change event
if (this.options.onchange) {
@@ -64,7 +81,7 @@
}
// set values
- this.$slider.slider('value', new_val);
+ this.$slider && this.$slider.slider('value', new_val);
this.$text.val(new_val);
}
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: SelectToolParameter: Fix type check before split operation.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/20882e294f92/
Changeset: 20882e294f92
User: guerler
Date: 2014-10-16 17:42:17+00:00
Summary: SelectToolParameter: Fix type check before split operation.
Affected #: 1 file
diff -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 -r 20882e294f925cb4c895e194d508bc15306e4403 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -818,7 +818,7 @@
if value == '':
value = None
else:
- if not isinstance( value, list ):
+ if isinstance( value, basestring ):
# Split on all whitespace. This not only provides flexibility
# in interpreting values but also is needed because many browsers
# use \r\n to separate lines.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Update tag latest_2014.10.06 for changeset e1404e285ccb
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/78c9a97be4b6/
Changeset: 78c9a97be4b6
Branch: stable
User: natefoo
Date: 2014-10-16 17:00:13+00:00
Summary: Update tag latest_2014.10.06 for changeset e1404e285ccb
Affected #: 1 file
diff -r e1404e285ccb9e52bd09c5827934cd0da1974acc -r 78c9a97be4b6bfe55136b055477fd1b9f22fd848 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-1744b7d8e9ab619d78c0516f9ccb093b0a814163 latest_2014.10.06
+e1404e285ccb9e52bd09c5827934cd0da1974acc latest_2014.10.06
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0