galaxy-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- 15302 discussions
commit/galaxy-central: jgoecks: Trackster: more name location fixes.
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/503d939099fc/
Changeset: 503d939099fc
User: jgoecks
Date: 2013-10-18 04:45:23
Summary: Trackster: more name location fixes.
Affected #: 1 file
diff -r f0875c78b7864c5ac75be62e9a52611bfa2a6cf0 -r 503d939099fcd8913202300b83221a8d3269b9f9 static/scripts/viz/trackster_ui.js
--- a/static/scripts/viz/trackster_ui.js
+++ b/static/scripts/viz/trackster_ui.js
@@ -75,7 +75,7 @@
});
// FIXME: give unique IDs to Drawables and save overview as ID.
- var overview_track_name = (view.overview_drawable ? view.overview_drawable.name : null),
+ var overview_track_name = (view.overview_drawable ? view.overview_drawable.prefs.name : null),
viz_config = {
'view': view.to_dict(),
'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high, 'overview': overview_track_name },
@@ -88,7 +88,7 @@
dataType: "json",
data: {
'id' : view.vis_id,
- 'title' : view.name,
+ 'title' : view.prefs.name,
'dbkey' : view.dbkey,
'type' : 'trackster',
'vis_json' : JSON.stringify(viz_config)
@@ -265,7 +265,7 @@
// Set overview.
var overview_drawable;
for (var i = 0; i < view.drawables.length; i++) {
- if (view.drawables[i].name === overview_drawable_name) {
+ if (view.drawables[i].prefs.name === overview_drawable_name) {
view.set_overview(view.drawables[i]);
break;
}
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: Set visualization naming to refer to new location.
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f0875c78b786/
Changeset: f0875c78b786
User: jgoecks
Date: 2013-10-18 04:22:36
Summary: Set visualization naming to refer to new location.
Affected #: 1 file
diff -r 0d46133c90452dc8815de7057b13548f06beb7bb -r f0875c78b7864c5ac75be62e9a52611bfa2a6cf0 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -197,7 +197,7 @@
init_editor : function ()
{
// set title
- $("#center .unified-panel-title").text(view.name + " (" + view.dbkey + ")");
+ $("#center .unified-panel-title").text(view.prefs.name + " (" + view.dbkey + ")");
// add dataset
if (galaxy_config.app.add_dataset)
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: jmchilton: Add smpt_ssl parameter to force SSL SMTP connection from start.
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0d46133c9045/
Changeset: 0d46133c9045
User: jmchilton
Date: 2013-10-18 01:09:55
Summary: Add smpt_ssl parameter to force SSL SMTP connection from start.
This is based on a slightly reworked commit from @aswarren (pull
request 198). I tweaked it by dropping smtp_from (as discussed in
pull request), and fixing a small string versus bool bug.
Tested both ways and it seems to work, with any luck though there is a
bug in there somewhere and Galaxy admins everywhere will get a break
until it is discovered :).
Affected #: 3 files
diff -r 90547efa211fb9c6480662129591ab28acbc0ffe -r 0d46133c90452dc8815de7057b13548f06beb7bb lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -159,6 +159,7 @@
self.smtp_server = kwargs.get( 'smtp_server', None )
self.smtp_username = kwargs.get( 'smtp_username', None )
self.smtp_password = kwargs.get( 'smtp_password', None )
+ self.smtp_ssl = kwargs.get( 'smtp_ssl', None )
self.track_jobs_in_database = kwargs.get( 'track_jobs_in_database', 'None' )
self.start_job_runners = listify(kwargs.get( 'start_job_runners', '' ))
self.expose_dataset_path = string_as_bool( kwargs.get( 'expose_dataset_path', 'False' ) )
diff -r 90547efa211fb9c6480662129591ab28acbc0ffe -r 0d46133c90452dc8815de7057b13548f06beb7bb lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -873,19 +873,24 @@
log.error( "Mail is not configured for this Galaxy instance." )
log.info( msg )
return
- s = smtplib.SMTP()
+ smtp_ssl = asbool( config.smtp_ssl )
+ if smtp_ssl:
+ s = smtplib.SMTP_SSL()
+ else:
+ s = smtplib.SMTP()
s.connect( config.smtp_server )
- try:
- s.starttls()
- log.debug( 'Initiated SSL/TLS connection to SMTP server: %s' % config.smtp_server )
- except RuntimeError, e:
- log.warning( 'SSL/TLS support is not available to your Python interpreter: %s' % e )
- except smtplib.SMTPHeloError, e:
- log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
- s.close()
- raise
- except smtplib.SMTPException, e:
- log.warning( 'The server does not support the STARTTLS extension: %s' % e )
+ if not smtp_ssl:
+ try:
+ s.starttls()
+ log.debug( 'Initiated SSL/TLS connection to SMTP server: %s' % config.smtp_server )
+ except RuntimeError, e:
+ log.warning( 'SSL/TLS support is not available to your Python interpreter: %s' % e )
+ except smtplib.SMTPHeloError, e:
+ log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
+ s.close()
+ raise
+ except smtplib.SMTPException, e:
+ log.warning( 'The server does not support the STARTTLS extension: %s' % e )
if config.smtp_username and config.smtp_password:
try:
s.login( config.smtp_username, config.smtp_password )
diff -r 90547efa211fb9c6480662129591ab28acbc0ffe -r 0d46133c90452dc8815de7057b13548f06beb7bb universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -263,6 +263,9 @@
#smtp_username = None
#smtp_password = None
+# If your SMTP server requires SSL from the beginning of the connection
+# smtp_ssl= False
+
# On the user registration form, users may choose to join the mailing list.
# This is the address of the list they'll be subscribed to.
#mailing_join_addr = galaxy-announce-join(a)bx.psu.edu
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/0b440d5c1667/
Changeset: 0b440d5c1667
User: nsoranzo
Date: 2013-10-17 12:46:13
Summary: Fix for "NotFound: cannot find 'cov_cutoff' while searching for 'expected.cov_cutoff'"
Affected #: 1 file
diff -r 329ea7a83af4f389a7c95ee4559d88c6fec0211b -r 0b440d5c1667b06e3a1eb3c8131b925e6da173fd tools/sr_assembly/velvetg.xml
--- a/tools/sr_assembly/velvetg.xml
+++ b/tools/sr_assembly/velvetg.xml
@@ -19,7 +19,7 @@
#if $expected.coverage == "auto":
-exp_cov auto
#elif $expected.coverage == "value":
- -exp_cov $expected.cov_cutoff
+ -exp_cov $expected.exp_cov
#end if
#if $contig_lgth.use_contig_lgth == "yes":
-min_contig_lgth $contig_lgth.min_contig_lgth
https://bitbucket.org/galaxy/galaxy-central/commits/90547efa211f/
Changeset: 90547efa211f
User: jmchilton
Date: 2013-10-18 00:27:23
Summary: Merge.
Affected #: 1 file
diff -r 0282484e4c323e1baf79d05813ea8213239a8b4e -r 90547efa211fb9c6480662129591ab28acbc0ffe tools/sr_assembly/velvetg.xml
--- a/tools/sr_assembly/velvetg.xml
+++ b/tools/sr_assembly/velvetg.xml
@@ -19,7 +19,7 @@
#if $expected.coverage == "auto":
-exp_cov auto
#elif $expected.coverage == "value":
- -exp_cov $expected.cov_cutoff
+ -exp_cov $expected.exp_cov
#end if
#if $contig_lgth.use_contig_lgth == "yes":
-min_contig_lgth $contig_lgth.min_contig_lgth
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: BjoernGruening: If you have a repeat tag and want to get the filetype from the first element you can't access the first element in a from_param type.
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0282484e4c32/
Changeset: 0282484e4c32
User: BjoernGruening
Date: 2013-08-14 19:07:31
Summary: If you have a repeat tag and want to get the filetype from the first element you can't access the first element in a from_param type.
That commit creates some artifical parameter called 'first' that you can use as value in param_attribute. For example:
<option type="from_param" name="singlePaired.mate_list" param_attribute="first.input_mate1.ext" />
I use that to retrive the filetype of paired end reads that are inserted in a repeat tag.
Assuming that every mate pair is from the same type as the first element.
Affected #: 1 file
diff -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 -r 0282484e4c323e1baf79d05813ea8213239a8b4e lib/galaxy/tools/parameters/output.py
--- a/lib/galaxy/tools/parameters/output.py
+++ b/lib/galaxy/tools/parameters/output.py
@@ -188,7 +188,14 @@
assert ref_name in value, "Required dependency '%s' not found in incoming values" % ref_name
value = value.get( ref_name )
for attr_name in self.param_attribute:
- value = getattr( value, attr_name )
+ # if the value is a list from a repeat tag you can access the first element of the repeat with
+ # artifical 'first' attribute_name. For example: .. param_attribute="first.input_mate1.ext"
+ if isinstance(value, list) and attr_name == 'first':
+ value = value[0]
+ elif isinstance(value, dict):
+ value = value[ attr_name ]
+ else:
+ value = getattr( value, attr_name )
options = [ [ str( value ) ] ]
for filter in self.filters:
options = filter.filter_options( options, other_values )
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: carlfeberhard: UI, Popupmenu: fix for IE 9; pack scripts
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5c9cfd1dea8b/
Changeset: 5c9cfd1dea8b
User: carlfeberhard
Date: 2013-10-17 22:05:29
Summary: UI, Popupmenu: fix for IE 9; pack scripts
Affected #: 7 files
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -213,226 +213,159 @@
});
// =============================================================================
-/**
+/**
* view for a popup menu
*/
-var PopupMenu = Backbone.View.extend(
-{
- /* TODO:
- add submenus
- add hrefs
- test various html keys
- add make_popupmenus style
- */
+var PopupMenu = Backbone.View.extend({
/** Cache the desired button element and options, set up the button click handler
* NOTE: attaches this view as HTML/jQ data on the button for later use.
*/
- //TODO: include docs on special option keys (divider, checked, etc.)
- initialize: function($button, options)
- {
+ initialize: function( $button, options ){
// default settings
- this.$button = $button || $('<div/>');
+ this.$button = $button || $( '<div/>' );
this.options = options || [];
// set up button click -> open menu behavior
var menu = this;
- this.$button.click(function(event)
- {
- menu._renderAndShow(event);
+ this.$button.click( function( event ){
+ menu._renderAndShow( event );
return false;
});
+ },
- // attach this view as a data object on the button - for later access
- //TODO:?? memleak?
- this.$button.data('PopupMenu', this);
+ // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show
+ _renderAndShow: function( clickEvent ){
+ this.render();
+ this.$el.appendTo( 'body' );
+ this.$el.css( this._getShownPosition( clickEvent ));
+ this._setUpCloseBehavior();
+ this.$el.show();
},
// render the menu
- // this menu doesn't attach itself to the DOM (see _renderAndShow)
- render: function()
- {
- // link this popup
- var menu = this;
-
- // render the menu body
- this.$el.addClass('popmenu-wrapper')
- .css(
- {
- position : 'absolute',
- display : 'none'
- });
-
- // use template
- this.$el.html(this.template(this.$button.attr('id'), this.options));
+ // this menu doesn't attach itself to the DOM ( see _renderAndShow )
+ render: function(){
+ // render the menu body absolute and hidden, fill with template
+ this.$el.addClass( 'popmenu-wrapper' ).hide()
+ .css({ position : 'absolute' })
+ .html( this.template( this.$button.attr( 'id' ), this.options ));
// set up behavior on each link/anchor elem
- if(this.options.length)
- {
- this.$el.find('li').each(function(i, li)
- {
- var $li = $(li),
- $anchor = $li.children( 'a.popupmenu-option' ),
- menuFunc = menu.options[i].func;
+ if( this.options.length ){
+ var menu = this;
+ //precondition: there should be one option per li
+ this.$el.find( 'li' ).each( function( i, li ){
+ var option = menu.options[i];
- // click event
- if($anchor.length && menuFunc)
- {
- $anchor.click(function(event)
- {
- menuFunc(event, menu.options[i]);
+ // if the option has 'func', call that function when the anchor is clicked
+ if( option.func ){
+ $( this ).children( 'a.popupmenu-option' ).click( function( event ){
+ option.func.call( menu, event, option );
+ // bubble up so that an option click will call the close behavior
+ //return false;
});
}
-
- // cache the anchor as a jq obj within the options obj
- menu.options[i].$li = $li;
});
}
return this;
},
+ template : function( id, options ){
+ return [
+ '<ul id="', id, '-menu" class="dropdown-menu">', this._templateOptions( options ), '</ul>'
+ ].join( '' );
+ },
+
+ _templateOptions : function( options ){
+ if( !options.length ){
+ return '<li>(no options)</li>';
+ }
+ return _.map( options, function( option ){
+ if( option.divider ){
+ return '<li class="divider"></li>';
+ } else if( option.header ){
+ return [ '<li class="head"><a href="javascript:void(0);">', option.html, '</a></li>' ].join( '' );
+ }
+ var href = option.href || 'javascript:void(0);',
+ target = ( option.target )?( ' target="' + target + '"' ):( '' ),
+ check = ( option.checked )?( '<span class="fa-icon-ok"></span>' ):( '' );
+ return [
+ '<li><a class="popupmenu-option" href="', href, '"', target, '>',
+ check, option.html,
+ '</a></li>'
+ ].join( '' );
+ }).join( '' );
+ },
+
// get the absolute position/offset for the menu
- _getShownPosition : function( clickEvent )
- {
- // get element width
+ _getShownPosition : function( clickEvent ){
+
+ // display menu horiz. centered on click...
var menuWidth = this.$el.width();
-
- // display menu horiz. centered on click...
var x = clickEvent.pageX - menuWidth / 2 ;
- // adjust to handle horiz. scroll and window dimensions (draw entirely on visible screen area)
+ // adjust to handle horiz. scroll and window dimensions ( draw entirely on visible screen area )
x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 );
x = Math.max( x, $( document ).scrollLeft() + 5 );
-
- // return
return {
top: clickEvent.pageY,
left: x
};
},
- // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show
- _renderAndShow: function(clickEvent)
- {
- this.render();
- this.$el.appendTo('body');
- this.$el.css( this._getShownPosition(clickEvent));
- this._setUpCloseBehavior();
- this.$el.show();
- },
-
// bind an event handler to all available frames so that when anything is clicked
// the menu is removed from the DOM and the event handler unbinds itself
- _setUpCloseBehavior: function()
- {
+ _setUpCloseBehavior: function(){
// function to close popup and unbind itself
var menu = this;
- var closePopupWhenClicked = function($elClicked)
- {
- $elClicked.bind("click.close_popup", function()
- {
+ var closePopupWhenClicked = function( $elClicked ){
+ $elClicked.one( "click.close_popup", function(){
menu.remove();
- $elClicked.unbind("click.close_popup");
});
};
// bind to current, parent, and sibling frames
- closePopupWhenClicked($(window.document));
- closePopupWhenClicked($(window.top.document));
- _.each(window.top.frames, function(siblingFrame)
- {
- closePopupWhenClicked($(siblingFrame.document));
+ closePopupWhenClicked( $( window.document ));
+ closePopupWhenClicked( $( window.top.document ));
+ _.each( window.top.frames, function( siblingFrame ){
+ closePopupWhenClicked( $( siblingFrame.document ));
});
},
// add a menu option/item at the given index
- addItem: function(item, index)
- {
+ addItem: function( item, index ){
// append to end if no index
- index = (index >= 0) ? index : this.options.length;
- this.options.splice(index, 0, item);
+ index = ( index >= 0 ) ? index : this.options.length;
+ this.options.splice( index, 0, item );
return this;
},
// remove a menu option/item at the given index
- removeItem: function(index)
- {
- if(index >=0)
- this.options.splice(index, 1);
+ removeItem: function( index ){
+ if( index >=0 ){
+ this.options.splice( index, 1 );
+ }
return this;
},
// search for a menu option by it's html
- findIndexByHtml: function(html)
- {
- for(var i = 0; i < this.options.length; i++)
- if(_.has(this.options[i], 'html') && (this.options[i].html === html))
+ findIndexByHtml: function( html ){
+ for( var i = 0; i < this.options.length; i++ ){
+ if( _.has( this.options[i], 'html' ) && ( this.options[i].html === html )){
return i;
+ }
+ }
return null;
},
// search for a menu option by it's html
- findItemByHtml: function(html)
- {
- return this.options[(this.findIndexByHtml(html))];
+ findItemByHtml: function( html ){
+ return this.options[( this.findIndexByHtml( html ))];
},
// string representation
- toString: function()
- {
+ toString: function(){
return 'PopupMenu';
- },
-
- // template
- template: function(id, options)
- {
- // initialize template
- var tmpl = '<ul id="' + id + '-menu" class="dropdown-menu">';
-
- // check item number
- if (options.length > 0)
- {
- // add option
- for (var i in options)
- {
- // get item
- var item = options[i];
-
- // check for divider
- if (item.divider)
- {
- // add divider
- tmpl += '<li class="divider"></li>';
- } else {
- // identify header
- if(item.header)
- {
- tmpl += '<li class="head"><a href="javascript:void(0);">' + item.html + '</a></li>';
- } else {
- // add href
- if (item.href)
- {
- tmpl += '<li><a href="' + item.href + '"';
- tmpl += 'target="' + item.target + '"';
- } else
- tmpl += '<li><a href="javascript:void(0);"';
-
- // add class
- tmpl += 'class="popupmenu-option">'
-
- // add target
- if (item.checked)
- tmpl += '<span class="fa-icon-ok"></span>';
-
- // add html
- tmpl += item.html;
- }
- }
- }
- } else
- tmpl += '<li>No Options.</li>';
-
- // return
- return tmpl + '</ul>';
}
});
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/galaxy.frame.js
--- a/static/scripts/packed/galaxy.frame.js
+++ b/static/scripts/packed/galaxy.frame.js
@@ -1,1 +1,1 @@
-define(["galaxy.master","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el_main:"#everything",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:9},cols:0,top:0,top_max:0,frame_z:0,frame_counter:0,frame_counter_id:0,frame_list:[],frame_shadow:null,visible:false,active:false,button_active:null,button_load:null,initialize:function(d){var c=this;this.button_active=new b.GalaxyMasterIcon({icon:"fa-icon-th",tooltip:"Enable/Disable Scratchbook",on_click:function(f){c.event_panel_active(f)}});Galaxy.master.append(this.button_active);this.button_load=new b.GalaxyMasterIcon({icon:"fa-icon-eye-open",tooltip:"Show/Hide Scratchbook",on_click:function(f){c.event_panel_load(f)},with_number:true});Galaxy.master.append(this.button_load);if(d){this.options=_.defaults(d,this.options)}this.top=this.top_max=this.options.top_min;this.setElement(this.template());$(this.el).append(this.template_background());$(this.el).append(this.template_menu());$(this.el_main).append($(this.el));var e="#frame-shadow";$(this.el).append(this.template_shadow(e.substring(1)));this.frame_shadow={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.frame_shadow,{width:0,height:0});this.frame_list[e]=this.frame_shadow;this.panel_refresh();var c=this;$(window).resize(function(){if(c.visible){c.panel_refresh()}});window.onbeforeunload=function(){if(c.frame_counter>0){return"You opened "+c.frame_counter+" frame(s) which will be lost."}}},event:{type:null,target:null,xy:null},events:{mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .frame":"event_frame_mouse_down","mousedown .frame-background":"event_panel_load","mousedown .frame-scroll-up":"event_panel_scroll_up","mousedown .frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"},event_frame_mouse_down:function(c){if(this.event.type!==null){return}if($(c.target).hasClass("f-header")||$(c.target).hasClass("f-title")){this.event.type="drag"}if($(c.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}c.preventDefault();this.event.target=this.event_get_frame(c.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:c.originalEvent.pageX,y:c.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(i){if(this.event.type!="drag"&&this.event.type!="resize"){return}var g={x:i.originalEvent.pageX,y:i.originalEvent.pageY};var d={x:g.x-this.event.xy.x,y:g.y-this.event.xy.y};this.event.xy=g;var h=this.frame_screen(this.event.target);if(this.event.type=="resize"){h.width+=d.x;h.height+=d.y;var f=this.options.cell-this.options.margin-1;h.width=Math.max(h.width,f);h.height=Math.max(h.height,f);this.frame_resize(this.event.target,h);h.width=this.to_grid_coord("width",h.width)+1;h.height=this.to_grid_coord("height",h.height)+1;h.width=this.to_pixel_coord("width",h.width);h.height=this.to_pixel_coord("height",h.height);this.frame_resize(this.frame_shadow,h);this.frame_insert(this.frame_shadow,{top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)})}if(this.event.type=="drag"){h.left+=d.x;h.top+=d.y;this.frame_offset(this.event.target,h);var c={top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)};if(c.left!==0){c.left++}this.frame_insert(this.frame_shadow,c)}},event_frame_mouse_up:function(c){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);var c=this;$(f.id).fadeOut("fast",function(){$(f.id).remove();delete c.frame_list[f.id];c.frame_counter--;c.panel_refresh(true);c.panel_animation_complete();if(c.visible&&c.frame_counter==0){c.panel_show_hide()}})},event_frame_lock:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this.event_get_frame(c.target);if(d.grid_lock){d.grid_lock=false;$(d.id).find(".f-pin").removeClass("toggle");$(d.id).find(".f-header").removeClass("f-not-allowed");$(d.id).find(".f-title").removeClass("f-not-allowed");$(d.id).find(".f-resize").show();$(d.id).find(".f-close").show()}else{d.grid_lock=true;$(d.id).find(".f-pin").addClass("toggle");$(d.id).find(".f-header").addClass("f-not-allowed");$(d.id).find(".f-title").addClass("f-not-allowed");$(d.id).find(".f-resize").hide();$(d.id).find(".f-close").hide()}},event_panel_load:function(c){if(this.event.type!==null){return}this.panel_show_hide()},event_panel_active:function(c){if(this.event.type!==null){return}this.panel_active_disable()},event_panel_scroll:function(c){if(this.event.type!==null||!this.visible){return}c.preventDefault();var d=c.originalEvent.detail?c.originalEvent.detail:c.originalEvent.wheelDelta/-3;this.panel_scroll(d)},event_panel_scroll_up:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(c){return this.frame_list["#"+$(c).closest(".frame").attr("id")]},frame_drag_start:function(d){this.frame_focus(d,true);var c=this.frame_screen(d);this.frame_resize(this.frame_shadow,c);this.frame_grid(this.frame_shadow,d.grid_location);d.grid_location=null;$(this.frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(d){this.frame_focus(d,false);var c=this.frame_screen(this.frame_shadow);this.frame_resize(d,c);this.frame_grid(d,this.frame_shadow.grid_location,true);this.frame_shadow.grid_location=null;$(this.frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(e,d){var c=(e=="width"||e=="height")?1:-1;if(e=="top"){d-=this.top}return parseInt((d+c*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(e,f){var c=(e=="width"||e=="height")?1:-1;var d=(f*this.options.cell)-c*this.options.margin;if(e=="top"){d+=this.top}return d},to_grid:function(c){return{top:this.to_grid_coord("top",c.top),left:this.to_grid_coord("left",c.left),width:this.to_grid_coord("width",c.width),height:this.to_grid_coord("height",c.height)}},to_pixel:function(c){return{top:this.to_pixel_coord("top",c.top),left:this.to_pixel_coord("left",c.left),width:this.to_pixel_coord("width",c.width),height:this.to_pixel_coord("height",c.height)}},is_collision:function(e){function c(h,g){return !(h.left>g.left+g.width-1||h.left+h.width-1<g.left||h.top>g.top+g.height-1||h.top+h.height-1<g.top)}for(var d in this.frame_list){var f=this.frame_list[d];if(f.grid_location===null){continue}if(c(e,f.grid_location)){return true}}return false},location_rank:function(c){return(c.top*this.cols)+c.left},menu_refresh:function(){this.button_load.number(this.frame_counter);if(this.frame_counter==0){this.button_load.hide()}else{this.button_load.show()}if(this.top==this.options.top_min){$(".frame-scroll-up").hide()}else{$(".frame-scroll-up").show()}if(this.top==this.top_max){$(".frame-scroll-down").hide()}else{$(".frame-scroll-down").show()}},panel_animation_complete:function(){var c=this;$(".frame").promise().done(function(){c.panel_scroll(0,true)})},panel_refresh:function(c){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,c)},panel_scroll:function(h,c){var e=this.top-this.options.scroll*h;e=Math.max(e,this.top_max);e=Math.min(e,this.options.top_min);if(this.top!=e){for(var d in this.frame_list){var g=this.frame_list[d];if(g.grid_location!==null){var f={top:g.screen_location.top-(this.top-e),left:g.screen_location.left};this.frame_offset(g,f,c)}}this.top=e}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".frame").fadeOut("fast");this.button_load.icon("fa-icon-eye-close");this.button_load.untoggle();$(".frame-background").hide();$(".frame-menu").hide()}else{this.visible=true;$(".frame").fadeIn("fast");this.button_load.icon("fa-icon-eye-open");this.button_load.toggle();$(this.frame_shadow.id).hide();$(".frame-background").show();this.panel_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;this.button_active.untoggle();if(this.visible){this.panel_show_hide()}}else{this.active=true;this.button_active.toggle()}},frame_new:function(d){if(!this.active){if(d.location=="center"){var c=$(window.parent.document).find("iframe#galaxy_main");c.attr("src",d.content)}else{window.location=d.content}return}if(this.frame_counter>=this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var e="#frame-"+(this.frame_counter_id++);if($(e).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.template_frame(e.substring(1),d.title,d.type,d.content));var f={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};d.width=this.to_pixel_coord("width",this.options.frame.cols);d.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_z=parseInt($(f.id).css("z-index"));this.frame_list[e]=f;this.frame_counter++;this.frame_resize(f,{width:d.width,height:d.height});this.frame_insert(f,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(j,c,e){var d=[];if(j){j.grid_location=null;d.push([j,this.location_rank(c)])}var g=null;for(g in this.frame_list){var h=this.frame_list[g];if(h.grid_location!==null&&!h.grid_lock){h.grid_location=null;d.push([h,h.grid_rank])}}d.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(g=0;g<d.length;g++){this.frame_place(d[g][0],e)}this.top_max=0;for(var g in this.frame_list){var j=this.frame_list[g];if(j.grid_location!==null){this.top_max=Math.max(this.top_max,j.grid_location.top+j.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(k,d){k.grid_location=null;var h=this.to_grid(this.frame_screen(k));var c=false;for(var f=0;f<this.options.rows;f++){for(var e=0;e<Math.max(1,this.cols-h.width);e++){h.top=f;h.left=e;if(!this.is_collision(h)){c=true;break}}if(c){break}}if(c){this.frame_grid(k,h,d)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(e,c){var d=this.frame_z+(c?1:0);$(e.id).css("z-index",d)},frame_offset:function(f,e,d){f.screen_location.left=e.left;f.screen_location.top=e.top;if(d){this.frame_focus(f,true);var c=this;$(f.id).animate({top:e.top,left:e.left},"fast",function(){c.frame_focus(f,false)})}else{$(f.id).css({top:e.top,left:e.left})}},frame_resize:function(d,c){$(d.id).css({width:c.width,height:c.height});d.screen_location.width=c.width;d.screen_location.height=c.height},frame_grid:function(e,c,d){e.grid_location=c;this.frame_offset(e,this.to_pixel(c),d);e.grid_rank=this.location_rank(c)},frame_screen:function(d){var c=d.screen_location;return{top:c.top,left:c.left,width:c.width,height:c.height}},template:function(){return'<div class="galaxy-frame"></div>'},template_frame:function(f,e,c,d){if(!e){e=""}if(c=="url"){d='<iframe scrolling="auto" class="f-iframe" src="'+d+'"></iframe>'}return'<div id="'+f+'" class="frame corner"><div class="f-header corner"><span class="f-title">'+e+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content">'+d+'<div class="f-cover"></div></div><span class="f-resize f-icon corner fa-icon-resize-full"></span></div>'},template_shadow:function(c){return'<div id="'+c+'" class="frame-shadow corner"></div>'},template_background:function(){return'<div class="frame-background"></div>'},template_menu:function(){return'<div class="frame-scroll-up frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="frame-scroll-down frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
+define(["galaxy.master","libs/backbone/backbone-relational"],function(b){var a=Backbone.View.extend({el_main:"#everything",options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:9},cols:0,top:0,top_max:0,frame_z:0,frame_counter:0,frame_counter_id:0,frame_list:[],frame_shadow:null,visible:false,active:false,button_active:null,button_load:null,initialize:function(d){var c=this;this.button_active=new b.GalaxyMasterIcon({icon:"fa-icon-th",tooltip:"Enable/Disable Scratchbook",on_click:function(f){c.event_panel_active(f)},on_unload:function(){if(c.frame_counter>0){return"You opened "+c.frame_counter+" frame(s) which will be lost."}}});Galaxy.master.append(this.button_active);this.button_load=new b.GalaxyMasterIcon({icon:"fa-icon-eye-open",tooltip:"Show/Hide Scratchbook",on_click:function(f){c.event_panel_load(f)},with_number:true});Galaxy.master.append(this.button_load);if(d){this.options=_.defaults(d,this.options)}this.top=this.top_max=this.options.top_min;this.setElement(this.template());$(this.el).append(this.template_background());$(this.el).append(this.template_menu());$(this.el_main).append($(this.el));var e="#frame-shadow";$(this.el).append(this.template_shadow(e.substring(1)));this.frame_shadow={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this.frame_resize(this.frame_shadow,{width:0,height:0});this.frame_list[e]=this.frame_shadow;this.panel_refresh();var c=this;$(window).resize(function(){if(c.visible){c.panel_refresh()}})},event:{type:null,target:null,xy:null},events:{mousemove:"event_frame_mouse_move",mouseup:"event_frame_mouse_up",mouseleave:"event_frame_mouse_up",mousewheel:"event_panel_scroll",DOMMouseScroll:"event_panel_scroll","mousedown .frame":"event_frame_mouse_down","mousedown .frame-background":"event_panel_load","mousedown .frame-scroll-up":"event_panel_scroll_up","mousedown .frame-scroll-down":"event_panel_scroll_down","mousedown .f-close":"event_frame_close","mousedown .f-pin":"event_frame_lock"},event_frame_mouse_down:function(c){if(this.event.type!==null){return}if($(c.target).hasClass("f-header")||$(c.target).hasClass("f-title")){this.event.type="drag"}if($(c.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}c.preventDefault();this.event.target=this.event_get_frame(c.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:c.originalEvent.pageX,y:c.originalEvent.pageY};this.frame_drag_start(this.event.target)},event_frame_mouse_move:function(i){if(this.event.type!="drag"&&this.event.type!="resize"){return}var g={x:i.originalEvent.pageX,y:i.originalEvent.pageY};var d={x:g.x-this.event.xy.x,y:g.y-this.event.xy.y};this.event.xy=g;var h=this.frame_screen(this.event.target);if(this.event.type=="resize"){h.width+=d.x;h.height+=d.y;var f=this.options.cell-this.options.margin-1;h.width=Math.max(h.width,f);h.height=Math.max(h.height,f);this.frame_resize(this.event.target,h);h.width=this.to_grid_coord("width",h.width)+1;h.height=this.to_grid_coord("height",h.height)+1;h.width=this.to_pixel_coord("width",h.width);h.height=this.to_pixel_coord("height",h.height);this.frame_resize(this.frame_shadow,h);this.frame_insert(this.frame_shadow,{top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)})}if(this.event.type=="drag"){h.left+=d.x;h.top+=d.y;this.frame_offset(this.event.target,h);var c={top:this.to_grid_coord("top",h.top),left:this.to_grid_coord("left",h.left)};if(c.left!==0){c.left++}this.frame_insert(this.frame_shadow,c)}},event_frame_mouse_up:function(c){if(this.event.type!="drag"&&this.event.type!="resize"){return}this.frame_drag_stop(this.event.target);this.event.type=null},event_frame_close:function(d){if(this.event.type!==null){return}d.preventDefault();var f=this.event_get_frame(d.target);var c=this;$(f.id).fadeOut("fast",function(){$(f.id).remove();delete c.frame_list[f.id];c.frame_counter--;c.panel_refresh(true);c.panel_animation_complete();if(c.visible&&c.frame_counter==0){c.panel_show_hide()}})},event_frame_lock:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this.event_get_frame(c.target);if(d.grid_lock){d.grid_lock=false;$(d.id).find(".f-pin").removeClass("toggle");$(d.id).find(".f-header").removeClass("f-not-allowed");$(d.id).find(".f-title").removeClass("f-not-allowed");$(d.id).find(".f-resize").show();$(d.id).find(".f-close").show()}else{d.grid_lock=true;$(d.id).find(".f-pin").addClass("toggle");$(d.id).find(".f-header").addClass("f-not-allowed");$(d.id).find(".f-title").addClass("f-not-allowed");$(d.id).find(".f-resize").hide();$(d.id).find(".f-close").hide()}},event_panel_load:function(c){if(this.event.type!==null){return}this.panel_show_hide()},event_panel_active:function(c){if(this.event.type!==null){return}this.panel_active_disable()},event_panel_scroll:function(c){if(this.event.type!==null||!this.visible){return}c.preventDefault();var d=c.originalEvent.detail?c.originalEvent.detail:c.originalEvent.wheelDelta/-3;this.panel_scroll(d)},event_panel_scroll_up:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(-this.options.scroll)},event_panel_scroll_down:function(c){if(this.event.type!==null){return}c.preventDefault();this.panel_scroll(this.options.scroll)},event_get_frame:function(c){return this.frame_list["#"+$(c).closest(".frame").attr("id")]},frame_drag_start:function(d){this.frame_focus(d,true);var c=this.frame_screen(d);this.frame_resize(this.frame_shadow,c);this.frame_grid(this.frame_shadow,d.grid_location);d.grid_location=null;$(this.frame_shadow.id).show();$(".f-cover").show()},frame_drag_stop:function(d){this.frame_focus(d,false);var c=this.frame_screen(this.frame_shadow);this.frame_resize(d,c);this.frame_grid(d,this.frame_shadow.grid_location,true);this.frame_shadow.grid_location=null;$(this.frame_shadow.id).hide();$(".f-cover").hide();this.panel_animation_complete()},to_grid_coord:function(e,d){var c=(e=="width"||e=="height")?1:-1;if(e=="top"){d-=this.top}return parseInt((d+c*this.options.margin)/this.options.cell,10)},to_pixel_coord:function(e,f){var c=(e=="width"||e=="height")?1:-1;var d=(f*this.options.cell)-c*this.options.margin;if(e=="top"){d+=this.top}return d},to_grid:function(c){return{top:this.to_grid_coord("top",c.top),left:this.to_grid_coord("left",c.left),width:this.to_grid_coord("width",c.width),height:this.to_grid_coord("height",c.height)}},to_pixel:function(c){return{top:this.to_pixel_coord("top",c.top),left:this.to_pixel_coord("left",c.left),width:this.to_pixel_coord("width",c.width),height:this.to_pixel_coord("height",c.height)}},is_collision:function(e){function c(h,g){return !(h.left>g.left+g.width-1||h.left+h.width-1<g.left||h.top>g.top+g.height-1||h.top+h.height-1<g.top)}for(var d in this.frame_list){var f=this.frame_list[d];if(f.grid_location===null){continue}if(c(e,f.grid_location)){return true}}return false},location_rank:function(c){return(c.top*this.cols)+c.left},menu_refresh:function(){this.button_load.number(this.frame_counter);if(this.frame_counter==0){this.button_load.hide()}else{this.button_load.show()}if(this.top==this.options.top_min){$(".frame-scroll-up").hide()}else{$(".frame-scroll-up").show()}if(this.top==this.top_max){$(".frame-scroll-down").hide()}else{$(".frame-scroll-down").show()}},panel_animation_complete:function(){var c=this;$(".frame").promise().done(function(){c.panel_scroll(0,true)})},panel_refresh:function(c){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this.frame_insert(null,null,c)},panel_scroll:function(h,c){var e=this.top-this.options.scroll*h;e=Math.max(e,this.top_max);e=Math.min(e,this.options.top_min);if(this.top!=e){for(var d in this.frame_list){var g=this.frame_list[d];if(g.grid_location!==null){var f={top:g.screen_location.top-(this.top-e),left:g.screen_location.left};this.frame_offset(g,f,c)}}this.top=e}this.menu_refresh()},panel_show_hide:function(){if(this.visible){this.visible=false;$(".frame").fadeOut("fast");this.button_load.icon("fa-icon-eye-close");this.button_load.untoggle();$(".frame-background").hide();$(".frame-menu").hide()}else{this.visible=true;$(".frame").fadeIn("fast");this.button_load.icon("fa-icon-eye-open");this.button_load.toggle();$(this.frame_shadow.id).hide();$(".frame-background").show();this.panel_refresh()}},panel_active_disable:function(){if(this.active){this.active=false;this.button_active.untoggle();if(this.visible){this.panel_show_hide()}}else{this.active=true;this.button_active.toggle()}},frame_new:function(d){if(!this.active){if(d.location=="center"){var c=$(window.parent.document).find("iframe#galaxy_main");c.attr("src",d.content)}else{window.location=d.content}return}if(this.frame_counter>=this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var e="#frame-"+(this.frame_counter_id++);if($(e).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;$(this.el).append(this.template_frame(e.substring(1),d.title,d.type,d.content));var f={id:e,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};d.width=this.to_pixel_coord("width",this.options.frame.cols);d.height=this.to_pixel_coord("height",this.options.frame.rows);this.frame_z=parseInt($(f.id).css("z-index"));this.frame_list[e]=f;this.frame_counter++;this.frame_resize(f,{width:d.width,height:d.height});this.frame_insert(f,{top:0,left:0},true);if(!this.visible){this.panel_show_hide()}},frame_insert:function(j,c,e){var d=[];if(j){j.grid_location=null;d.push([j,this.location_rank(c)])}var g=null;for(g in this.frame_list){var h=this.frame_list[g];if(h.grid_location!==null&&!h.grid_lock){h.grid_location=null;d.push([h,h.grid_rank])}}d.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(g=0;g<d.length;g++){this.frame_place(d[g][0],e)}this.top_max=0;for(var g in this.frame_list){var j=this.frame_list[g];if(j.grid_location!==null){this.top_max=Math.max(this.top_max,j.grid_location.top+j.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this.menu_refresh()},frame_place:function(k,d){k.grid_location=null;var h=this.to_grid(this.frame_screen(k));var c=false;for(var f=0;f<this.options.rows;f++){for(var e=0;e<Math.max(1,this.cols-h.width);e++){h.top=f;h.left=e;if(!this.is_collision(h)){c=true;break}}if(c){break}}if(c){this.frame_grid(k,h,d)}else{console.log("Grid dimensions exceeded.")}},frame_focus:function(e,c){var d=this.frame_z+(c?1:0);$(e.id).css("z-index",d)},frame_offset:function(f,e,d){f.screen_location.left=e.left;f.screen_location.top=e.top;if(d){this.frame_focus(f,true);var c=this;$(f.id).animate({top:e.top,left:e.left},"fast",function(){c.frame_focus(f,false)})}else{$(f.id).css({top:e.top,left:e.left})}},frame_resize:function(d,c){$(d.id).css({width:c.width,height:c.height});d.screen_location.width=c.width;d.screen_location.height=c.height},frame_grid:function(e,c,d){e.grid_location=c;this.frame_offset(e,this.to_pixel(c),d);e.grid_rank=this.location_rank(c)},frame_screen:function(d){var c=d.screen_location;return{top:c.top,left:c.left,width:c.width,height:c.height}},template:function(){return'<div class="galaxy-frame"></div>'},template_frame:function(f,e,c,d){if(!e){e=""}if(c=="url"){d='<iframe scrolling="auto" class="f-iframe" src="'+d+'"></iframe>'}return'<div id="'+f+'" class="frame corner"><div class="f-header corner"><span class="f-title">'+e+'</span><span class="f-icon f-pin fa-icon-pushpin"></span><span class="f-icon f-close fa-icon-trash"></span></div><div class="f-content">'+d+'<div class="f-cover"></div></div><span class="f-resize f-icon corner fa-icon-resize-full"></span></div>'},template_shadow:function(c){return'<div id="'+c+'" class="frame-shadow corner"></div>'},template_background:function(){return'<div class="frame-background"></div>'},template_menu:function(){return'<div class="frame-scroll-up frame-menu fa-icon-chevron-up fa-icon-2x"></div><div class="frame-scroll-down frame-menu fa-icon-chevron-down fa-icon-2x"></div>'}});return{GalaxyFrameManager:a}});
\ No newline at end of file
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/galaxy.master.js
--- a/static/scripts/packed/galaxy.master.js
+++ b/static/scripts/packed/galaxy.master.js
@@ -1,1 +1,1 @@
-define(["libs/backbone/backbone-relational"],function(){var a=Backbone.View.extend({el_master:"#masthead",initialize:function(c){this.setElement($(this.template()));$(this.el_master).append($(this.el))},events:{mousedown:function(c){c.preventDefault()}},append:function(c){$(this.el).append($(c.el))},prepend:function(c){$(this.el).prepend($(c.el))},template:function(){return'<div class="iconbar"></div>'}});var b=Backbone.View.extend({options:{id:"galaxy-icon",icon:"fa-icon-cog",tooltip:"galaxy-icon",with_number:false,on_click:function(){alert("clicked")},visible:true},initialize:function(d){if(d){this.options=_.defaults(d,this.options)}this.setElement($(this.template(this.options)));var c=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip}).on("click",c.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(c){$(this.el).find(".icon").removeClass(this.options.icon).addClass(c);this.options.icon=c},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(c){$(this.el).find(".number").text(c)},template:function(d){var c="<div id="+d.id+' class="symbol"><div class="icon fa-icon-2x '+d.icon+'"></div>';if(d.with_number){c+='<div class="number"></div>'}c+="</div>";return c}});return{GalaxyMaster:a,GalaxyMasterIcon:b}});
\ No newline at end of file
+define(["libs/backbone/backbone-relational"],function(){var a=Backbone.View.extend({el_master:"#masthead",list:[],initialize:function(d){this.setElement($(this.template()));$(this.el_master).append($(this.el));var c=this;window.onbeforeunload=function(){var f="";for(key in c.list){if(c.list[key].options.on_unload){var e=c.list[key].options.on_unload();if(e){f+=e+" "}}}if(f!=""){return f}}},events:{mousedown:function(c){c.preventDefault()}},append:function(c){$(this.el).append($(c.el));this.list.push(c)},prepend:function(c){$(this.el).prepend($(c.el));this.list.push(c)},template:function(){return'<div class="iconbar"></div>'}});var b=Backbone.View.extend({options:{id:"galaxy-icon",icon:"fa-icon-cog",tooltip:"galaxy-icon",with_number:false,on_click:function(){alert("clicked")},on_unload:null,visible:true},initialize:function(d){if(d){this.options=_.defaults(d,this.options)}this.setElement($(this.template(this.options)));var c=this;$(this.el).find(".icon").tooltip({title:this.options.tooltip}).on("click",c.options.on_click);if(!this.options.visible){this.hide()}},show:function(){$(this.el).css({visibility:"visible"})},hide:function(){$(this.el).css({visibility:"hidden"})},icon:function(c){$(this.el).find(".icon").removeClass(this.options.icon).addClass(c);this.options.icon=c},toggle:function(){$(this.el).addClass("toggle")},untoggle:function(){$(this.el).removeClass("toggle")},number:function(c){$(this.el).find(".number").text(c)},template:function(d){var c="<div id="+d.id+' class="symbol"><div class="icon fa-icon-2x '+d.icon+'"></div>';if(d.with_number){c+='<div class="number"></div>'}c+="</div>";return c}});return{GalaxyMaster:a,GalaxyMasterIcon:b}});
\ No newline at end of file
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/galaxy.modal.js
--- a/static/scripts/packed/galaxy.modal.js
+++ b/static/scripts/packed/galaxy.modal.js
@@ -1,1 +1,1 @@
-define(["libs/backbone/backbone-relational"],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true},options:{},initialize:function(b){if(b){this.create(b)}},show:function(b){this.initialize(b);var c=$(document).height()/2;this.$body.css("max-height",c);if(this.options.height){this.$body.css("height",Math.min(this.options.height,c))}if(this.options.height){this.$body.css("overflow","hidden")}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},create:function(c){this.options=_.defaults(c,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove()}this.setElement(this.template(this.options.title));this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);this.$body.css("min-width",this.$body.width());if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){var b=this;$.each(this.options.buttons,function(d,e){b.$buttons.append($('<button id="'+String(d).toLowerCase()+'"></button>').text(d).click(e)).append(" ")})}else{this.$footer.hide()}$(this.elMain).append($(this.el))},enableButton:function(b){this.$buttons.find("#"+String(b).toLowerCase()).prop("disabled",false)},disableButton:function(b){this.$buttons.find("#"+String(b).toLowerCase()).prop("disabled",true)},scrollTop:function(){return this.$body.scrollTop()},template:function(b){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+b+'</h4></div><div class="modal-body"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{GalaxyModal:a}});
\ No newline at end of file
+define(["libs/backbone/backbone-relational"],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true,height:null,width:null},options:{},initialize:function(b){if(b){this.create(b)}},show:function(b){this.initialize(b);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},create:function(c){this.options=_.defaults(c,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove()}this.setElement(this.template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){var b=this;$.each(this.options.buttons,function(d,e){b.$buttons.append($('<button id="'+String(d).toLowerCase()+'"></button>').text(d).click(e)).append(" ")})}else{this.$footer.hide()}$(this.elMain).append($(this.el))},enableButton:function(b){this.$buttons.find("#"+String(b).toLowerCase()).prop("disabled",false)},disableButton:function(b){this.$buttons.find("#"+String(b).toLowerCase()).prop("disabled",true)},scrollTop:function(){return this.$body.scrollTop()},template:function(b){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+b+'</h4></div><div class="modal-body"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{GalaxyModal:a}});
\ No newline at end of file
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/galaxy.upload.js
--- a/static/scripts/packed/galaxy.upload.js
+++ b/static/scripts/packed/galaxy.upload.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","galaxy.master","utils/galaxy.utils","utils/galaxy.uploadbox","libs/backbone/backbone-relational"],function(b,d,c){var a=Backbone.View.extend({modal:null,button_show:null,uploadbox:null,select_extension:{auto:"Auto-detect"},state:{init:"fa-icon-trash",queued:"fa-icon-spinner fa-icon-spin",running:"__running__",success:"fa-icon-ok",error:"fa-icon-warning-sign"},counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(){if(!Galaxy.currHistoryPanel){var e=this;window.setTimeout(function(){e.initialize()},500);return}var e=this;this.button_show=new d.GalaxyMasterIcon({icon:"fa-icon-upload",tooltip:"Upload Files",on_click:function(f){e.event_show(f)},with_number:true});Galaxy.master.prepend(this.button_show);var e=this;c.jsonFromUrl(galaxy_config.root+"api/datatypes",function(g){for(key in g){var f=g[key];e.select_extension[f]=f}})},event_dragover:function(f){},event_dragleave:function(f){},event_announce:function(f,g,i){var j="#upload-"+f;$(this.el).find("tbody:last").append(this.template_row(j,this.select_extension));var h=this.get_upload_item(f);h.fadeIn();h.find("#title").html(g.name);h.find("#size").html(this.size_to_string(g.size));var e=this;h.find("#symbol").on("click",function(){e.event_remove(f)});this.event_progress(f,g,0);this.counter.announce++;this.update_screen()},event_initialize:function(g,h,k){this.button_show.number(this.counter.announce);var i=this.get_upload_item(g);var l=i.find("#symbol");l.addClass(this.state.running);var e=Galaxy.currHistoryPanel.model.get("id");var f=i.find("#extension").val();var j=i.find("#space_to_tabs").is(":checked");this.uploadbox.configure({url:galaxy_config.root+"api/tools/",paramname:"files_0|file_data"});tool_input={};tool_input.dbkey="?";tool_input.file_type=f;tool_input["files_0|NAME"]=h.name;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=j;data={};data.history_id=e;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},event_progress:function(f,g,i){var h=this.get_upload_item(f);var e=parseInt(i);h.find(".progress-bar").css({width:e+"%"});if(e!=100){h.find("#percentage").html(e+"%")}else{h.find("#percentage").html("Adding to history...")}},event_success:function(e,f,h){this.event_progress(e,f,100);this.button_show.number("");this.counter.announce--;this.counter.success++;this.update_screen();var g=this.get_upload_item(e);g.addClass("success");g.find("#percentage").html("100%");var i=g.find("#symbol");i.removeClass(this.state.running);i.removeClass(this.state.queued);i.addClass(this.state.success);Galaxy.currHistoryPanel.refresh()},event_error:function(e,f,h){this.event_progress(e,f,0);this.button_show.number("");this.counter.announce--;this.counter.error++;this.update_screen();var g=this.get_upload_item(e);g.addClass("danger");g.find(".progress").remove();g.find("#info").html("<strong>Failed: </strong>"+h).show();var i=g.find("#symbol");i.removeClass(this.state.running);i.removeClass(this.state.queued);i.addClass(this.state.error)},event_upload:function(){if(this.counter.announce==0||this.counter.running>0){return}var f=$(this.el).find(".upload-item");var e=this;f.each(function(){var g=$(this).find("#symbol");if(g.hasClass(e.state.init)){g.removeClass(e.state.init);g.addClass(e.state.queued);$(this).find("#extension").attr("disabled",true);$(this).find("#space_to_tabs").attr("disabled",true)}});this.counter.running=this.counter.announce;this.update_screen();this.uploadbox.upload()},event_pause:function(){if(this.counter.running==0){return}this.uploadbox.pause();$("#upload-info").html("Queueing will pause after completing the current file...")},event_complete:function(){this.counter.running=0;this.update_screen();var f=$(this.el).find(".upload-item");var e=this;f.each(function(){var g=$(this).find("#symbol");if(g.hasClass(e.state.queued)&&!g.hasClass(e.state.running)){g.removeClass(e.state.queued);g.addClass(e.state.init);$(this).find("#extension").attr("disabled",false);$(this).find("#space_to_tabs").attr("disabled",false)}})},event_reset:function(){if(this.counter.running==0){var e=$(this.el).find(".upload-item");$(this.el).find("table").fadeOut({complete:function(){e.remove()}});this.counter.reset();this.update_screen();this.uploadbox.reset()}},event_remove:function(e){var f=this.get_upload_item(e);var g=f.find("#symbol");if(g.hasClass(this.state.init)||g.hasClass(this.state.success)||g.hasClass(this.state.error)){if(f.hasClass("success")){this.counter.success--}else{if(f.hasClass("danger")){this.counter.error--}else{this.counter.announce--}}this.update_screen();this.uploadbox.remove(e);f.remove()}},event_show:function(g){g.preventDefault();if(!this.modal){var f=this;this.modal=new b.GalaxyModal({title:"Upload files from your local drive",body:this.template("upload-box","upload-info"),buttons:{Select:function(){f.uploadbox.select()},Upload:function(){f.event_upload()},Pause:function(){f.event_pause()},Reset:function(){f.event_reset()},Close:function(){f.modal.hide()}},height:"350"});this.setElement("#upload-box");var f=this;this.uploadbox=this.$el.uploadbox({dragover:function(){f.event_dragover()},dragleave:function(){f.event_dragleave()},announce:function(e,h,i){f.event_announce(e,h,i)},initialize:function(e,h,i){return f.event_initialize(e,h,i)},success:function(e,h,i){f.event_success(e,h,i)},progress:function(e,h,i){f.event_progress(e,h,i)},error:function(e,h,i){f.event_error(e,h,i)},complete:function(){f.event_complete()},});this.update_screen()}this.modal.show()},get_upload_item:function(e){return $(this.el).find("#upload-"+e)},size_to_string:function(e){var f="";if(e>=100000000000){e=e/100000000000;f="TB"}else{if(e>=100000000){e=e/100000000;f="GB"}else{if(e>=100000){e=e/100000;f="MB"}else{if(e>=100){e=e/100;f="KB"}else{e=e*10;f="b"}}}}return"<strong>"+(Math.round(e)/10)+"</strong> "+f},update_screen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible){message="Drag&drop files into this box or click 'Select' to select files!"}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Please upgrade to i.e. Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Upload' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Upload")}else{this.modal.disableButton("Upload")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Select")}else{this.modal.disableButton("Select")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("table").show()}else{$(this.el).find("table").hide()}},template:function(f,e){return'<div id="'+f+'" class="upload-box"><table class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Space→Tab</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+e+'" class="upload-info"></h6>'},template_row:function(g,f){var e='<tr id="'+g.substr(1)+'" class="upload-item"><td><div id="title" class="title"></div></td><td><div id="size" class="size"></div></td><td><select id="extension" class="extension">';for(key in f){e+='<option value="'+key+'">'+f[key]+"</option>"}e+='</select></td><td><input id="space_to_tabs" type="checkbox"></input></td><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="symbol '+this.state.init+'"></div></td></tr>';return e}});return{GalaxyUpload:a}});
\ No newline at end of file
+define(["galaxy.modal","galaxy.master","utils/galaxy.utils","utils/galaxy.uploadbox","libs/backbone/backbone-relational"],function(b,d,c){var a=Backbone.View.extend({modal:null,button_show:null,uploadbox:null,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],state:{init:"fa-icon-trash",queued:"fa-icon-spinner fa-icon-spin",running:"__running__",success:"fa-icon-ok",error:"fa-icon-warning-sign"},counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(){if(!Galaxy.currHistoryPanel){var e=this;window.setTimeout(function(){e.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}var e=this;this.button_show=new d.GalaxyMasterIcon({icon:"fa-icon-upload",tooltip:"Upload Files",on_click:function(f){e.event_show(f)},on_unload:function(){if(e.counter.running>0){return"Several uploads are still processing."}},with_number:true});Galaxy.master.prepend(this.button_show);var e=this;c.jsonFromUrl(galaxy_config.root+"api/datatypes",function(f){for(key in f){e.select_extension.push([f[key],f[key]])}});c.jsonFromUrl(galaxy_config.root+"api/genomes",function(f){var g=e.select_genome[0];e.select_genome=[];for(key in f){if(f[key].length>1){if(f[key][1]!==g[1]){e.select_genome.push(f[key])}}}e.select_genome.sort(function(i,h){return i[0]>h[0]?1:i[0]<h[0]?-1:0});e.select_genome.unshift(g)})},event_dragover:function(f){},event_dragleave:function(f){},event_announce:function(i,g,n){var f="#upload-"+i;$(this.el).find("tbody:last").append(this.template_row(f));var h=this.get_upload_item(i);h.fadeIn();h.find("#title").html(g.name);h.find("#size").html(this.size_to_string(g.size));var m=this;h.find("#symbol").on("click",function(){m.event_remove(i)});h.find("#text-content").on("keyup",function(){var o=h.find("#text-content").val().length;h.find("#size").html(m.size_to_string(o))});this.event_progress(i,g,0);this.counter.announce++;this.update_screen();if(g.size==-1){var l=h.find("#text");var j=8;var e=h.width()-2*j;var k=h.height()-j;l.css("width",e+"px");l.css("top",k+"px");h.height(k+l.height()+2*j);l.show()}},event_initialize:function(i,e,n){this.button_show.number(this.counter.announce);var g=this.get_upload_item(i);var k=g.find("#symbol");k.addClass(this.state.running);var j=Galaxy.currHistoryPanel.model.get("id");var f=g.find("#extension").val();var m=g.find("#genome").val();var l=g.find("#text-content").val();var h=g.find("#space_to_tabs").is(":checked");if(!l&&!(e.size>0)){return null}this.uploadbox.configure({url:galaxy_config.root+"api/tools/",paramname:"files_0|file_data"});tool_input={};tool_input.dbkey=m;tool_input.file_type=f;tool_input["files_0|NAME"]=e.name;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=l;tool_input.space_to_tabs=h;data={};data.history_id=j;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},event_progress:function(f,g,i){var h=this.get_upload_item(f);var e=parseInt(i);h.find(".progress-bar").css({width:e+"%"});if(e!=100){h.find("#percentage").html(e+"%")}else{h.find("#percentage").html("Adding to history...")}},event_success:function(e,f,h){this.event_progress(e,f,100);this.button_show.number("");this.counter.announce--;this.counter.success++;this.update_screen();var g=this.get_upload_item(e);g.addClass("success");g.find("#percentage").html("100%");var i=g.find("#symbol");i.removeClass(this.state.running);i.removeClass(this.state.queued);i.addClass(this.state.success);Galaxy.currHistoryPanel.refresh()},event_error:function(e,f,h){this.event_progress(e,f,0);this.button_show.number("");this.counter.announce--;this.counter.error++;this.update_screen();var g=this.get_upload_item(e);g.addClass("danger");g.find(".progress").remove();g.find("#info").html("<strong>Failed: </strong>"+h).show();var i=g.find("#symbol");i.removeClass(this.state.running);i.removeClass(this.state.queued);i.addClass(this.state.error)},event_start:function(){if(this.counter.announce==0||this.counter.running>0){return}var f=$(this.el).find(".upload-item");var e=this;f.each(function(){var g=$(this).find("#symbol");if(g.hasClass(e.state.init)){g.removeClass(e.state.init);g.addClass(e.state.queued);$(this).find("#text-content").attr("disabled",true);$(this).find("#genome").attr("disabled",true);$(this).find("#extension").attr("disabled",true);$(this).find("#space_to_tabs").attr("disabled",true)}});this.counter.running=this.counter.announce;this.update_screen();this.uploadbox.start()},event_stop:function(){if(this.counter.running==0){return}this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},event_complete:function(){this.counter.running=0;this.update_screen();var f=$(this.el).find(".upload-item");var e=this;f.each(function(){var g=$(this).find("#symbol");if(g.hasClass(e.state.queued)&&!g.hasClass(e.state.running)){g.removeClass(e.state.queued);g.addClass(e.state.init);$(this).find("#text-content").attr("disabled",false);$(this).find("#genome").attr("disabled",false);$(this).find("#extension").attr("disabled",false);$(this).find("#space_to_tabs").attr("disabled",false)}})},event_reset:function(){if(this.counter.running==0){var e=$(this.el).find(".upload-item");$(this.el).find("table").fadeOut({complete:function(){e.remove()}});this.counter.reset();this.update_screen();this.uploadbox.reset()}},event_remove:function(e){var f=this.get_upload_item(e);var g=f.find("#symbol");if(g.hasClass(this.state.init)||g.hasClass(this.state.success)||g.hasClass(this.state.error)){if(f.hasClass("success")){this.counter.success--}else{if(f.hasClass("danger")){this.counter.error--}else{this.counter.announce--}}this.update_screen();this.uploadbox.remove(e);f.remove()}},event_create:function(){this.uploadbox.add([{name:"New File",size:-1}])},event_show:function(g){g.preventDefault();if(!this.modal){var f=this;this.modal=new b.GalaxyModal({title:"Upload files from your local drive",body:this.template("upload-box","upload-info"),buttons:{Select:function(){f.uploadbox.select()},Create:function(){f.event_create()},Upload:function(){f.event_start()},Pause:function(){f.event_stop()},Reset:function(){f.event_reset()},Close:function(){f.modal.hide()},},height:"400",width:"900"});this.setElement("#upload-box");var f=this;this.uploadbox=this.$el.uploadbox({dragover:function(){f.event_dragover()},dragleave:function(){f.event_dragleave()},announce:function(e,h,i){f.event_announce(e,h,i)},initialize:function(e,h,i){return f.event_initialize(e,h,i)},success:function(e,h,i){f.event_success(e,h,i)},progress:function(e,h,i){f.event_progress(e,h,i)},error:function(e,h,i){f.event_error(e,h,i)},complete:function(){f.event_complete()},});this.update_screen()}this.modal.show()},get_upload_item:function(e){return $(this.el).find("#upload-"+e)},size_to_string:function(e){var f="";if(e>=100000000000){e=e/100000000000;f="TB"}else{if(e>=100000000){e=e/100000000;f="GB"}else{if(e>=100000){e=e/100000;f="MB"}else{if(e>=100){e=e/100;f="KB"}else{if(e>0){e=e*10;f="b"}else{return"<strong>-</strong>"}}}}}return"<strong>"+(Math.round(e)/10)+"</strong> "+f},update_screen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="Drag&drop files into this box or click 'Select' to select files!"}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Please upgrade to i.e. Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Upload' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Upload")}else{this.modal.disableButton("Upload")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Select");this.modal.enableButton("Create")}else{this.modal.disableButton("Select");this.modal.disableButton("Create")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("table").show()}else{$(this.el).find("table").hide()}},template:function(f,e){return'<div id="'+f+'" class="upload-box"><table class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Space→Tab</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+e+'" class="upload-info"></h6>'},template_row:function(f){var e='<tr id="'+f.substr(1)+'" class="upload-item"><td><div style="position: relative;"><div id="title" class="title"></div><div id="text" class="text"><div class="text-info">You may specify a list of URLs (one per line) or paste the contents of a file.</div><textarea id="text-content" class="text-content form-control"></textarea></div></div></td><td><div id="size" class="size"></div></td>';e+='<td><select id="extension" class="extension">';for(key in this.select_extension){e+='<option value="'+this.select_extension[key][1]+'">'+this.select_extension[key][0]+"</option>"}e+="</select></td>";e+='<td><select id="genome" class="genome">';for(key in this.select_genome){e+='<option value="'+this.select_genome[key][1]+'">'+this.select_genome[key][0]+"</option>"}e+="</select></td>";e+='<td><input id="space_to_tabs" type="checkbox"></input></td><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="symbol '+this.state.init+'"></div></td></tr>';return e}});return{GalaxyUpload:a}});
\ No newline at end of file
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.attributes);a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this)},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(this.template(this.$button.attr("id"),this.options));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this;var a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"},template:function(e,b){var a='<ul id="'+e+'-menu" class="dropdown-menu">';if(b.length>0){for(var c in b){var d=b[c];if(d.divider){a+='<li class="divider"></li>'}else{if(d.header){a+='<li class="head"><a href="javascript:void(0);">'+d.html+"</a></li>"}else{if(d.href){a+='<li><a href="'+d.href+'"';a+='target="'+d.target+'"'}else{a+='<li><a href="javascript:void(0);"'}a+='class="popupmenu-option">';if(d.checked){a+='<span class="fa-icon-ok"></span>'}a+=d.html}}}}else{a+="<li>No Options.</li>"}return a+"</ul>"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.attributes);a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+e+'"'):(""),b=(d.checked)?('<span class="fa-icon-ok"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var b=this;var a=function(c){c.one("click.close_popup",function(){b.remove()})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
diff -r f888228f48d89ade8b8f49a4d777c573174392d1 -r 5c9cfd1dea8bfb85bcc1ee07035629a77ee3a051 static/scripts/packed/utils/galaxy.uploadbox.js
--- a/static/scripts/packed/utils/galaxy.uploadbox.js
+++ b/static/scripts/packed/utils/galaxy.uploadbox.js
@@ -1,1 +1,1 @@
-(function(d){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:20,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(j,k,l){alert(l)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"The server is unavailable.",error_toomany:"You can only queue <20 files per upload session."};var b={};var f={};var g=0;var i=0;var e=false;var a=false;var c=null;d.fn.uploadbox=function(z){b=d.extend({},h,z);c=this;c.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');c.on("drop",m);c.on("dragover",n);c.on("dragleave",u);d("#uploadbox_input").change(function(A){w(A.target.files);d(this).val("")});function m(A){if(!A.dataTransfer){return}w(A.dataTransfer.files);A.preventDefault();return false}function n(A){A.preventDefault();b.dragover.call(A)}function u(A){A.stopPropagation();b.dragleave.call(A)}function j(A){if(A.lengthComputable){b.progress(this.index,this.file,Math.round((A.loaded*100)/A.total))}}function w(C){if(e){return}for(var B=0;B<C.length;B++){if(i>=b.maxfilenumber){break}var A=String(g++);f[A]=C[B];b.announce(A,f[A],"");i++}}function p(A){if(f[A]){delete f[A];i--}}function k(){if(i==0||a){a=false;e=false;b.complete();return}else{e=true}var D=-1;for(var F in f){D=F;break}var E=f[D];p(D);var H=b.initialize(D,E);try{var B=new FileReader();var C=E.size;var A=1048576*b.maxfilesize;B.index=D;if(C<A){B.onload=function(I){o(D,E,H)};B.onerror=function(I){s(D,E,b.error_default)};B.onabort=function(I){s(D,E,b.error_default)};B.readAsDataURL(E)}else{s(D,E,b.error_filesize)}}catch(G){s(D,E,G)}}function o(A,C,D){var E=new FormData();for(var B in D){E.append(B,D[B])}E.append(b.paramname,C,C.name);var F=new XMLHttpRequest();F.onreadystatechange=function(){if(F.readyState!=F.DONE){return}var G=null;if(F.responseText){try{G=jQuery.parseJSON(F.responseText)}catch(H){G=F.responseText}}if(F.status<200||F.status>299){var I=F.statusText;if(!F.statusText){if(F.status==0){I=b.error_server}else{I=b.error_default}}s(A,C,I+" ("+F.status+")")}else{v(A,C,G)}};F.upload.index=A;F.upload.file=C;F.upload.addEventListener("progress",j,false);F.open("POST",b.url,true);F.setRequestHeader("Accept","application/json");F.setRequestHeader("Cache-Control","no-cache");F.setRequestHeader("X-Requested-With","XMLHttpRequest");F.send(E)}function v(A,B,C){b.success(A,B,C);k()}function s(A,B,C){b.error(A,B,C);k()}function t(){d("#uploadbox_input").trigger("click")}function r(A){for(A in f){p(A)}}function y(){if(!e){e=true;k()}}function x(){a=true}function l(A){b=d.extend({},b,A);return b}function q(){return window.File&&window.FileReader&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:t,remove:p,upload:y,pause:x,reset:r,configure:l,compatible:q}}})(jQuery);
\ No newline at end of file
+(function(c){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:20,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(k,l,m){alert(m)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_toomany:"You can only queue <20 files per upload session.",error_login:"Uploads require you to log in.",error_missing:"No upload content available."};var a={};var e={};var f=0;var j=0;var d=false;var g=false;var b=null;var i=null;c.fn.uploadbox=function(A){a=c.extend({},h,A);b=this;b.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');b.on("drop",o);b.on("dragover",p);b.on("dragleave",x);c("#uploadbox_input").change(function(B){z(B.target.files);c(this).val("")});function o(B){if(!B.dataTransfer){return}z(B.dataTransfer.files);B.preventDefault();return false}function p(B){B.preventDefault();a.dragover.call(B)}function x(B){B.stopPropagation();a.dragleave.call(B)}function k(B){if(B.lengthComputable){a.progress(this.index,this.file,Math.round((B.loaded*100)/B.total))}}function z(D){if(d){return}for(var C=0;C<D.length;C++){if(j>=a.maxfilenumber){break}var B=String(f++);e[B]=D[C];a.announce(B,e[B],"");j++}}function r(B){if(e[B]){delete e[B];j--}}function m(){if(j==0||g){g=false;d=false;a.complete();return}else{d=true}var D=-1;for(var F in e){D=F;break}var E=e[D];r(D);var C=E.size;var B=1048576*a.maxfilesize;if(C<B){var G=a.initialize(D,E);if(G){q(D,E,G)}else{u(D,E,a.error_missing)}}else{u(D,E,a.error_filesize)}}function q(B,D,E){var F=new FormData();for(var C in E){F.append(C,E[C])}if(D.size>0){F.append(a.paramname,D,D.name)}i=new XMLHttpRequest();i.open("POST",a.url,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onreadystatechange=function(){if(i.readyState!=i.DONE){return}var G=null;if(i.responseText){try{G=jQuery.parseJSON(i.responseText)}catch(H){G=i.responseText}}if(i.status<200||i.status>299){var I=i.statusText;if(i.status==403){I=a.error_login}else{if(i.status==0){I=a.error_server}else{if(!I){I=a.error_default}}}u(B,D,I+" ("+i.status+")")}else{y(B,D,G)}};i.upload.index=B;i.upload.file=D;i.upload.addEventListener("progress",k,false);i.send(F)}function y(B,C,D){a.success(B,C,D);m()}function u(B,C,D){a.error(B,C,D);m()}function w(){c("#uploadbox_input").trigger("click")}function t(B){for(B in e){r(B)}}function l(){if(!d){d=true;m()}}function v(){g=true}function n(B){a=c.extend({},a,B);return a}function s(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:w,add:z,remove:r,start:l,stop:v,reset:t,configure:n,compatible:s}}})(jQuery);
\ 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
6 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d816d6602e18/
Changeset: d816d6602e18
Branch: custom-toolbox2
User: BjoernGruening
Date: 2013-06-13 22:46:22
Summary: Implement the ability to change the tool-panel as user prederence.
Affected #: 10 files
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -6,8 +6,9 @@
import logging, logging.config
import ConfigParser
from datetime import timedelta
-from galaxy.util import string_as_bool, listify, parse_xml
-
+from galaxy.util import string_as_bool
+from galaxy.util import listify
+from galaxy.util import parse_xml
from galaxy import eggs
import pkg_resources
@@ -64,9 +65,14 @@
tcf = kwargs[ 'tool_config_files' ]
else:
tcf = 'tool_conf.xml'
- self.tool_filters = listify( kwargs.get( "tool_filters", [] ) )
- self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ) )
- self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ) )
+ self.tool_filters = listify( kwargs.get( "tool_filters", [] ), do_strip=True )
+ self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ), do_strip=True )
+ self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ), do_strip=True )
+
+ self.user_tool_filters = listify( kwargs.get( "user_tool_filters", [] ), do_strip=True )
+ self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True )
+ self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True )
+
self.tool_configs = [ resolve_path( p, self.root ) for p in listify( tcf ) ]
self.shed_tool_data_path = kwargs.get( "shed_tool_data_path", None )
if self.shed_tool_data_path:
@@ -459,3 +465,4 @@
sentry_handler = SentryHandler( config.sentry_dsn )
sentry_handler.setLevel( logging.WARN )
root.addHandler( sentry_handler )
+
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3267,7 +3267,7 @@
#end of Data Manager Classes
class UserPreference ( object ):
- def __init__( self, name=None, value=None ):
+ def __init__( self, name=None, value=None):
self.name = name
self.value = value
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -3426,3 +3426,4 @@
class InterruptedUpload( Exception ):
pass
+
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -1,4 +1,5 @@
-
+from galaxy.util import listify
+from copy import deepcopy
class FilterFactory( object ):
"""
@@ -15,17 +16,29 @@
self.default_filters = dict( tool=[ _not_hidden ], section=[], label=[] )
# Add dynamic filters to these default filters.
config = toolbox.app.config
- self.__init_filters( "tool", config.tool_filters )
- self.__init_filters( "section", config.tool_section_filters )
- self.__init_filters( "label", config.tool_label_filters )
+ self.__init_filters( "tool", config.tool_filters, self.default_filters )
+ self.__init_filters( "section", config.tool_section_filters, self.default_filters )
+ self.__init_filters( "label", config.tool_label_filters, self.default_filters )
def build_filters( self, trans, **kwds ):
"""
Build list of filters to check tools against given current context.
"""
- filters = self.default_filters.copy()
-
- if not trans.user:
+ filters = deepcopy( self.default_filters )
+ if trans.user:
+ for name, value in trans.user.preferences.items():
+ if value.strip():
+ user_filters = listify( value, do_strip=True )
+ category = ''
+ if name == 'toolbox_tool_filters':
+ category = "tool"
+ elif name == 'toolbox_section_filters':
+ category = "section"
+ elif name == 'toolbox_label_filters':
+ category = "label"
+ if category:
+ self.__init_filters( category, user_filters, filters )
+ else:
filters[ "tool" ].append( _requires_login )
if kwds.get( "trackster", False ):
@@ -33,10 +46,11 @@
return filters
- def __init_filters( self, key, filters ):
+ def __init_filters( self, key, filters, toolbox_filters ):
for filter in filters:
filter_function = self.__build_filter_function( filter )
- self.default_filters[ key ].append( filter_function )
+ toolbox_filters[ key ].append( filter_function )
+ return toolbox_filters
def __build_filter_function( self, filter_name ):
"""Obtain python function (importing a submodule if needed)
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/filters/examples.py
--- /dev/null
+++ b/lib/galaxy/tools/filters/examples.py
@@ -0,0 +1,115 @@
+import logging
+log = logging.getLogger( __name__ )
+
+
+def restrict_encode( content, tool ):
+ """
+ Disable the random interval ENCODE tool
+
+ This tool filter will disable all the ENCODE tool when enabled.
+ """
+ if tool.id == 'random_intervals1':
+ return False
+ return True
+
+
+def restrict_text( content, section ):
+ """
+ Disable Text sections
+
+ This tool filter will disable all Tools groups under a 'Text' section when enabled.
+ """
+ if section.name.find('Text') != -1:
+ return False
+ return True
+
+
+def restrict_upload_to_admins( context, tool ):
+ """
+ Disable Upload tool for all non-admin users.
+
+ This tool filter will hide the upload tool from all users except admin
+ users.
+
+ This can be enabled by renaming this file to examples.py and adding
+ the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:restrict_upload_to_admins
+ """
+ if tool.name == "Upload File":
+ return context.trans.user_is_admin()
+ return True
+
+
+def disable_gatk( context, tool ):
+ """
+ This tool filter will disable all gatk tools when enabled.
+
+ This can be enabled by renaming this file to examples.py and adding the following to the
+ ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:disable_gatk
+ """
+ return not any( [ requirement.name == "gatk" for requirement in tool.requirements ] )
+
+
+def explicit_user_mapping( context, section ):
+ """
+ This tool section filter uses an explicit mapping to describe what users can view
+ which tool sections. Anonymous users will only be able to view the "Get Data"
+ tool section (with id getext). This can be enabled by renaming this file to
+ examples.py and adding the following to the ``app:main`` section of
+ ``universe_wsgi.ini``:
+
+ tool_section_filters = examples:explicit_user_mapping
+ """
+ users_sections = {
+ None: [ "getext" ],
+ "bob(a)example.com": [ "getext", "textutil", "filter" ],
+ "mary(a)example.com": [ "getext", "textutil", "filter", "ngs" ],
+ }
+ user = context.trans.user
+ email = user and user.email
+ valid_sections = users_sections.get( email, [] )
+ return section.id in valid_sections
+
+
+DEVELOPERS = [ "mary(a)example.com" ]
+
+
+def restrict_development_tools( context, tool ):
+ """
+ This tool filter will disable all tools with the string alpha appearing in
+ the version for all users except those explicitly appearing in the DEVELOPERS list
+ defined above. This can be enabled by renaming this file to examples.py and
+ adding the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:restrict_development_tools
+ """
+ version = tool.version
+ user = context.trans.user
+ email = user and user.email
+ return "alpha" not in version or email in DEVELOPERS
+
+
+def per_host_tool_sections( context, section ):
+ """
+ This tool section filter results in different sections being display based on
+ the URL the user is making the request to. This could allow a single Galaxy instance
+ to seem like several different instances hosting different tools based on the URL used
+ to access the Galxy. This can be enabled by renaming this file to examples.py and adding
+ the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_section_filters = examples:per_host_tool_sections
+ """
+ host = context.trans.request.host
+ # Core tools used by all virtual hosts.
+ valid_sections = [ "getext", "textutil", "filter" ]
+ if "ngs.galaxy.example.com" in host:
+ valid_sections += [ "ngs" ]
+ elif "microarray.galaxy.example.com" in host:
+ valid_sections += [ "microarray" ]
+ elif "proteomics.galaxy.example.com" in host:
+ valid_sections += [ "proteomics" ]
+ return section.id in valid_sections
+
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -496,7 +496,7 @@
else:
return False
-def listify( item ):
+def listify( item, do_strip=False ):
"""
Make a single item a single item list, or return a list if passed a
list. Passing a None returns an empty list.
@@ -506,7 +506,10 @@
elif isinstance( item, list ):
return item
elif isinstance( item, basestring ) and item.count( ',' ):
- return item.split( ',' )
+ if do_strip:
+ return [token.strip() for token in item.split( ',' )]
+ else:
+ return item.split( ',' )
else:
return [ item ]
@@ -746,6 +749,32 @@
current_group,
e ) )
+def docstring_trim(docstring):
+ """Trimming python doc strings. Taken from: http://www.python.org/dev/peps/pep-0257/"""
+ if not docstring:
+ return ''
+ # Convert tabs to spaces (following the normal Python rules)
+ # and split into a list of lines:
+ lines = docstring.expandtabs().splitlines()
+ # Determine minimum indentation (first line doesn't count):
+ indent = sys.maxint
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ # Remove indentation (first line is special):
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxint:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ # Strip off trailing and leading blank lines:
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ # Return a single string:
+ return '\n'.join(trimmed)
+
def nice_size(size):
"""
Returns a readably formatted string with the size
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -9,14 +9,24 @@
import string
import random
from galaxy import web
-from galaxy import util, model
+from galaxy import util
+from galaxy import model
from galaxy.model.orm import and_
-from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.security.validate_user_input import validate_email
+from galaxy.security.validate_user_input import validate_publicname
+from galaxy.security.validate_user_input import validate_password
+from galaxy.security.validate_user_input import transform_publicname
+from galaxy.util.json import from_json_string
+from galaxy.util.json import to_json_string
+from galaxy.util import listify
+from galaxy.util import docstring_trim
from galaxy.web import url_for
-from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin
-from galaxy.web.form_builder import CheckboxField, build_select_field
+from galaxy.web.base.controller import BaseUIController
+from galaxy.web.base.controller import UsesFormDefinitionsMixin
+from galaxy.web.form_builder import CheckboxField
+from galaxy.web.form_builder import build_select_field
from galaxy.web.framework.helpers import time_ago, grids
+from galaxy.web.framework.helpers import grids
log = logging.getLogger( __name__ )
@@ -101,6 +111,7 @@
use_panels=use_panels,
message=message,
status='error' ) )
+
@web.expose
def openid_process( self, trans, **kwd ):
'''Handle's response from OpenID Providers'''
@@ -221,6 +232,7 @@
redirect=redirect,
message=message,
status=status ) )
+
@web.expose
def openid_associate( self, trans, cntrller='user', **kwd ):
'''Associates a user with an OpenID log in'''
@@ -359,6 +371,7 @@
user_type_form_definition=user_type_form_definition,
widgets=widgets,
openids=openids )
+
@web.expose
@web.require_login( 'manage OpenIDs' )
def openid_disassociate( self, trans, **kwd ):
@@ -465,6 +478,7 @@
openid_providers=trans.app.openid_providers,
form_input_auto_focus=True,
active_view="user" )
+
def __validate_login( self, trans, **kwd ):
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
@@ -662,6 +676,7 @@
message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
success = True
return ( message, status, user, success )
+
def __get_user_type_form_definition( self, trans, user=None, **kwd ):
params = util.Params( kwd )
if user and user.values:
@@ -673,6 +688,7 @@
else:
user_type_form_definition = None
return user_type_form_definition
+
def __get_widgets( self, trans, user_type_form_definition, user=None, **kwd ):
widgets = []
if user_type_form_definition:
@@ -774,6 +790,7 @@
username=user.username,
message=message,
status=status )
+
@web.expose
def edit_info( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -882,6 +899,7 @@
action='manage_user_info',
cntrller=cntrller,
**kwd ) )
+
@web.expose
def reset_password( self, trans, email=None, **kwd ):
if trans.app.config.smtp_server is None:
@@ -929,6 +947,7 @@
return trans.fill_template( '/user/reset_password.mako',
message=message,
status=status )
+
def __validate( self, trans, params, email, password, confirm, username ):
# If coming from the tool shed webapp, we'll require a public user name
if trans.webapp.name == 'tool_shed':
@@ -950,6 +969,7 @@
if user_type_fd_id in [ 'none' ]:
return "Select the user's type and information"
return message
+
@web.expose
def set_default_permissions( self, trans, cntrller, **kwd ):
"""Sets the user's default permissions for the new histories"""
@@ -975,7 +995,128 @@
status=status )
else:
# User not logged in, history group must be only public
- return trans.show_error_message( "You must be logged in to change your default permitted actions." )
+ return trans.show_error_message( "You must be logged in to change your default permitted actions." )
+
+ @web.expose
+ @web.require_login()
+ def toolbox_filters( self, trans, cntrller, **kwd ):
+ """
+ Sets the user's default filters for the toolbox.
+ Toolbox filters are specified in universe_wsgi.ini.
+ The user can activate them and the choice is stored in user_preferences.
+ """
+
+ def get_filter_mapping( db_filters, config_filters ):
+ """
+ Compare the allowed filters from the universe_wsgi.ini config file with the previously saved or default filters from the database.
+ We need that to toogle the checkboxes for the formular in the right way.
+ Furthermore we extract all information associated to a filter to display them in the formular.
+ """
+ filters = list()
+ for filter_name in config_filters:
+ if ":" in filter_name:
+ # Should be a submodule of filters (e.g. examples:restrict_development_tools)
+ (module_name, function_name) = filter_name.rsplit(":", 1)
+ module_name = 'galaxy.tools.filters.%s' % module_name.strip()
+ module = __import__( module_name, globals(), fromlist=['temp_module'] )
+ function = getattr( module, function_name.strip() )
+ else:
+ # No module found it has to be explicitly imported.
+ module = __import__( 'galaxy.tools.filters', globals(), fromlist=['temp_module'] )
+ function = getattr( globals(), filter_name.strip() )
+
+ doc_string = docstring_trim( function.__doc__ )
+ split = doc_string.split('\n\n')
+ if split:
+ sdesc = split[0]
+ else:
+ log.error( 'No description specified in the __doc__ string for %s.' % filter_name )
+ if len(split) > 1:
+ description = split[1]
+ else:
+ description = ''
+
+ if filter_name in db_filters:
+ filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=True ) )
+ else:
+ filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=False ) )
+ return filters
+
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+
+ user_id = params.get( 'user_id', False )
+ if user_id:
+ user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
+ else:
+ user = trans.user
+
+ if user:
+ saved_user_tool_filters = list()
+ saved_user_section_filters = list()
+ saved_user_label_filters = list()
+
+ for name, value in user.preferences.items():
+ if name == 'toolbox_tool_filters':
+ saved_user_tool_filters = listify( value, do_strip=True )
+ elif name == 'toolbox_section_filters':
+ saved_user_section_filters = listify( value, do_strip=True )
+ elif name == 'toolbox_label_filters':
+ saved_user_label_filters = listify( value, do_strip=True )
+
+ tool_filters = get_filter_mapping( saved_user_tool_filters, trans.app.config.user_tool_filters )
+ section_filters = get_filter_mapping( saved_user_section_filters, trans.app.config.user_section_filters )
+ label_filters = get_filter_mapping( saved_user_label_filters, trans.app.config.user_label_filters )
+
+ return trans.fill_template( 'user/toolbox_filters.mako',
+ cntrller=cntrller,
+ message=message,
+ tool_filters=tool_filters,
+ section_filters=section_filters,
+ label_filters=label_filters,
+ user=user,
+ status=status )
+ else:
+ # User not logged in, history group must be only public
+ return trans.show_error_message( "You must be logged in to change private toolbox filters." )
+
+ @web.expose
+ @web.require_login( "to change the private toolbox filters" )
+ def edit_toolbox_filters( self, trans, cntrller, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ user_id = params.get( 'user_id', False )
+ if not user_id:
+ # User must be logged in to create a new address
+ return trans.show_error_message( "You must be logged in to change the ToolBox filters." )
+
+ user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
+
+ if params.get( 'edit_toolbox_filter_button', False ):
+ tool_filters = list()
+ section_filters = list()
+ label_filters = list()
+ for name, state in params.flatten():
+ if state == 'on':
+ if name.startswith('t_'):
+ tool_filters.append( name[2:] )
+ elif name.startswith('l_'):
+ label_filters.append( name[2:] )
+ elif name.startswith('s_'):
+ section_filters.append( name[2:] )
+ user.preferences['toolbox_tool_filters'] = ','.join( tool_filters )
+ user.preferences['toolbox_section_filters'] = ','.join( section_filters )
+ user.preferences['toolbox_label_filters'] = ','.join( label_filters )
+
+ trans.sa_session.add( user )
+ trans.sa_session.flush()
+ message = 'ToolBox filters has been updated.'
+ kwd = dict( message=message, status='done' )
+
+ # Display the ToolBox filters form with the current values filled in
+ return self.toolbox_filters( trans, cntrller, **kwd )
+
@web.expose
@web.require_login( "to get most recently used tool" )
@web.json_pretty
@@ -998,7 +1139,8 @@
"minsizehint" : tool.uihints.get( 'minwidth', -1 ),
"description" : tool.description
}
- return tool_info
+ return tool_info
+
@web.expose
def manage_addresses(self, trans, **kwd):
if trans.user:
@@ -1020,6 +1162,7 @@
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change your default permitted actions." )
+
@web.expose
def new_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -1104,6 +1247,7 @@
phone=phone,
message=message,
status=status )
+
@web.expose
def edit_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -1118,7 +1262,7 @@
address_id = params.get( 'address_id', None )
if not address_id:
return trans.show_error_message( "No address id received for editing." )
- address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
+ address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
if params.get( 'edit_address_button', False ):
short_desc = util.restore_text( params.get( 'short_desc', '' ) )
name = util.restore_text( params.get( 'name', '' ) )
@@ -1181,6 +1325,7 @@
address_obj=address_obj,
message=message,
status=status )
+
@web.expose
def delete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
@@ -1201,6 +1346,7 @@
user_id=user_id,
message=message,
status=status ) )
+
@web.expose
def undelete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
@@ -1220,6 +1366,7 @@
user_id=user_id,
message=message,
status=status ) )
+
@web.expose
def set_user_pref_async( self, trans, pref_name, pref_value ):
""" Set a user preference asynchronously. If user is not logged in, do nothing. """
@@ -1232,7 +1379,7 @@
""" Log a user action asynchronously. If user is not logged in, do nothing. """
if trans.user:
trans.log_action( trans.get_user(), action, context, params )
-
+
@web.expose
@web.require_login()
def dbkeys( self, trans, **kwds ):
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf templates/user/index.mako
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -13,6 +13,7 @@
<li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li><li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li>
+ <li><a href="${h.url_for( controller='user', action='toolbox_filters', cntrller=cntrller )}">${_('Manage your ToolBox filters')}</a></li>
%if trans.app.config.enable_openid:
<li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li>
%endif
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf templates/user/toolbox_filters.mako
--- /dev/null
+++ b/templates/user/toolbox_filters.mako
@@ -0,0 +1,91 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+</br>
+</br>
+
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a>
+ </li>
+</ul>
+
+%if tool_filters or section_filters or label_filters:
+ <div class="toolForm">
+ <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
+ % if tool_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Tools</div>
+ <div class="toolFormBody">
+ % for filter in tool_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="t_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="t_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+
+ % if section_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Sections</div>
+ <div class="toolFormBody">
+ % for filter in section_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="s_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="s_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+
+ % if label_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Labels</div>
+ <div class="toolFormBody">
+ % for filter in label_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="l_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="l_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+ <div class="form-row">
+ <input type="submit" name="edit_toolbox_filter_button" value="Save changes">
+ </div>
+ </form>
+ </div>
+%else:
+ ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )}
+%endif
diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -682,6 +682,18 @@
# if running many handlers.
#cache_user_job_count = False
+# ToolBox filtering
+# Modules from lib/galaxy/tools/filters/ can be specified in the following lines.
+# tool_* filters will be applied for all users and can not be changed by them.
+# user_tool_* filters will be shown under user preferences and can be toogled
+# on and off by runtime
+#tool_filters
+#tool_label_filters
+#tool_section_filters
+#user_tool_filters = examples:restrict_upload_to_admins, examples:restrict_encode
+#user_tool_section_filters = examples:restrict_text
+#user_tool_label_filters = examples:restrict_upload_to_admins, examples:restrict_encode
+
# ---- Galaxy Message Queue -------------------------------------------------
# Galaxy uses AMQ protocol to receive messages from external sources like
https://bitbucket.org/galaxy/galaxy-central/commits/fb1b676f51b2/
Changeset: fb1b676f51b2
User: dannon
Date: 2013-10-17 19:40:04
Summary: Merged custom-toolbox2
Affected #: 10 files
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -6,8 +6,9 @@
import logging, logging.config
import ConfigParser
from datetime import timedelta
-from galaxy.util import string_as_bool, listify, parse_xml
-
+from galaxy.util import string_as_bool
+from galaxy.util import listify
+from galaxy.util import parse_xml
from galaxy import eggs
import pkg_resources
@@ -64,9 +65,14 @@
tcf = kwargs[ 'tool_config_files' ]
else:
tcf = 'tool_conf.xml,shed_tool_conf.xml'
- self.tool_filters = listify( kwargs.get( "tool_filters", [] ) )
- self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ) )
- self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ) )
+ self.tool_filters = listify( kwargs.get( "tool_filters", [] ), do_strip=True )
+ self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ), do_strip=True )
+ self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ), do_strip=True )
+
+ self.user_tool_filters = listify( kwargs.get( "user_tool_filters", [] ), do_strip=True )
+ self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True )
+ self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True )
+
self.tool_configs = [ resolve_path( p, self.root ) for p in listify( tcf ) ]
self.shed_tool_data_path = kwargs.get( "shed_tool_data_path", None )
if self.shed_tool_data_path:
@@ -489,3 +495,4 @@
sentry_handler = SentryHandler( config.sentry_dsn )
sentry_handler.setLevel( logging.WARN )
root.addHandler( sentry_handler )
+
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3359,7 +3359,7 @@
#end of Data Manager Classes
class UserPreference ( object ):
- def __init__( self, name=None, value=None ):
+ def __init__( self, name=None, value=None):
self.name = name
self.value = value
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -3433,3 +3433,4 @@
class InterruptedUpload( Exception ):
pass
+
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -1,4 +1,5 @@
-
+from galaxy.util import listify
+from copy import deepcopy
class FilterFactory( object ):
"""
@@ -15,25 +16,39 @@
self.default_filters = dict( tool=[ _not_hidden, _handle_requires_login ], section=[], label=[] )
# Add dynamic filters to these default filters.
config = toolbox.app.config
- self.__init_filters( "tool", config.tool_filters )
- self.__init_filters( "section", config.tool_section_filters )
- self.__init_filters( "label", config.tool_label_filters )
+ self.__init_filters( "tool", config.tool_filters, self.default_filters )
+ self.__init_filters( "section", config.tool_section_filters, self.default_filters )
+ self.__init_filters( "label", config.tool_label_filters, self.default_filters )
def build_filters( self, trans, **kwds ):
"""
Build list of filters to check tools against given current context.
"""
- filters = self.default_filters.copy()
-
+ filters = deepcopy( self.default_filters )
+ if trans.user:
+ for name, value in trans.user.preferences.items():
+ if value.strip():
+ user_filters = listify( value, do_strip=True )
+ category = ''
+ if name == 'toolbox_tool_filters':
+ category = "tool"
+ elif name == 'toolbox_section_filters':
+ category = "section"
+ elif name == 'toolbox_label_filters':
+ category = "label"
+ if category:
+ self.__init_filters( category, user_filters, filters )
+ else:
if kwds.get( "trackster", False ):
filters[ "tool" ].append( _has_trackster_conf )
return filters
- def __init_filters( self, key, filters ):
+ def __init_filters( self, key, filters, toolbox_filters ):
for filter in filters:
filter_function = self.__build_filter_function( filter )
- self.default_filters[ key ].append( filter_function )
+ toolbox_filters[ key ].append( filter_function )
+ return toolbox_filters
def __build_filter_function( self, filter_name ):
"""Obtain python function (importing a submodule if needed)
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/filters/examples.py
--- /dev/null
+++ b/lib/galaxy/tools/filters/examples.py
@@ -0,0 +1,115 @@
+import logging
+log = logging.getLogger( __name__ )
+
+
+def restrict_encode( content, tool ):
+ """
+ Disable the random interval ENCODE tool
+
+ This tool filter will disable all the ENCODE tool when enabled.
+ """
+ if tool.id == 'random_intervals1':
+ return False
+ return True
+
+
+def restrict_text( content, section ):
+ """
+ Disable Text sections
+
+ This tool filter will disable all Tools groups under a 'Text' section when enabled.
+ """
+ if section.name.find('Text') != -1:
+ return False
+ return True
+
+
+def restrict_upload_to_admins( context, tool ):
+ """
+ Disable Upload tool for all non-admin users.
+
+ This tool filter will hide the upload tool from all users except admin
+ users.
+
+ This can be enabled by renaming this file to examples.py and adding
+ the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:restrict_upload_to_admins
+ """
+ if tool.name == "Upload File":
+ return context.trans.user_is_admin()
+ return True
+
+
+def disable_gatk( context, tool ):
+ """
+ This tool filter will disable all gatk tools when enabled.
+
+ This can be enabled by renaming this file to examples.py and adding the following to the
+ ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:disable_gatk
+ """
+ return not any( [ requirement.name == "gatk" for requirement in tool.requirements ] )
+
+
+def explicit_user_mapping( context, section ):
+ """
+ This tool section filter uses an explicit mapping to describe what users can view
+ which tool sections. Anonymous users will only be able to view the "Get Data"
+ tool section (with id getext). This can be enabled by renaming this file to
+ examples.py and adding the following to the ``app:main`` section of
+ ``universe_wsgi.ini``:
+
+ tool_section_filters = examples:explicit_user_mapping
+ """
+ users_sections = {
+ None: [ "getext" ],
+ "bob(a)example.com": [ "getext", "textutil", "filter" ],
+ "mary(a)example.com": [ "getext", "textutil", "filter", "ngs" ],
+ }
+ user = context.trans.user
+ email = user and user.email
+ valid_sections = users_sections.get( email, [] )
+ return section.id in valid_sections
+
+
+DEVELOPERS = [ "mary(a)example.com" ]
+
+
+def restrict_development_tools( context, tool ):
+ """
+ This tool filter will disable all tools with the string alpha appearing in
+ the version for all users except those explicitly appearing in the DEVELOPERS list
+ defined above. This can be enabled by renaming this file to examples.py and
+ adding the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_filters = examples:restrict_development_tools
+ """
+ version = tool.version
+ user = context.trans.user
+ email = user and user.email
+ return "alpha" not in version or email in DEVELOPERS
+
+
+def per_host_tool_sections( context, section ):
+ """
+ This tool section filter results in different sections being display based on
+ the URL the user is making the request to. This could allow a single Galaxy instance
+ to seem like several different instances hosting different tools based on the URL used
+ to access the Galxy. This can be enabled by renaming this file to examples.py and adding
+ the following to the ``app:main`` section of ``universe_wsgi.ini``:
+
+ tool_section_filters = examples:per_host_tool_sections
+ """
+ host = context.trans.request.host
+ # Core tools used by all virtual hosts.
+ valid_sections = [ "getext", "textutil", "filter" ]
+ if "ngs.galaxy.example.com" in host:
+ valid_sections += [ "ngs" ]
+ elif "microarray.galaxy.example.com" in host:
+ valid_sections += [ "microarray" ]
+ elif "proteomics.galaxy.example.com" in host:
+ valid_sections += [ "proteomics" ]
+ return section.id in valid_sections
+
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -504,7 +504,7 @@
else:
return False
-def listify( item ):
+def listify( item, do_strip=False ):
"""
Make a single item a single item list, or return a list if passed a
list. Passing a None returns an empty list.
@@ -514,7 +514,10 @@
elif isinstance( item, list ):
return item
elif isinstance( item, basestring ) and item.count( ',' ):
- return item.split( ',' )
+ if do_strip:
+ return [token.strip() for token in item.split( ',' )]
+ else:
+ return item.split( ',' )
else:
return [ item ]
@@ -778,6 +781,32 @@
current_group,
e ) )
+def docstring_trim(docstring):
+ """Trimming python doc strings. Taken from: http://www.python.org/dev/peps/pep-0257/"""
+ if not docstring:
+ return ''
+ # Convert tabs to spaces (following the normal Python rules)
+ # and split into a list of lines:
+ lines = docstring.expandtabs().splitlines()
+ # Determine minimum indentation (first line doesn't count):
+ indent = sys.maxint
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ # Remove indentation (first line is special):
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxint:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ # Strip off trailing and leading blank lines:
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ # Return a single string:
+ return '\n'.join(trimmed)
+
def nice_size(size):
"""
Returns a readably formatted string with the size
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -10,15 +10,25 @@
import random
import urllib
from galaxy import web
-from galaxy import util, model
+from galaxy import util
+from galaxy import model
from galaxy.model.orm import and_
-from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.security.validate_user_input import validate_email
+from galaxy.security.validate_user_input import validate_publicname
+from galaxy.security.validate_user_input import validate_password
+from galaxy.security.validate_user_input import transform_publicname
+from galaxy.util.json import from_json_string
+from galaxy.util.json import to_json_string
+from galaxy.util import listify
+from galaxy.util import docstring_trim
from galaxy.web import url_for
-from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin
-from galaxy.web.form_builder import CheckboxField, build_select_field
+from galaxy.web.base.controller import BaseUIController
+from galaxy.web.base.controller import UsesFormDefinitionsMixin
+from galaxy.web.form_builder import CheckboxField
+from galaxy.web.form_builder import build_select_field
from galaxy.web.framework.helpers import time_ago, grids
from datetime import datetime, timedelta
+from galaxy.web.framework.helpers import grids
from galaxy.util import hash_util
log = logging.getLogger( __name__ )
@@ -104,6 +114,7 @@
use_panels=use_panels,
message=message,
status='error' ) )
+
@web.expose
def openid_process( self, trans, **kwd ):
'''Handle's response from OpenID Providers'''
@@ -231,6 +242,7 @@
redirect=redirect,
message=message,
status=status ) )
+
@web.expose
def openid_associate( self, trans, cntrller='user', **kwd ):
'''Associates a user with an OpenID log in'''
@@ -369,6 +381,7 @@
user_type_form_definition=user_type_form_definition,
widgets=widgets,
openids=openids )
+
@web.expose
@web.require_login( 'manage OpenIDs' )
def openid_disassociate( self, trans, **kwd ):
@@ -849,6 +862,7 @@
else:
user_type_form_definition = None
return user_type_form_definition
+
def __get_widgets( self, trans, user_type_form_definition, user=None, **kwd ):
widgets = []
if user_type_form_definition:
@@ -950,6 +964,7 @@
username=user.username,
message=message,
status=status )
+
@web.expose
def edit_info( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -1058,6 +1073,7 @@
action='manage_user_info',
cntrller=cntrller,
**kwd ) )
+
@web.expose
def reset_password( self, trans, email=None, **kwd ):
if trans.app.config.smtp_server is None:
@@ -1105,6 +1121,7 @@
return trans.fill_template( '/user/reset_password.mako',
message=message,
status=status )
+
def __validate( self, trans, params, email, password, confirm, username ):
# If coming from the tool shed webapp, we'll require a public user name
if trans.webapp.name == 'tool_shed':
@@ -1126,6 +1143,7 @@
if user_type_fd_id in [ 'none' ]:
return "Select the user's type and information"
return message
+
@web.expose
def set_default_permissions( self, trans, cntrller, **kwd ):
"""Sets the user's default permissions for the new histories"""
@@ -1152,6 +1170,127 @@
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change your default permitted actions." )
+
+ @web.expose
+ @web.require_login()
+ def toolbox_filters( self, trans, cntrller, **kwd ):
+ """
+ Sets the user's default filters for the toolbox.
+ Toolbox filters are specified in universe_wsgi.ini.
+ The user can activate them and the choice is stored in user_preferences.
+ """
+
+ def get_filter_mapping( db_filters, config_filters ):
+ """
+ Compare the allowed filters from the universe_wsgi.ini config file with the previously saved or default filters from the database.
+ We need that to toogle the checkboxes for the formular in the right way.
+ Furthermore we extract all information associated to a filter to display them in the formular.
+ """
+ filters = list()
+ for filter_name in config_filters:
+ if ":" in filter_name:
+ # Should be a submodule of filters (e.g. examples:restrict_development_tools)
+ (module_name, function_name) = filter_name.rsplit(":", 1)
+ module_name = 'galaxy.tools.filters.%s' % module_name.strip()
+ module = __import__( module_name, globals(), fromlist=['temp_module'] )
+ function = getattr( module, function_name.strip() )
+ else:
+ # No module found it has to be explicitly imported.
+ module = __import__( 'galaxy.tools.filters', globals(), fromlist=['temp_module'] )
+ function = getattr( globals(), filter_name.strip() )
+
+ doc_string = docstring_trim( function.__doc__ )
+ split = doc_string.split('\n\n')
+ if split:
+ sdesc = split[0]
+ else:
+ log.error( 'No description specified in the __doc__ string for %s.' % filter_name )
+ if len(split) > 1:
+ description = split[1]
+ else:
+ description = ''
+
+ if filter_name in db_filters:
+ filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=True ) )
+ else:
+ filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=False ) )
+ return filters
+
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+
+ user_id = params.get( 'user_id', False )
+ if user_id:
+ user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
+ else:
+ user = trans.user
+
+ if user:
+ saved_user_tool_filters = list()
+ saved_user_section_filters = list()
+ saved_user_label_filters = list()
+
+ for name, value in user.preferences.items():
+ if name == 'toolbox_tool_filters':
+ saved_user_tool_filters = listify( value, do_strip=True )
+ elif name == 'toolbox_section_filters':
+ saved_user_section_filters = listify( value, do_strip=True )
+ elif name == 'toolbox_label_filters':
+ saved_user_label_filters = listify( value, do_strip=True )
+
+ tool_filters = get_filter_mapping( saved_user_tool_filters, trans.app.config.user_tool_filters )
+ section_filters = get_filter_mapping( saved_user_section_filters, trans.app.config.user_section_filters )
+ label_filters = get_filter_mapping( saved_user_label_filters, trans.app.config.user_label_filters )
+
+ return trans.fill_template( 'user/toolbox_filters.mako',
+ cntrller=cntrller,
+ message=message,
+ tool_filters=tool_filters,
+ section_filters=section_filters,
+ label_filters=label_filters,
+ user=user,
+ status=status )
+ else:
+ # User not logged in, history group must be only public
+ return trans.show_error_message( "You must be logged in to change private toolbox filters." )
+
+ @web.expose
+ @web.require_login( "to change the private toolbox filters" )
+ def edit_toolbox_filters( self, trans, cntrller, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ user_id = params.get( 'user_id', False )
+ if not user_id:
+ # User must be logged in to create a new address
+ return trans.show_error_message( "You must be logged in to change the ToolBox filters." )
+
+ user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
+
+ if params.get( 'edit_toolbox_filter_button', False ):
+ tool_filters = list()
+ section_filters = list()
+ label_filters = list()
+ for name, state in params.flatten():
+ if state == 'on':
+ if name.startswith('t_'):
+ tool_filters.append( name[2:] )
+ elif name.startswith('l_'):
+ label_filters.append( name[2:] )
+ elif name.startswith('s_'):
+ section_filters.append( name[2:] )
+ user.preferences['toolbox_tool_filters'] = ','.join( tool_filters )
+ user.preferences['toolbox_section_filters'] = ','.join( section_filters )
+ user.preferences['toolbox_label_filters'] = ','.join( label_filters )
+
+ trans.sa_session.add( user )
+ trans.sa_session.flush()
+ message = 'ToolBox filters has been updated.'
+ kwd = dict( message=message, status='done' )
+
+ # Display the ToolBox filters form with the current values filled in
+ return self.toolbox_filters( trans, cntrller, **kwd )
+
@web.expose
@web.require_login( "to get most recently used tool" )
@web.json_pretty
@@ -1175,6 +1314,7 @@
"description" : tool.description
}
return tool_info
+
@web.expose
def manage_addresses(self, trans, **kwd):
if trans.user:
@@ -1196,6 +1336,7 @@
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change your default permitted actions." )
+
@web.expose
def new_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -1280,6 +1421,7 @@
phone=phone,
message=message,
status=status )
+
@web.expose
def edit_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -1357,6 +1499,7 @@
address_obj=address_obj,
message=message,
status=status )
+
@web.expose
def delete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
@@ -1377,6 +1520,7 @@
user_id=user_id,
message=message,
status=status ) )
+
@web.expose
def undelete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
@@ -1396,6 +1540,7 @@
user_id=user_id,
message=message,
status=status ) )
+
@web.expose
def set_user_pref_async( self, trans, pref_name, pref_value ):
""" Set a user preference asynchronously. If user is not logged in, do nothing. """
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 templates/user/index.mako
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -13,6 +13,7 @@
<li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li><li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li>
+ <li><a href="${h.url_for( controller='user', action='toolbox_filters', cntrller=cntrller )}">${_('Manage your ToolBox filters')}</a></li>
%if trans.app.config.enable_openid:
<li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li>
%endif
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 templates/user/toolbox_filters.mako
--- /dev/null
+++ b/templates/user/toolbox_filters.mako
@@ -0,0 +1,91 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+</br>
+</br>
+
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a>
+ </li>
+</ul>
+
+%if tool_filters or section_filters or label_filters:
+ <div class="toolForm">
+ <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
+ % if tool_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Tools</div>
+ <div class="toolFormBody">
+ % for filter in tool_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="t_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="t_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+
+ % if section_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Sections</div>
+ <div class="toolFormBody">
+ % for filter in section_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="s_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="s_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+
+ % if label_filters:
+ <div class="toolFormTitle">Edit ToolBox filters :: Labels</div>
+ <div class="toolFormBody">
+ % for filter in label_filters:
+ <div class="form-row">
+ <div style="float: left; width: 40px; margin-right: 10px;">
+ % if filter['checked']:
+ <input type="checkbox" name="l_${filter['filterpath']}" checked="checked">
+ % else:
+ <input type="checkbox" name="l_${filter['filterpath']}">
+ % endif
+ </div>
+ <div style="float: left; margin-right: 10px;">
+ ${filter['short_desc']}
+ <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ % endfor
+ </div>
+ % endif
+ <div class="form-row">
+ <input type="submit" name="edit_toolbox_filter_button" value="Save changes">
+ </div>
+ </form>
+ </div>
+%else:
+ ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )}
+%endif
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -758,6 +758,18 @@
# if running many handlers.
#cache_user_job_count = False
+# ToolBox filtering
+# Modules from lib/galaxy/tools/filters/ can be specified in the following lines.
+# tool_* filters will be applied for all users and can not be changed by them.
+# user_tool_* filters will be shown under user preferences and can be toogled
+# on and off by runtime
+#tool_filters
+#tool_label_filters
+#tool_section_filters
+#user_tool_filters = examples:restrict_upload_to_admins, examples:restrict_encode
+#user_tool_section_filters = examples:restrict_text
+#user_tool_label_filters = examples:restrict_upload_to_admins, examples:restrict_encode
+
# ---- Galaxy Message Queue -------------------------------------------------
# Galaxy uses AMQ protocol to receive messages from external sources like
https://bitbucket.org/galaxy/galaxy-central/commits/74100455218f/
Changeset: 74100455218f
User: dannon
Date: 2013-10-17 19:41:45
Summary: Fix duplicate import from bad merge
Affected #: 1 file
diff -r fb1b676f51b224a4f3b830402d79652850dd9261 -r 74100455218f1dbfb2ef39aceda4f88ae15e50ef lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -28,7 +28,6 @@
from galaxy.web.form_builder import build_select_field
from galaxy.web.framework.helpers import time_ago, grids
from datetime import datetime, timedelta
-from galaxy.web.framework.helpers import grids
from galaxy.util import hash_util
log = logging.getLogger( __name__ )
https://bitbucket.org/galaxy/galaxy-central/commits/bdf393fb4155/
Changeset: bdf393fb4155
User: dannon
Date: 2013-10-17 20:09:07
Summary: Fix indentation from merge
Affected #: 1 file
diff -r 74100455218f1dbfb2ef39aceda4f88ae15e50ef -r bdf393fb4155bed5f633d2daf9cd6a96ab46e7ce lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -39,8 +39,8 @@
if category:
self.__init_filters( category, user_filters, filters )
else:
- if kwds.get( "trackster", False ):
- filters[ "tool" ].append( _has_trackster_conf )
+ if kwds.get( "trackster", False ):
+ filters[ "tool" ].append( _has_trackster_conf )
return filters
https://bitbucket.org/galaxy/galaxy-central/commits/f888228f48d8/
Changeset: f888228f48d8
User: dannon
Date: 2013-10-17 21:31:15
Summary: Merge w/ central
Affected #: 1 file
diff -r bdf393fb4155bed5f633d2daf9cd6a96ab46e7ce -r f888228f48d89ade8b8f49a4d777c573174392d1 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -293,7 +293,7 @@
full_path_to_dir = os.path.abspath( install_dir )
td_common_util.move_file( current_dir=work_dir,
source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ destination=full_path_to_dir )
if action_type == 'download_by_url':
# Eliminate the download_by_url action so remaining actions can be processed correctly.
filtered_actions = actions[ 1: ]
@@ -551,7 +551,7 @@
full_path_to_dir = os.path.abspath( install_dir )
td_common_util.move_file( current_dir=work_dir,
source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ destination=full_path_to_dir )
def log_results( command, fabric_AttributeString, file_path ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/acf1a0062ea8/
Changeset: acf1a0062ea8
Branch: custom-toolbox2
User: dannon
Date: 2013-10-17 21:32:40
Summary: Close feature branch for toolbox filtering 2
Affected #: 0 files
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: greg: Fix for the call to td_common_util.move_file reported by Jim Johnson - thanks Jim!
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1846eddc72a8/
Changeset: 1846eddc72a8
User: greg
Date: 2013-10-17 19:46:03
Summary: Fix for the call to td_common_util.move_file reported by Jim Johnson - thanks Jim!
Affected #: 1 file
diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r 1846eddc72a8b4138a2835d93b5db764524c216d lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -293,7 +293,7 @@
full_path_to_dir = os.path.abspath( install_dir )
td_common_util.move_file( current_dir=work_dir,
source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ destination=full_path_to_dir )
if action_type == 'download_by_url':
# Eliminate the download_by_url action so remaining actions can be processed correctly.
filtered_actions = actions[ 1: ]
@@ -551,7 +551,7 @@
full_path_to_dir = os.path.abspath( install_dir )
td_common_util.move_file( current_dir=work_dir,
source=downloaded_filename,
- destination_dir=full_path_to_dir )
+ destination=full_path_to_dir )
def log_results( command, fabric_AttributeString, file_path ):
"""
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: carlfeberhard: Graph datatypes: re-add to conf.sample returning False from all sniffers; the user must now manually change the type
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f1d77cc91367/
Changeset: f1d77cc91367
User: carlfeberhard
Date: 2013-10-17 19:14:11
Summary: Graph datatypes: re-add to conf.sample returning False from all sniffers; the user must now manually change the type
Affected #: 2 files
diff -r 01975234fe5b2ea1058dee188b5032155a43499b -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -245,6 +245,10 @@
<datatype extension="snpmatrix" type="galaxy.datatypes.genetics:SNPMatrix" display_in_upload="true"/><datatype extension="xls" type="galaxy.datatypes.tabular:Tabular"/><!-- End RGenetics Datatypes -->
+ <!-- graph datatypes -->
+ <datatype extension="xgmml" type="galaxy.datatypes.graph:Xgmml" display_in_upload="true"/>
+ <datatype extension="sif" type="galaxy.datatypes.graph:Sif" display_in_upload="true"/>
+ <datatype extension="rdf" type="galaxy.datatypes.graph:Rdf" display_in_upload="true"/></registration><sniffers><!--
diff -r 01975234fe5b2ea1058dee188b5032155a43499b -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 lib/galaxy/datatypes/graph.py
--- a/lib/galaxy/datatypes/graph.py
+++ b/lib/galaxy/datatypes/graph.py
@@ -34,14 +34,9 @@
def sniff( self, filename ):
"""
- Determines whether the file is XML or not, should probably actually check if it is a real xgmml file....
+ Returns false and the user must manually set.
"""
- line = ''
- with open( filename ) as handle:
- line = handle.readline()
-
- #TODO - Is there a more robust way to do this?
- return line.startswith( '<?xml ' )
+ return False
@staticmethod
def merge( split_files, output_file ):
@@ -85,19 +80,9 @@
def sniff( self, filename ):
"""
- Determines whether the file is SIF
+ Returns false and the user must manually set.
"""
- line = ''
- with open( filename ) as infile:
- correct = True
- for line in infile:
- if not line.strip():
- continue
- tlen = len( line.split( "\t" ) )
- # may contain 1 or >= 3 columns
- if tlen == 2:
- correct = False
- return correct
+ return False
@staticmethod
def merge( split_files, output_file ):
@@ -116,6 +101,12 @@
"""
file_ext = "rdf"
+ def sniff( self, filename ):
+ """
+ Returns false and the user must manually set.
+ """
+ return False
+
def set_peek( self, dataset, is_multi_byte=False ):
"""Set the peek and blurb text"""
if not dataset.dataset.purged:
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: greg: Allow for skipping specified repositories when setting metadata in the tool shed.
by commits-noreply@bitbucket.org 17 Oct '13
by commits-noreply@bitbucket.org 17 Oct '13
17 Oct '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/01975234fe5b/
Changeset: 01975234fe5b
User: greg
Date: 2013-10-17 17:18:05
Summary: Allow for skipping specified repositories when setting metadata in the tool shed.
Affected #: 3 files
diff -r 329ea7a83af4f389a7c95ee4559d88c6fec0211b -r 01975234fe5b2ea1058dee188b5032155a43499b lib/galaxy/webapps/tool_shed/api/repositories.py
--- a/lib/galaxy/webapps/tool_shed/api/repositories.py
+++ b/lib/galaxy/webapps/tool_shed/api/repositories.py
@@ -230,6 +230,7 @@
to True will restrict resetting metadata to only repositories that are writable by the user
in addition to those repositories of type tool_dependency_definition. This param is ignored
if the current user is not an admin user, in which case this same restriction is automatic.
+ :param encoded_ids_to_skip (optional): a list of encoded repository ids for repositories that should not be processed.
"""
def handle_repository( trans, repository, results ):
repository_id = trans.security.encode_id( repository.id )
@@ -253,6 +254,7 @@
successful_count=0,
unsuccessful_count=0 )
handled_repository_ids = []
+ encoded_ids_to_skip = payload.get( 'encoded_ids_to_skip', [] )
if trans.user_is_admin():
my_writable = util.asbool( payload.get( 'my_writable', False ) )
else:
@@ -260,11 +262,19 @@
query = suc.get_query_for_setting_metadata_on_repositories( trans, my_writable=my_writable, order=False )
# First reset metadata on all repositories of type repository_dependency_definition.
for repository in query:
- if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids:
+ encoded_id = trans.security.encode_id( repository.id )
+ if encoded_id in encoded_ids_to_skip:
+ log.debug( "Skipping repository with id %s because it is in encoded_ids_to_skip %s" % \
+ ( str( repository_id ), str( encoded_ids_to_skip ) ) )
+ elif repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids:
results = handle_repository( trans, repository, results )
# Now reset metadata on all remaining repositories.
for repository in query:
- if repository.type != rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids:
+ encoded_id = trans.security.encode_id( repository.id )
+ if encoded_id in encoded_ids_to_skip:
+ log.debug( "Skipping repository with id %s because it is in encoded_ids_to_skip %s" % \
+ ( str( repository_id ), str( encoded_ids_to_skip ) ) )
+ elif repository.type != rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids:
results = handle_repository( trans, repository, results )
stop_time = strftime( "%Y-%m-%d %H:%M:%S" )
results[ 'stop_time' ] = stop_time
diff -r 329ea7a83af4f389a7c95ee4559d88c6fec0211b -r 01975234fe5b2ea1058dee188b5032155a43499b lib/tool_shed/scripts/api/reset_metadata_on_repositories.py
--- a/lib/tool_shed/scripts/api/reset_metadata_on_repositories.py
+++ b/lib/tool_shed/scripts/api/reset_metadata_on_repositories.py
@@ -27,18 +27,29 @@
def main( options ):
api_key = options.api
+ base_tool_shed_url = options.tool_shed_url.rstrip( '/' )
my_writable = options.my_writable
one_per_request = options.one_per_request
- base_tool_shed_url = options.tool_shed_url.rstrip( '/' )
+ skip_file = options.skip_file
+ encoded_ids_to_skip = []
+ if skip_file and os.path.exists( skip_file ):
+ # Contents of file must be 1 encoded repository id per line.
+ contents = open( skip_file, 'rb' ).read()
+ if contents:
+ encoded_ids_to_skip = contents.split( '\n' )
if string_as_bool( one_per_request ):
url = '%s/api/repositories/repository_ids_for_setting_metadata?key=%s&my_writable=%s' % ( base_tool_shed_url, api_key, str( my_writable ) )
repository_ids = get( url, api_key )
for repository_id in repository_ids:
- data = dict( repository_id=repository_id )
- url = '%s/api/repositories/reset_metadata_on_repository' % base_tool_shed_url
- submit( url, data, options.api )
+ if repository_id in encoded_ids_to_skip:
+ print "Skipping repository with id %s because it is in skip file %s" % ( str( repository_id ), str( skip_file ) )
+ else:
+ data = dict( repository_id=repository_id )
+ url = '%s/api/repositories/reset_metadata_on_repository' % base_tool_shed_url
+ submit( url, data, options.api )
else:
- data = dict( my_writable=my_writable )
+ data = dict( encoded_ids_to_skip=encoded_ids_to_skip,
+ my_writable=my_writable )
url = '%s/api/repositories/reset_metadata_on_repositories' % base_tool_shed_url
submit( url, data, options.api )
@@ -46,7 +57,8 @@
parser = argparse.ArgumentParser( description='Reset metadata on certain repositories in the Tool Shed via the Tool Shed API.' )
parser.add_argument( "-a", "--api", dest="api", required=True, help="API Key" )
parser.add_argument( "-m", "--my_writable", dest="my_writable", required=False, default='False', help="Restrict to my writable repositories" )
- parser.add_argument( "-o", "--one_per_request", dest="one_per_request", required=False, default='False', help="One repository per request" )
+ parser.add_argument( "-o", "--one_per_request", dest="one_per_request", required=False, default='True', help="One repository per request" )
+ parser.add_argument( "-s", "--skip_file", dest="skip_file", required=False, help="Name of local file containing encoded repository ids to skip" )
parser.add_argument( "-u", "--url", dest="tool_shed_url", required=True, help="Tool Shed URL" )
options = parser.parse_args()
main( options )
diff -r 329ea7a83af4f389a7c95ee4559d88c6fec0211b -r 01975234fe5b2ea1058dee188b5032155a43499b lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -821,12 +821,12 @@
clause_list = []
for repository in trans.sa_session.query( trans.model.Repository ) \
.filter( trans.model.Repository.table.c.deleted == False ):
- allow_push = repository.allow_push( trans.app )
- if not order:
- # We've been called from the Tool Shed API, so reset metadata on all repositories of type tool_dependency_definition.
- if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION:
- clause_list.append( trans.model.Repository.table.c.id == repository.id )
- elif allow_push:
+ # Always reset metadata on all repositories of type tool_dependency_definition.
+ if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION:
+ clause_list.append( trans.model.Repository.table.c.id == repository.id )
+ else:
+ allow_push = repository.allow_push( trans.app )
+ if allow_push:
# Include all repositories that are writable by the current user.
allow_push_usernames = allow_push.split( ',' )
if username in allow_push_usernames:
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