galaxy-dev
Threads by month
- ----- 2025 -----
- 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
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10008 discussions
details: http://www.bx.psu.edu/hg/galaxy/rev/5f60d79f483f
changeset: 2613:5f60d79f483f
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 14:01:08 2009 -0400
description:
Remove logging from galaxy.base
2 file(s) affected in this change:
static/scripts/galaxy.base.js
static/scripts/packed/galaxy.base.js
diffs (26 lines):
diff -r 278df6aa7139 -r 5f60d79f483f static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Fri Aug 21 14:28:46 2009 -0400
+++ b/static/scripts/galaxy.base.js Sun Aug 23 14:01:08 2009 -0400
@@ -77,14 +77,12 @@
};
function attach_popupmenu( button_element, wrapper ) {
- console.log( button_element, wrapper );
var clean = function() {
wrapper.unbind().hide();
$("#popup-helper").unbind( "click.popupmenu" ).hide();
// $(document).unbind( "click.popupmenu" );
};
var click = function( e ) {
- console.log( e );
var o = $(button_element).offset();
$("#popup-helper").bind( "click.popupmenu", clean ).show();
// $(document).bind( "click.popupmenu", clean );
diff -r 278df6aa7139 -r 5f60d79f483f static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Fri Aug 21 14:28:46 2009 -0400
+++ b/static/scripts/packed/galaxy.base.js Sun Aug 23 14:01:08 2009 -0400
@@ -1,1 +1,1 @@
-$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){console.log(b,d);var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){console.log(g);var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)};
\ No newline at end of file
+$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)};
\ No newline at end of file
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/77b761ff6cd3
changeset: 2607:77b761ff6cd3
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 09:22:19 2009 -0400
description:
Fix clone history tests
1 file(s) affected in this change:
templates/history/clone.mako
diffs (12 lines):
diff -r e6dda627e6b0 -r 77b761ff6cd3 templates/history/clone.mako
--- a/templates/history/clone.mako Sat Aug 22 23:20:09 2009 -0400
+++ b/templates/history/clone.mako Sun Aug 23 09:22:19 2009 -0400
@@ -8,7 +8,7 @@
<form action="${h.url_for( controller='history', action='clone' )}" method="post" >
<div class="form-row">
%if id_argument is not None:
- <input type="hidden" name="id" value="${trans.security.encode_id( id_argument )}">
+ <input type="hidden" name="id" value="${id_argument}">
%endif
You can clone the history such that the clone will include all items in the original
history, or you can eliminate the original history's deleted items from the clone.
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/19b86ccccf6f
changeset: 2608:19b86ccccf6f
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 12:26:46 2009 -0400
description:
[mq]: pages
5 file(s) affected in this change:
lib/galaxy/model/__init__.py
lib/galaxy/model/mapping.py
lib/galaxy/model/migrate/versions/0014_pages.py
lib/galaxy/web/controllers/user.py
templates/user/index.mako
diffs (220 lines):
diff -r 77b761ff6cd3 -r 19b86ccccf6f lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Sun Aug 23 09:22:19 2009 -0400
+++ b/lib/galaxy/model/__init__.py Sun Aug 23 12:26:46 2009 -0400
@@ -33,6 +33,7 @@
self.external = False
self.deleted = False
self.purged = False
+ self.username = None
# Relationships
self.histories = []
@@ -1118,7 +1119,20 @@
self.country+'<br/>'+ \
'Phone: '+self.phone
+class Page( object ):
+ def __init__( self ):
+ self.id = None
+ self.user = None
+ self.title = None
+ self.slug = None
+ self.latest_revision_id = None
+ self.revisions = []
+class PageRevision( object ):
+ def __init__( self ):
+ self.user = None
+ self.title = None
+ self.content = None
diff -r 77b761ff6cd3 -r 19b86ccccf6f lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Sun Aug 23 09:22:19 2009 -0400
+++ b/lib/galaxy/model/mapping.py Sun Aug 23 12:26:46 2009 -0400
@@ -42,6 +42,7 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
+ Column( "username", TrimmedString( 255 ), index=True, unique=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
@@ -523,6 +524,26 @@
Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ),
Column( "comment", TEXT ) )
+Page.table = Table( "page", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "latest_revision_id", Integer,
+ ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
+ Column( "title", TEXT ),
+ Column( "slug", TEXT, unique=True, index=True ),
+ )
+
+PageRevision.table = Table( "page_revision", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
+ Column( "title", TEXT ),
+ Column( "content", TEXT )
+ )
+
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
@@ -905,6 +926,18 @@
assign_mapper( context, MetadataFile, MetadataFile.table,
properties=dict( history_dataset=relation( HistoryDatasetAssociation ), library_dataset=relation( LibraryDatasetDatasetAssociation ) ) )
+assign_mapper( context, PageRevision, PageRevision.table )
+
+assign_mapper( context, Page, Page.table,
+ properties=dict( user=relation( User ),
+ revisions=relation( PageRevision, backref='page',
+ cascade="all, delete-orphan",
+ primaryjoin=( Page.table.c.id == PageRevision.table.c.page_id ) ),
+ latest_revision=relation( PageRevision, post_update=True,
+ primaryjoin=( Page.table.c.latest_revision_id == PageRevision.table.c.id ),
+ lazy=False )
+ ) )
+
def db_next_hid( self ):
"""
Override __next_hid to generate from the database in a concurrency
diff -r 77b761ff6cd3 -r 19b86ccccf6f lib/galaxy/model/migrate/versions/0014_pages.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0014_pages.py Sun Aug 23 12:26:46 2009 -0400
@@ -0,0 +1,56 @@
+from sqlalchemy import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+
+Page_table = Table( "page", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "latest_revision_id", Integer,
+ ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
+ Column( "title", TEXT ),
+ Column( "slug", TEXT, unique=True, index=True ),
+ )
+
+PageRevision_table = Table( "page_revision", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
+ Column( "title", TEXT ),
+ Column( "content", TEXT )
+ )
+
+def upgrade():
+ metadata.reflect()
+ try:
+ Page_table.create()
+ except:
+ log.debug( "Could not create page table" )
+ try:
+ PageRevision_table.create()
+ except:
+ log.debug( "Could not create page_revision table" )
+
+ # Add 1 column to the user table
+ User_table = Table( "galaxy_user", metadata, autoload=True )
+ col = Column( 'username', String(255), index=True, unique=True, default=False )
+ print type( col ), col
+ col.create( User_table )
+ assert col is User_table.c.username
+
+def downgrade():
+ metadata.reflect()
+ Page_table.drop()
+ PageRevision_table.drop()
+ User_table = Table( "galaxy_user", metadata, autoload=True )
+ User_table.c.username.drop()
\ No newline at end of file
diff -r 77b761ff6cd3 -r 19b86ccccf6f lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Sun Aug 23 09:22:19 2009 -0400
+++ b/lib/galaxy/web/controllers/user.py Sun Aug 23 12:26:46 2009 -0400
@@ -4,7 +4,7 @@
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util
-import logging, os, string
+import logging, os, string, re
from random import choice
log = logging.getLogger( __name__ )
@@ -19,6 +19,8 @@
"""
require_login_nocreation_template = require_login_template % ""
require_login_creation_template = require_login_template % " If you don't already have an account, <a href='%s'>you may create one</a>."
+
+VALID_USERNAME_RE = re.compile( "^[a-zA-Z0-9\-\_]+$" )
class User( BaseController ):
edit_address_id = None
@@ -78,6 +80,37 @@
.add_text( "email", "Email", value=email, error=email_err )
.add_text( "conf_email", "Confirm Email", value='', error=conf_email_err )
.add_password( "password", "Password", value='', error=pass_err ) )
+
+ @web.expose
+ def change_username(self, trans, username='', **kwd):
+ username_err = ''
+ user = trans.get_user()
+ if not user:
+ trans.response.send_redirect( web.url_for( action='login' ) )
+ if trans.request.method == "POST":
+ if len( username ) < 4:
+ username_err = "Username must be at least 4 characters in length"
+ elif len( username ) > 255:
+ username_err = "USername must be at most 255 characters in length"
+ elif not( VALID_USERNAME_RE.match( username ) ):
+ username_err = "Username must contain only letters, numbers, '-', and '_'"
+ elif trans.app.model.User.filter_by( username=username ).first():
+ username_err = "This username is not available"
+ else:
+ user.username = username
+ user.flush()
+ trans.log_event( "User change username" )
+ return trans.show_ok_message( "Username been set to: " + user.username )
+ else:
+ username = user.username or ''
+ return trans.show_form(
+ web.FormBuilder( web.url_for(), "Change username", submit_text="Submit" )
+ .add_text( "username", "Username", value=username, error=username_err,
+ help="""Your username is an optional identifier that
+ will be used to generate adresses for information
+ you share publicly. Usernames must be at least
+ four characters in length and contain only letters,
+ numbers, and the '-' and '_' characters""" ) )
@web.expose
def login( self, trans, email='', password='' ):
diff -r 77b761ff6cd3 -r 19b86ccccf6f templates/user/index.mako
--- a/templates/user/index.mako Sun Aug 23 09:22:19 2009 -0400
+++ b/templates/user/index.mako Sun Aug 23 12:26:46 2009 -0400
@@ -9,6 +9,7 @@
<ul>
<li><a href="${h.url_for( action='change_password' )}">${_('Change your password')}</a></li>
<li><a href="${h.url_for( action='change_email' )}">${_('Update your email address')}</a></li>
+ <li><a href="${h.url_for( action='change_username' )}">${_('Change your public username')}</a></li>
<li><a href="${h.url_for( action='set_default_permissions' )}">${_('Change default permissions')}</a> for new histories</li>
<li><a href="${h.url_for( action='manage_addresses' )}">${_('Manage your addresses')}</a></li>
<li><a href="${h.url_for( action='logout' )}">${_('Logout')}</a></li>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/52a145b22b69
changeset: 2611:52a145b22b69
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 12:31:20 2009 -0400
description:
Merge
1 file(s) affected in this change:
lib/galaxy/model/migrate/versions/0014_pages.py
diffs (220 lines):
diff -r 36c479b93d7e -r 52a145b22b69 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Sun Aug 23 12:28:36 2009 -0400
+++ b/lib/galaxy/model/__init__.py Sun Aug 23 12:31:20 2009 -0400
@@ -33,7 +33,6 @@
self.external = False
self.deleted = False
self.purged = False
- self.username = None
# Relationships
self.histories = []
@@ -1119,20 +1118,7 @@
self.country+'<br/>'+ \
'Phone: '+self.phone
-class Page( object ):
- def __init__( self ):
- self.id = None
- self.user = None
- self.title = None
- self.slug = None
- self.latest_revision_id = None
- self.revisions = []
-class PageRevision( object ):
- def __init__( self ):
- self.user = None
- self.title = None
- self.content = None
diff -r 36c479b93d7e -r 52a145b22b69 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Sun Aug 23 12:28:36 2009 -0400
+++ b/lib/galaxy/model/mapping.py Sun Aug 23 12:31:20 2009 -0400
@@ -42,7 +42,6 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", TrimmedString( 255 ), index=True, unique=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
@@ -524,26 +523,6 @@
Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ),
Column( "comment", TEXT ) )
-Page.table = Table( "page", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
- Column( "latest_revision_id", Integer,
- ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
- Column( "title", TEXT ),
- Column( "slug", TEXT, unique=True, index=True ),
- )
-
-PageRevision.table = Table( "page_revision", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
- Column( "title", TEXT ),
- Column( "content", TEXT )
- )
-
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
@@ -926,18 +905,6 @@
assign_mapper( context, MetadataFile, MetadataFile.table,
properties=dict( history_dataset=relation( HistoryDatasetAssociation ), library_dataset=relation( LibraryDatasetDatasetAssociation ) ) )
-assign_mapper( context, PageRevision, PageRevision.table )
-
-assign_mapper( context, Page, Page.table,
- properties=dict( user=relation( User ),
- revisions=relation( PageRevision, backref='page',
- cascade="all, delete-orphan",
- primaryjoin=( Page.table.c.id == PageRevision.table.c.page_id ) ),
- latest_revision=relation( PageRevision, post_update=True,
- primaryjoin=( Page.table.c.latest_revision_id == PageRevision.table.c.id ),
- lazy=False )
- ) )
-
def db_next_hid( self ):
"""
Override __next_hid to generate from the database in a concurrency
diff -r 36c479b93d7e -r 52a145b22b69 lib/galaxy/model/migrate/versions/0014_pages.py
--- a/lib/galaxy/model/migrate/versions/0014_pages.py Sun Aug 23 12:28:36 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-from sqlalchemy import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-
-import logging
-log = logging.getLogger( __name__ )
-
-metadata = MetaData( migrate_engine )
-
-Page_table = Table( "page", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
- Column( "latest_revision_id", Integer,
- ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
- Column( "title", TEXT ),
- Column( "slug", TEXT, unique=True, index=True ),
- )
-
-PageRevision_table = Table( "page_revision", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
- Column( "title", TEXT ),
- Column( "content", TEXT )
- )
-
-def upgrade():
- metadata.reflect()
- try:
- Page_table.create()
- except:
- log.debug( "Could not create page table" )
- try:
- PageRevision_table.create()
- except:
- log.debug( "Could not create page_revision table" )
-
- # Add 1 column to the user table
- User_table = Table( "galaxy_user", metadata, autoload=True )
- col = Column( 'username', String(255), index=True, unique=True, default=False )
- print type( col ), col
- col.create( User_table )
- assert col is User_table.c.username
-
-def downgrade():
- metadata.reflect()
- Page_table.drop()
- PageRevision_table.drop()
- User_table = Table( "galaxy_user", metadata, autoload=True )
- User_table.c.username.drop()
\ No newline at end of file
diff -r 36c479b93d7e -r 52a145b22b69 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Sun Aug 23 12:28:36 2009 -0400
+++ b/lib/galaxy/web/controllers/user.py Sun Aug 23 12:31:20 2009 -0400
@@ -4,7 +4,7 @@
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util
-import logging, os, string, re
+import logging, os, string
from random import choice
log = logging.getLogger( __name__ )
@@ -19,8 +19,6 @@
"""
require_login_nocreation_template = require_login_template % ""
require_login_creation_template = require_login_template % " If you don't already have an account, <a href='%s'>you may create one</a>."
-
-VALID_USERNAME_RE = re.compile( "^[a-zA-Z0-9\-\_]+$" )
class User( BaseController ):
edit_address_id = None
@@ -80,37 +78,6 @@
.add_text( "email", "Email", value=email, error=email_err )
.add_text( "conf_email", "Confirm Email", value='', error=conf_email_err )
.add_password( "password", "Password", value='', error=pass_err ) )
-
- @web.expose
- def change_username(self, trans, username='', **kwd):
- username_err = ''
- user = trans.get_user()
- if not user:
- trans.response.send_redirect( web.url_for( action='login' ) )
- if trans.request.method == "POST":
- if len( username ) < 4:
- username_err = "Username must be at least 4 characters in length"
- elif len( username ) > 255:
- username_err = "USername must be at most 255 characters in length"
- elif not( VALID_USERNAME_RE.match( username ) ):
- username_err = "Username must contain only letters, numbers, '-', and '_'"
- elif trans.app.model.User.filter_by( username=username ).first():
- username_err = "This username is not available"
- else:
- user.username = username
- user.flush()
- trans.log_event( "User change username" )
- return trans.show_ok_message( "Username been set to: " + user.username )
- else:
- username = user.username or ''
- return trans.show_form(
- web.FormBuilder( web.url_for(), "Change username", submit_text="Submit" )
- .add_text( "username", "Username", value=username, error=username_err,
- help="""Your username is an optional identifier that
- will be used to generate adresses for information
- you share publicly. Usernames must be at least
- four characters in length and contain only letters,
- numbers, and the '-' and '_' characters""" ) )
@web.expose
def login( self, trans, email='', password='' ):
diff -r 36c479b93d7e -r 52a145b22b69 templates/user/index.mako
--- a/templates/user/index.mako Sun Aug 23 12:28:36 2009 -0400
+++ b/templates/user/index.mako Sun Aug 23 12:31:20 2009 -0400
@@ -9,7 +9,6 @@
<ul>
<li><a href="${h.url_for( action='change_password' )}">${_('Change your password')}</a></li>
<li><a href="${h.url_for( action='change_email' )}">${_('Update your email address')}</a></li>
- <li><a href="${h.url_for( action='change_username' )}">${_('Change your public username')}</a></li>
<li><a href="${h.url_for( action='set_default_permissions' )}">${_('Change default permissions')}</a> for new histories</li>
<li><a href="${h.url_for( action='manage_addresses' )}">${_('Manage your addresses')}</a></li>
<li><a href="${h.url_for( action='logout' )}">${_('Logout')}</a></li>
1
0

24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/36c479b93d7e
changeset: 2609:36c479b93d7e
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 12:28:36 2009 -0400
description:
Fix security problem with grids. Template should not be passed at call time, it must be passed at configure time.
6 file(s) affected in this change:
lib/galaxy/web/controllers/history.py
lib/galaxy/web/controllers/requests.py
lib/galaxy/web/controllers/requests_admin.py
lib/galaxy/web/framework/helpers/grids.py
manage_db.sh
templates/grid.mako
diffs (325 lines):
diff -r 19b86ccccf6f -r 36c479b93d7e lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/web/controllers/history.py Sun Aug 23 12:28:36 2009 -0400
@@ -39,6 +39,7 @@
# Grid definition
title = "Stored histories"
model_class = model.History
+ template='/history/grid.mako'
default_sort_key = "-create_time"
columns = [
grids.GridColumn( "Name", key="name",
@@ -86,6 +87,7 @@
return history.user.email
# Grid definition
title = "Histories shared with you by others"
+ template='/history/grid.mako'
model_class = model.History
default_sort_key = "-update_time"
columns = [
@@ -161,7 +163,7 @@
status, message = self._list_undelete( trans, histories )
trans.sa_session.flush()
# Render the list view
- return self.stored_list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs )
+ return self.stored_list_grid( trans, status=status, message=message, **kwargs )
def _list_delete( self, trans, histories ):
"""Delete histories"""
n_deleted = 0
@@ -240,14 +242,14 @@
if operation == "clone":
if not id:
message = "Select a history to clone"
- return self.shared_list_grid( trans, status='error', message=message, template='/history/grid.mako', **kwargs )
+ return self.shared_list_grid( trans, status='error', message=message, **kwargs )
# When cloning shared histories, only copy active datasets
new_kwargs = { 'clone_choice' : 'active' }
return self.clone( trans, id, **new_kwargs )
elif operation == 'unshare':
if not id:
message = "Select a history to unshare"
- return self.shared_list_grid( trans, status='error', message=message, template='/history/grid.mako', **kwargs )
+ return self.shared_list_grid( trans, status='error', message=message, **kwargs )
ids = util.listify( id )
histories = []
for history_id in ids:
@@ -261,7 +263,7 @@
message = "Unshared %d shared histories" % len( ids )
status = 'done'
# Render the list view
- return self.shared_list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs )
+ return self.shared_list_grid( trans, status=status, message=message, **kwargs )
@web.expose
def delete_current( self, trans ):
"""Delete just the active history -- this does not require a logged in user."""
diff -r 19b86ccccf6f -r 36c479b93d7e lib/galaxy/web/controllers/requests.py
--- a/lib/galaxy/web/controllers/requests.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/web/controllers/requests.py Sun Aug 23 12:28:36 2009 -0400
@@ -16,6 +16,7 @@
class RequestsListGrid( grids.Grid ):
title = "Sequencing Requests"
+ template = '/requests/grid.mako'
model_class = model.Request
default_sort_key = "-create_time"
show_filter = model.Request.states.UNSUBMITTED
@@ -103,7 +104,7 @@
self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.UNSUBMITTED)
# Render the list view
- return self.request_grid( trans, template='/requests/grid.mako', **kwargs )
+ return self.request_grid( trans, **kwargs )
def __show_request(self, trans, id, add_sample=False):
try:
diff -r 19b86ccccf6f -r 36c479b93d7e lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Sun Aug 23 12:28:36 2009 -0400
@@ -14,6 +14,7 @@
class RequestsListGrid( grids.Grid ):
title = "Sequencing Requests"
+ template = "admin/requests/grid.mako"
model_class = model.Request
default_sort_key = "-create_time"
show_filter = model.Request.states.SUBMITTED
@@ -101,7 +102,7 @@
self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.SUBMITTED)
# Render the list view
- return self.request_grid( trans, template='/admin/requests/grid.mako', **kwargs )
+ return self.request_grid( trans, **kwargs )
@web.expose
@web.require_admin
def edit(self, trans, **kwd):
diff -r 19b86ccccf6f -r 36c479b93d7e lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/web/framework/helpers/grids.py Sun Aug 23 12:28:36 2009 -0400
@@ -14,8 +14,9 @@
title = ""
exposed = True
model_class = None
- template = None
+ template = "grid.mako"
columns = []
+ operations = []
standard_filters = []
default_filter = None
default_sort_key = None
@@ -25,7 +26,6 @@
def __call__( self, trans, **kwargs ):
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
- template = kwargs.get( 'template', None )
session = trans.sa_session
# Build initial query
query = self.build_initial_query( session )
@@ -77,7 +77,7 @@
else:
new_kwargs[ 'id' ] = trans.security.encode_id( id )
return url_for( **new_kwargs )
- return trans.fill_template( template,
+ return trans.fill_template( self.template,
grid=self,
query=query,
sort_key=sort_key,
diff -r 19b86ccccf6f -r 36c479b93d7e templates/grid.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/grid.mako Sun Aug 23 12:28:36 2009 -0400
@@ -0,0 +1,196 @@
+<%inherit file="/base.mako"/>
+<%def name="title()">${grid.title}</%def>
+
+%if message:
+ <p>
+ <div class="${message_type}message transient-message">${message}</div>
+ <div style="clear: both"></div>
+ </p>
+%endif
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ ## TODO: generalize and move into galaxy.base.js
+ $(document).ready(function() {
+ $(".grid").each( function() {
+ var grid = this;
+ var checkboxes = $(this).find("input.grid-row-select-checkbox");
+ var update = $(this).find( "span.grid-selected-count" );
+ $(checkboxes).each( function() {
+ $(this).change( function() {
+ var n = $(checkboxes).filter("[checked]").size();
+ update.text( n );
+ });
+ })
+ });
+ });
+ ## Can this be moved into base.mako?
+ %if refresh_frames:
+ %if 'masthead' in refresh_frames:
+ ## Refresh masthead == user changes (backward compatibility)
+ if ( parent.user_changed ) {
+ %if trans.user:
+ parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} );
+ %else:
+ parent.user_changed( null, false );
+ %endif
+ }
+ %endif
+ %if 'history' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_history ) {
+ parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}";
+ if ( parent.force_right_panel ) {
+ parent.force_right_panel( 'show' );
+ }
+ }
+ %endif
+ %if 'tools' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_tools ) {
+ parent.frames.galaxy_tools.location.href="${h.url_for( controller='root', action='tool_menu')}";
+ if ( parent.force_left_panel ) {
+ parent.force_left_panel( 'show' );
+ }
+ }
+ %endif
+ %endif
+ </script>
+</%def>
+
+<%def name="stylesheets()">
+ <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" />
+ <style>
+ ## Not generic to all grids -- move to base?
+ .count-box {
+ min-width: 1.1em;
+ padding: 5px;
+ border-width: 1px;
+ border-style: solid;
+ text-align: center;
+ display: inline-block;
+ }
+ </style>
+</%def>
+
+<div class="grid-header">
+ <h2>${grid.title}</h2>
+ %if grid.standard_filters:
+ <span class="title">Filter:</span>
+ %for i, filter in enumerate( grid.standard_filters ):
+ %if i > 0:
+ <span>|</span>
+ %endif
+ <span class="filter"><a href="${url( filter.get_url_args() )}">${filter.label}</a></span>
+ %endfor
+ %endif
+</div>
+
+
+<form action="${url()}" method="post" >
+ <table class="grid">
+ <thead>
+ <tr>
+ <th></th>
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ href = ""
+ extra = ""
+ if column.sortable:
+ if sort_key == column.key:
+ if sort_order == "asc":
+ href = url( sort=( "-" + column.key ) )
+ extra = "↓"
+ else:
+ href = url( sort=( column.key ) )
+ extra = "↑"
+ else:
+ href = url( sort=column.key )
+ %>
+ <th\
+ %if column.ncells > 1:
+ colspan="${column.ncells}"
+ %endif
+ >
+ %if href:
+ <a href="${href}">${column.label}</a>
+ %else:
+ ${column.label}
+ %endif
+ <span>${extra}</span>
+ </th>
+ %endif
+ %endfor
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ %for i, item in enumerate( query ):
+ <tr \
+ %if current_item == item:
+ class="current" \
+ %endif
+ >
+ ## Item selection column
+ <td style="width: 1.5em;">
+ <input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" />
+ </td>
+ ## Data columns
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ # Link
+ link = column.get_link( trans, grid, item )
+ if link:
+ href = url( **link )
+ else:
+ href = None
+ # Value (coerced to list so we can loop)
+ value = column.get_value( trans, grid, item )
+ if column.ncells == 1:
+ value = [ value ]
+ %>
+ %for cellnum, v in enumerate( value ):
+ <%
+ # Attach popup menu?
+ if column.attach_popup and cellnum == 0:
+ extra = '<a id="grid-%d-popup" class="arrow" style="display: none;"><span>▼</span></a>' % i
+ else:
+ extra = ""
+ %>
+ %if href:
+ <td><div class="menubutton split"><a class="label" href="${href}">${v}${extra}</a></td>
+ %else:
+ <td >${v}${extra}</td>
+ %endif
+ %endfor
+ %endif
+ %endfor
+ ## Actions column
+ <td>
+ <div popupmenu="grid-${i}-popup">
+ %for operation in grid.operations:
+ %if operation.allowed( item ):
+ <a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a>
+ %endif
+ %endfor
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </tbody>
+ <tfoot>
+ <tr>
+ <td></td>
+ <td colspan="100">
+ For <span class="grid-selected-count"></span> selected items:
+ %for operation in grid.operations:
+ %if operation.allow_multiple:
+ <input type="submit" name="operation" value="${operation.label}" class="action-button">
+ %endif
+ %endfor
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/e6dda627e6b0
changeset: 2606:e6dda627e6b0
user: James Taylor <james(a)jamestaylor.org>
date: Sat Aug 22 23:20:09 2009 -0400
description:
Merge
2 file(s) affected in this change:
templates/base_panels.mako
templates/history/grid.mako
diffs (2711 lines):
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/model/migrate/versions/0009_request_table.py
--- a/lib/galaxy/model/migrate/versions/0009_request_table.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/model/migrate/versions/0009_request_table.py Sat Aug 22 23:20:09 2009 -0400
@@ -9,6 +9,7 @@
from migrate.changeset import *
import sys, logging
from galaxy.model.custom_types import *
+from sqlalchemy.exceptions import *
log = logging.getLogger( __name__ )
log.setLevel(logging.DEBUG)
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/tools/__init__.py Sat Aug 22 23:20:09 2009 -0400
@@ -1534,10 +1534,19 @@
child_dataset.flush()
child_dataset.set_size()
child_dataset.name = "Secondary Dataset (%s)" % ( designation )
- child_dataset.state = child_dataset.states.OK
child_dataset.init_meta()
child_dataset.set_meta()
child_dataset.set_peek()
+ # Associate new dataset with job
+ job = None
+ for assoc in outdata.creating_job_associations:
+ job = assoc.job
+ break
+ if job:
+ assoc = self.app.model.JobToOutputDatasetAssociation( '__new_child_file_%s|%s__' % ( name, designation ), child_dataset )
+ assoc.job = job
+ assoc.flush()
+ child_dataset.state = outdata.state
child_dataset.flush()
# Add child to return dict
children[name][designation] = child_dataset
@@ -1550,7 +1559,7 @@
def collect_primary_datasets( self, output):
primary_datasets = {}
- #Loop through output file names, looking for generated primary datasets in form of 'primary_associatedWithDatasetID_designation_visibility_extension'
+ #Loop through output file names, looking for generated primary datasets in form of 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
for name, outdata in output.items():
for filename in glob.glob(os.path.join(self.app.config.new_file_path,"primary_%i_*" % outdata.id) ):
if not name in primary_datasets:
@@ -1563,19 +1572,32 @@
if visible == "visible": visible = True
else: visible = False
ext = fields.pop(0).lower()
+ dbkey = outdata.dbkey
+ if fields:
+ dbkey = fields[ 0 ]
# Create new primary dataset
- primary_data = self.app.model.HistoryDatasetAssociation( extension=ext, designation=designation, visible=visible, dbkey=outdata.dbkey, create_dataset=True )
+ primary_data = self.app.model.HistoryDatasetAssociation( extension=ext, designation=designation, visible=visible, dbkey=dbkey, create_dataset=True )
self.app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
primary_data.flush()
# Move data from temp location to dataset location
shutil.move( filename, primary_data.file_name )
primary_data.set_size()
- primary_data.name = dataset.name
- primary_data.info = dataset.info
- primary_data.state = primary_data.states.OK
- primary_data.init_meta( copy_from=dataset )
+ primary_data.name = outdata.name
+ primary_data.info = outdata.info
+ primary_data.init_meta( copy_from=outdata )
+ primary_data.dbkey = dbkey
primary_data.set_meta()
primary_data.set_peek()
+ # Associate new dataset with job
+ job = None
+ for assoc in outdata.creating_job_associations:
+ job = assoc.job
+ break
+ if job:
+ assoc = self.app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
+ assoc.job = job
+ assoc.flush()
+ primary_data.state = outdata.state
primary_data.flush()
outdata.history.add_dataset( primary_data )
# Add dataset to return dict
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/tools/actions/upload.py
--- a/lib/galaxy/tools/actions/upload.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/tools/actions/upload.py Sat Aug 22 23:20:09 2009 -0400
@@ -20,12 +20,10 @@
for upload_dataset in incoming['files']:
f = upload_dataset['file_data']
if isinstance( f, FieldStorage ):
- # very small files can be StringIOs
- if 'name' in dir( f.file ) and f.file.name != '<fdopen>':
- local_filename = util.mkstemp_ln( f.file.name, 'upload_file_data_' )
- f.file.close()
- else:
- local_filename = datatypes.sniff.stream_to_file( f.file, prefix="strio_upload_file_" )[0]
+ assert not isinstance( f.file, StringIO.StringIO )
+ assert f.file.name != '<fdopen>'
+ local_filename = util.mkstemp_ln( f.file.name, 'upload_file_data_' )
+ f.file.close()
upload_dataset['file_data'] = dict( filename = f.filename,
local_filename = local_filename )
if upload_dataset['url_paste'].strip() != '':
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/tools/parameters/dynamic_options.py
--- a/lib/galaxy/tools/parameters/dynamic_options.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/tools/parameters/dynamic_options.py Sat Aug 22 23:20:09 2009 -0400
@@ -242,6 +242,55 @@
rval.append( add_value )
return rval
+class RemoveValueFilter( Filter ):
+ """
+ Removes a value from an options list.
+
+ Type: remove_value
+
+ Required Attributes:
+ value: value to remove from select list
+ or
+ ref: param to refer to
+ or
+ meta_ref: dataset to refer to
+ key: metadata key to compare to
+ """
+ def __init__( self, d_option, elem ):
+ Filter.__init__( self, d_option, elem )
+ self.value = elem.get( "value", None )
+ self.ref_name = elem.get( "ref", None )
+ self.meta_ref = elem.get( "meta_ref", None )
+ self.metadata_key = elem.get( "key", None )
+ assert self.value is not None or ( ( self.ref_name is not None or self.meta_ref is not None )and self.metadata_key is not None ), ValueError( "Required 'value' or 'ref' and 'key' attributes missing from filter" )
+ self.multiple = string_as_bool( elem.get( "multiple", "False" ) )
+ self.separator = elem.get( "separator", "," )
+ def filter_options( self, options, trans, other_values ):
+ if trans is not None and trans.workflow_building_mode: return options
+ assert self.value is not None or ( self.ref_name is not None and self.ref_name in other_values ) or (self.meta_ref is not None and self.meta_ref in other_values ) or ( trans is not None and trans.workflow_building_mode), Exception( "Required dependency '%s' or '%s' not found in incoming values" % ( self.ref_name, self.meta_ref ) )
+ def compare_value( option_value, filter_value ):
+ if isinstance( filter_value, list ):
+ if self.multiple:
+ option_value = option_value.split( self.separator )
+ for value in filter_value:
+ if value not in filter_value:
+ return False
+ return True
+ return option_value in filter_value
+ if self.multiple:
+ return filter_value in option_value.split( self.separator )
+ return option_value == filter_value
+ value = self.value
+ if value is None:
+ if self.ref_name is not None:
+ value = other_values.get( self.ref_name )
+ else:
+ data_ref = other_values.get( self.meta_ref )
+ if not isinstance( data_ref, self.dynamic_option.tool_param.tool.app.model.HistoryDatasetAssociation ):
+ return options #cannot modify options
+ value = data_ref.metadata.get( self.metadata_key, None )
+ return [ ( disp_name, optval, selected ) for disp_name, optval, selected in options if not compare_value( optval, value ) ]
+
class SortByColumnFilter( Filter ):
"""
Sorts an options list by a column
@@ -274,6 +323,7 @@
unique_value = UniqueValueFilter,
multiple_splitter = MultipleSplitterFilter,
add_value = AdditionalValueFilter,
+ remove_value = RemoveValueFilter,
sort_by = SortByColumnFilter )
class DynamicOptions( object ):
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/admin.py Sat Aug 22 23:20:09 2009 -0400
@@ -764,11 +764,7 @@
# See if we have any field contents
info = info_association.info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -965,11 +961,7 @@
# See if we have any field contents
info = info_association.info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -1220,11 +1212,7 @@
# See if we have any field contents
info = info_association.info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -2027,7 +2015,7 @@
num_states = int( util.restore_text( params.get( 'num_states', 0 ) ))
proceed = True
for i in range( num_states ):
- if not util.restore_text( params.get( 'new_element_name_%i' % i, None ) ):
+ if not util.restore_text( params.get( 'state_name_%i' % i, None ) ):
proceed = False
break
if not proceed:
@@ -2045,8 +2033,8 @@
ss.delete()
ss.flush()
for i in range( num_states ):
- name = util.restore_text( params.get( 'new_element_name_%i' % i, None ))
- desc = util.restore_text( params.get( 'new_element_description_%i' % i, None ))
+ name = util.restore_text( params.get( 'state_name_%i' % i, None ))
+ desc = util.restore_text( params.get( 'state_desc_%i' % i, None ))
ss = trans.app.model.SampleState(name, desc, rt)
ss.flush()
msg = "The new request type named '%s' with %s state(s) has been created" % (rt.name, num_states)
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/forms.py
--- a/lib/galaxy/web/controllers/forms.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/forms.py Sat Aug 22 23:20:09 2009 -0400
@@ -175,7 +175,7 @@
'visible': True,
'required': False,
'type': BaseField.form_field_types()[0],
- 'selectlist': '' }
+ 'selectlist': [] }
self.current_form['fields'].append(empty_field)
def __get_field(self, index, **kwd):
params = util.Params( kwd )
@@ -183,10 +183,10 @@
# To reproduce, create a new form, click the "add field" button, click the
# browser back arrow, then click the "add field" button again.
# You should never attempt to "restore_text()" on a None object...
- name = util.restore_text( params.get( 'field_name_%i' % index, None ) )
- helptext = util.restore_text( params.get( 'field_helptext_%i' % index, None ) )
+ name = util.restore_text( params.get( 'field_name_%i' % index, '' ) )
+ helptext = util.restore_text( params.get( 'field_helptext_%i' % index, '' ) )
required = params.get( 'field_required_%i' % index, False )
- field_type = util.restore_text( params.get( 'field_type_%i' % index, None ) )
+ field_type = util.restore_text( params.get( 'field_type_%i' % index, '' ) )
if field_type == 'SelectField':
selectlist = self.__get_selectbox_options(index, **kwd)
return {'label': name,
@@ -419,22 +419,39 @@
else:
fdc_list = trans.app.model.FormDefinitionCurrent.query().all()
return [ fdc.latest_form for fdc in fdc_list ]
-def get_form_widgets( trans, form, contents={} ):
+
+
+def get_form_widgets( trans, form, contents=[], user=None, **kwd ):
'''
Return the list of widgets that comprise a form definition,
including field contents if any.
'''
+ params = util.Params( kwd )
+ if not user:
+ user = trans.user
widgets = []
for index, field in enumerate( form.fields ):
field_name = 'field_%i' % index
- if field_name in contents:
- value = contents[ field_name ]
- elif field[ 'type' ] == 'CheckboxField':
- # Since we do not have contents, set checkbox value to False
- value = False
+ # determine the value of the field
+ if field_name in kwd:
+ # the user had already filled out this field and the same form is re-rendered
+ # due to some reason like required fields have been left out.
+ if field[ 'type' ] == 'CheckboxField':
+ value = CheckboxField.is_checked( util.restore_text( params.get( field_name, False ) ) )
+ else:
+ value = util.restore_text( params.get( field_name, '' ) )
+ elif contents:
+ # this field has a saved value
+ value = str(contents[ index ])
else:
- # Set other field types to empty string
- value = ''
+ # if none of the above, then leave the field empty
+ if field[ 'type' ] == 'CheckboxField':
+ # Since we do not have contents, set checkbox value to False
+ value = False
+ else:
+ # Set other field types to empty string
+ value = ''
+ # create the field widget
field_widget = eval( field[ 'type' ] )( field_name )
if field[ 'type' ] == 'TextField':
field_widget.set_size( 40 )
@@ -442,6 +459,10 @@
elif field[ 'type' ] == 'TextArea':
field_widget.set_size( 3, 40 )
field_widget.value = value
+ elif field['type'] == 'AddressField':
+ field_widget.user = user
+ field_widget.value = value
+ field_widget.params = params
elif field[ 'type' ] == 'SelectField':
for option in field[ 'selectlist' ]:
if option == value:
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/library.py
--- a/lib/galaxy/web/controllers/library.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/library.py Sat Aug 22 23:20:09 2009 -0400
@@ -137,11 +137,7 @@
# See if we have any field contents
info = library.info_association[0].info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -475,11 +471,7 @@
# See if we have any field contents
info = info_association.info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -996,11 +988,7 @@
# See if we have any field contents
info = info_association.info
if info:
- field_contents = {}
- for index, value in enumerate( info.content ):
- key = 'field_%i' % index
- field_contents[ key ] = value
- widgets = get_form_widgets( trans, template, field_contents )
+ widgets = get_form_widgets( trans, template, info.content )
else:
widgets = get_form_widgets( trans, template )
else:
@@ -1173,3 +1161,13 @@
edit_info=True,
msg=util.sanitize_text( msg ),
messagetype='done' ) )
+
+
+def get_authorized_libs(trans, user):
+ all_libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all()
+ authorized_libraries = []
+ for library in all_libraries:
+ if trans.app.security_agent.allow_action(user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library) \
+ or trans.app.security_agent.allow_action(user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library):
+ authorized_libraries.append(library)
+ return authorized_libraries
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/requests.py
--- a/lib/galaxy/web/controllers/requests.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/requests.py Sat Aug 22 23:20:09 2009 -0400
@@ -8,6 +8,8 @@
from galaxy.web.form_builder import *
from datetime import datetime, timedelta
from cgi import escape, FieldStorage
+from galaxy.web.controllers.forms import get_form_widgets
+from galaxy.web.controllers.library import get_authorized_libs
log = logging.getLogger( __name__ )
@@ -62,18 +64,12 @@
request_grid = RequestsListGrid()
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def index( self, trans ):
return trans.fill_template( "requests/index.mako" )
-
- def get_authorized_libs(self, trans):
- all_libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all()
- authorized_libraries = []
- for library in all_libraries:
- if trans.app.security_agent.allow_action(trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library) \
- or trans.app.security_agent.allow_action(trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library):
- authorized_libraries.append(library)
- return authorized_libraries
+
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def list( self, trans, **kwargs ):
'''
List all request made by the current user
@@ -137,7 +133,6 @@
Shows the request details
'''
request = trans.app.model.Request.get(id)
- libraries = self.get_authorized_libs(trans)
# list of widgets to be rendered on the request form
request_details = []
# main details
@@ -146,6 +141,9 @@
helptext=''))
request_details.append(dict(label='Type',
value=request.type.name,
+ helptext=''))
+ request_details.append(dict(label='State',
+ value=request.state,
helptext=''))
request_details.append(dict(label='Date created',
value=request.create_time,
@@ -201,6 +199,7 @@
copy_list.add_option(s[0], i)
return copy_list
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def show_request(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -326,6 +325,7 @@
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def delete_sample(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -348,6 +348,7 @@
edit_mode=self.edit_mode)
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def toggle_request_details(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -384,6 +385,7 @@
select_reqtype.add_option(rt.name, rt.id)
return select_reqtype
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def new(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -413,8 +415,8 @@
if params.get('create_request_button', False) == 'Save':
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
- msg=msg ,
- messagetype='done') )
+ message=msg ,
+ status='done') )
elif params.get('create_request_samples_button', False) == 'Add samples':
new_kwd = {}
new_kwd['id'] = trans.security.encode_id(request.id)
@@ -457,12 +459,10 @@
helptext='(Optional)'))
# libraries selectbox
- libraries = self.get_authorized_libs(trans)
+ libraries = get_authorized_libs(trans, trans.user)
libui = self.__library_ui(libraries, **kwd)
widgets = widgets + libui
- widgets = self.__create_form(trans, request_type.request_form_id, widgets,
- form_values, **kwd)
- title = 'Add a new request of type: %s' % request_type.name
+ widgets = widgets + get_form_widgets(trans, request_type.request_form, contents=[], **kwd)
return trans.fill_template( '/requests/new_request.mako',
select_request_type=select_request_type,
request_type=request_type,
@@ -502,58 +502,13 @@
return [widget, new_lib]
else:
return [widget]
-
- def __create_form(self, trans, form_id, widgets=[], form_values=None, **kwd):
- # TODO: RC - replace this method by importing as follows:
- # from galaxy.web.controllers.forms import get_form_widgets
- params = util.Params( kwd )
- form = trans.app.model.FormDefinition.get(form_id)
- # form fields
- for index, field in enumerate(form.fields):
- # value of the field
- if field['type'] == 'CheckboxField':
- value = util.restore_text( params.get( 'field_%i' % index, False ) )
- else:
- value = util.restore_text( params.get( 'field_%i' % index, '' ) )
- if not value:
- if form_values:
- value = str(form_values.content[index])
- # create the field
- fw = eval(field['type'])('field_%i' % index)
- if field['type'] == 'TextField':
- fw.set_size(40)
- fw.value = value
- elif field['type'] == 'TextArea':
- fw.set_size(3, 40)
- fw.value = value
- elif field['type'] == 'AddressField':
- fw.user = trans.user
- fw.value = value
- fw.params = params
- elif field['type'] == 'SelectField':
- for option in field['selectlist']:
- if option == value:
- fw.add_option(option, option, selected=True)
- else:
- fw.add_option(option, option)
- elif field['type'] == 'CheckboxField':
- fw.checked = value
- # require/optional
- if field['required'] == 'required':
- req = 'Required'
- else:
- req = 'Optional'
- widgets.append(dict(label=field['label'],
- widget=fw,
- helptext=field['helptext']+' ('+req+')'))
- return widgets
def __validate(self, trans, request):
'''
Validates the request entered by the user
'''
empty_fields = []
- if not request.library:
- empty_fields.append('Data library')
+# if not request.library:
+# empty_fields.append('Data library')
# check rest of the fields of the form
for index, field in enumerate(request.type.request_form.fields):
if field['required'] == 'required' and request.values.content[index] in ['', None]:
@@ -622,6 +577,7 @@
request.flush()
return request
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def edit(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -698,11 +654,10 @@
helptext='(Optional)'))
# libraries selectbox
- libraries = self.get_authorized_libs(trans)
+ libraries = get_authorized_libs(trans, trans.user)
libui = self.__library_ui(libraries, request, **kwd)
widgets = widgets + libui
- widgets = self.__create_form(trans, request.type.request_form_id, widgets,
- request.values, **kwd)
+ widgets = widgets + get_form_widgets(trans, request.type.request_form, request.values.content, **kwd)
return trans.fill_template( '/requests/edit_request.mako',
select_request_type=select_request_type,
request_type=request.type,
@@ -735,6 +690,8 @@
kwd['id'] = trans.security.encode_id(request.id)
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
+ status='done',
+ message='The request <b>%s</b> has been deleted.' % request.name,
**kwd) )
def __undelete_request(self, trans, id):
try:
@@ -754,6 +711,8 @@
kwd['id'] = trans.security.encode_id(request.id)
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
+ status='done',
+ message='The request <b>%s</b> has been undeleted.' % request.name,
**kwd) )
def __submit(self, trans, id):
try:
@@ -784,10 +743,14 @@
request.flush()
kwd = {}
kwd['id'] = trans.security.encode_id(request.id)
+ kwd['status'] = 'done'
+ kwd['message'] = 'The request <b>%s</b> has been submitted.' % request.name
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
+ show_filter=trans.app.model.Request.states.SUBMITTED,
**kwd) )
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def submit_request(self, trans, **kwd):
params = util.Params( kwd )
try:
@@ -817,13 +780,16 @@
# change request's submitted field
request.state = request.states.SUBMITTED
request.flush()
- ## TODO
kwd['id'] = trans.security.encode_id(request.id)
+ kwd['status'] = 'done'
+ kwd['message'] = 'The request <b>%s</b> has been submitted.' % request.name
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
+ show_filter=trans.app.model.Request.states.SUBMITTED,
**kwd) )
@web.expose
+ @web.require_login( "create/submit sequencing requests" )
def show_events(self, trans, **kwd):
params = util.Params( kwd )
try:
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Sat Aug 22 23:20:09 2009 -0400
@@ -7,19 +7,20 @@
import logging, tempfile, zipfile, tarfile, os, sys
from galaxy.web.form_builder import *
from datetime import datetime, timedelta
+from galaxy.web.controllers.forms import get_form_widgets
+from galaxy.web.controllers.library import get_authorized_libs
log = logging.getLogger( __name__ )
-
-# States for passing messages
-SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
class RequestsListGrid( grids.Grid ):
title = "Sequencing Requests"
model_class = model.Request
default_sort_key = "-create_time"
+ show_filter = model.Request.states.SUBMITTED
columns = [
grids.GridColumn( "Name", key="name",
- link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) )),
+ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ),
+ attach_popup=True ),
grids.GridColumn( "Description", key="desc"),
grids.GridColumn( "Sample(s)", method='number_of_samples',
link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ),
@@ -30,15 +31,18 @@
]
operations = [
-# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
-# grids.GridOperation( "Samples", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
-# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ),
-# grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
+ grids.GridOperation( "Submit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() and item.samples ) ),
+ grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
+ grids.GridOperation( "Delete", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ),
+ grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
]
standard_filters = [
+ grids.GridColumnFilter( model.Request.states.UNSUBMITTED,
+ args=dict( state=model.Request.states.UNSUBMITTED, deleted=False ) ),
grids.GridColumnFilter( model.Request.states.SUBMITTED,
args=dict( state=model.Request.states.SUBMITTED, deleted=False ) ),
grids.GridColumnFilter( model.Request.states.COMPLETE, args=dict( state=model.Request.states.COMPLETE, deleted=False ) ),
+ grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
grids.GridColumnFilter( "All", args=dict( deleted=False ) )
]
def get_user(self, trans, request):
@@ -48,9 +52,9 @@
def get_request_type(self, trans, request):
request_type = trans.app.model.RequestType.get(request.request_type_id)
return request_type.name
- def apply_default_filter( self, trans, query ):
- return query.filter(or_(self.model_class.state==self.model_class.states.SUBMITTED,
- self.model_class.state==self.model_class.states.COMPLETE))
+# def apply_default_filter( self, trans, query ):
+# return query.filter(or_(self.model_class.state==self.model_class.states.SUBMITTED,
+# self.model_class.state==self.model_class.states.COMPLETE))
def number_of_samples(self, trans, request):
return str(len(request.samples))
@@ -67,32 +71,277 @@
'''
List all request made by the current user
'''
- status = message = None
+ message = util.restore_text( kwargs.get( 'message', '' ) )
+ status = kwargs.get( 'status', 'done' )
self.request_grid.default_filter = dict(state=trans.app.model.Request.states.SUBMITTED,
deleted=False)
if 'operation' in kwargs:
operation = kwargs['operation'].lower()
if operation == "show_request":
id = trans.security.decode_id(kwargs['id'])
- return self.__show_request(trans, id)
-
+ return self.__show_request(trans, id, status, message)
+ elif operation == "submit":
+ id = trans.security.decode_id(kwargs['id'])
+ return self.__submit(trans, id)
+ elif operation == "edit":
+ id = trans.security.decode_id(kwargs['id'])
+ return self.__edit_request(trans, id)
+ elif operation == "delete":
+ id = trans.security.decode_id(kwargs['id'])
+ return self.__delete_request(trans, id)
+ elif operation == "undelete":
+ id = trans.security.decode_id(kwargs['id'])
+ return self.__undelete_request(trans, id)
if 'show_filter' in kwargs.keys():
if kwargs['show_filter'] == 'All':
- self.request_grid.default_filter = dict(deleted=False)
+ self.request_grid.default_filter = {}
+ elif kwargs['show_filter'] == 'Deleted':
+ self.request_grid.default_filter = dict(deleted=True)
else:
- self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
+ self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
+ self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.SUBMITTED)
# Render the list view
return self.request_grid( trans, template='/admin/requests/grid.mako', **kwargs )
- def __show_request(self, trans, id):
+ @web.expose
+ @web.require_admin
+ def edit(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ try:
+ request = trans.app.model.Request.get(int(params.get('request_id', None)))
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid request ID",
+ **kwd) )
+ if params.get('show', False) == 'True':
+ return self.__edit_request(trans, request.id, **kwd)
+ elif params.get('save_changes_request_button', False) == 'Save changes' \
+ or params.get('edit_samples_button', False) == 'Edit samples':
+ request_type = trans.app.model.RequestType.get(int(params.select_request_type))
+ if not util.restore_text(params.get('name', '')):
+ msg = 'Please enter the <b>Name</b> of the request'
+ kwd['messagetype'] = 'error'
+ kwd['msg'] = msg
+ kwd['show'] = 'True'
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='edit',
+ **kwd) )
+ request = self.__save_request(trans, request, **kwd)
+ msg = 'The changes made to the request named %s has been saved' % request.name
+ if params.get('save_changes_request_button', False) == 'Save changes':
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ message=msg ,
+ status='done') )
+ elif params.get('edit_samples_button', False) == 'Edit samples':
+ new_kwd = {}
+ new_kwd['request_id'] = request.id
+ new_kwd['edit_samples_button'] = 'Edit samples'
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='show_request',
+ msg=msg ,
+ messagetype='done',
+ **new_kwd) )
+ elif params.get('refresh', False) == 'true':
+ return self.__edit_request(trans, request.id, **kwd)
+ def __edit_request(self, trans, id, **kwd):
try:
request = trans.app.model.Request.get(id)
except:
- return trans.response.send_redirect( web.url_for( controller='requests',
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg) )
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ select_request_type = self.__select_request_type(trans, request.type.id)
+ # list of widgets to be rendered on the request form
+ widgets = []
+ if util.restore_text( params.get( 'name', '' ) ):
+ name = util.restore_text( params.get( 'name', '' ) )
+ else:
+ name = request.name
+ widgets.append(dict(label='Name',
+ widget=TextField('name', 40, name),
+ helptext='(Required)'))
+ if util.restore_text( params.get( 'desc', '' ) ):
+ desc = util.restore_text( params.get( 'desc', '' ) )
+ else:
+ desc = request.desc
+ widgets.append(dict(label='Description',
+ widget=TextField('desc', 40, desc),
+ helptext='(Optional)'))
+ # libraries selectbox
+ libui = self.__library_ui(trans, request.user, request, **kwd)
+ widgets = widgets + libui
+ widgets = widgets + get_form_widgets(trans, request.type.request_form, request.values.content, request.user, **kwd)
+ return trans.fill_template( '/admin/requests/edit_request.mako',
+ select_request_type=select_request_type,
+ request_type=request.type,
+ request=request,
+ widgets=widgets,
+ msg=msg,
+ messagetype=messagetype)
+ return self.__show_request_form(trans)
+ def __delete_request(self, trans, id):
+ try:
+ request = trans.app.model.Request.get(id)
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ # change request's submitted field
+ if not request.unsubmitted():
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message='This request cannot be deleted as it is already been submitted',
+ **kwd) )
+ request.deleted = True
+ request.flush()
+ kwd = {}
+ kwd['id'] = trans.security.encode_id(request.id)
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ show_filter=trans.app.model.Request.states.UNSUBMITTED,
+ status='done',
+ message='The request <b>%s</b> has been deleted.' % request.name,
+ **kwd) )
+ def __undelete_request(self, trans, id):
+ try:
+ request = trans.app.model.Request.get(id)
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ # change request's submitted field
+ request.deleted = False
+ request.flush()
+ kwd = {}
+ kwd['id'] = trans.security.encode_id(request.id)
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ show_filter=trans.app.model.Request.states.UNSUBMITTED,
+ status='done',
+ message='The request <b>%s</b> has been undeleted.' % request.name,
+ **kwd) )
+ def __submit(self, trans, id):
+ try:
+ request = trans.app.model.Request.get(id)
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ msg = self.__validate(trans, request)
+ if msg:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='edit',
+ messagetype = 'error',
+ msg=msg,
+ request_id=request.id,
+ show='True') )
+ # get the new state
+ new_state = request.type.states[0]
+ for s in request.samples:
+ event = trans.app.model.SampleEvent(s, new_state, 'Samples submitted to the system')
+ event.flush()
+ # change request's submitted field
+ request.state = request.states.SUBMITTED
+ request.flush()
+ kwd = {}
+ kwd['id'] = trans.security.encode_id(request.id)
+ kwd['status'] = 'done'
+ kwd['message'] = 'The request <b>%s</b> has been submitted.' % request.name
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ show_filter=trans.app.model.Request.states.SUBMITTED,
+ **kwd) )
+ @web.expose
+ @web.require_admin
+ def submit_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ try:
+ id = int(params.get('id', False))
+ request = trans.app.model.Request.get(id)
+ except:
+ msg = "Invalid request ID"
+ log.warn( msg )
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message=msg,
+ **kwd) )
+ msg = self.__validate(trans, request)
+ if msg:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='edit',
+ messagetype='error',
+ msg=msg,
+ request_id=request.id,
+ show='True') )
+ # get the new state
+ new_state = request.type.states[0]
+ for s in request.samples:
+ event = trans.app.model.SampleEvent(s, new_state, 'Samples submitted to the system')
+ event.flush()
+ # change request's submitted field
+ request.state = request.states.SUBMITTED
+ request.flush()
+ kwd['id'] = trans.security.encode_id(request.id)
+ kwd['status'] = 'done'
+ kwd['message'] = 'The request <b>%s</b> has been submitted.' % request.name
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ show_filter=trans.app.model.Request.states.SUBMITTED,
+ **kwd) )
+ def __copy_sample(self):
+ copy_list = SelectField('copy_sample')
+ copy_list.add_option('None', -1, selected=True)
+ for i, s in enumerate(self.current_samples):
+ copy_list.add_option(s[0], i)
+ return copy_list
+ def __update_samples(self, request, **kwd):
+ params = util.Params( kwd )
+ num_samples = len(self.current_samples)
+ self.current_samples = []
+ for s in request.samples:
+ self.current_samples.append([s.name, s.values.content])
+ for index in range(num_samples-len(request.samples)):
+ sample_index = index + len(request.samples)
+ sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
+ sample_values = []
+ for field_index in range(len(request.type.sample_form.fields)):
+ sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
+ self.current_samples.append([sample_name, sample_values])
+ def __show_request(self, trans, id, messagetype, msg):
+ try:
+ request = trans.app.model.Request.get(id)
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
status='error',
message="Invalid request ID",
**kwd) )
self.current_samples = []
+ self.edit_mode = False
for s in request.samples:
self.current_samples.append([s.name, s.values.content])
self.details_state = 'Show request details'
@@ -100,8 +349,163 @@
request=request,
request_details=self.request_details(trans, id),
current_samples = self.current_samples,
- details_state=self.details_state)
+ sample_copy=self.__copy_sample(),
+ details_state=self.details_state,
+ edit_mode=self.edit_mode,
+ msg=msg, messagetype=messagetype)
@web.expose
+ @web.require_admin
+ def show_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ try:
+ request = trans.app.model.Request.get(int(params.get('request_id', None)))
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid request ID",
+ **kwd) )
+ if params.get('import_samples_button', False) == 'Import samples':
+ try:
+ file_obj = params.get('file_data', '')
+ import csv
+ reader = csv.reader(file_obj.file)
+ for row in reader:
+ self.current_samples.append([row[0], row[1:]])
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=self.current_samples,
+ sample_copy=self.__copy_sample(),
+ details_state=self.details_state,
+ edit_mode=self.edit_mode)
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ operation='show_request',
+ id=trans.security.encode_id(request.id),
+ message='Error in importing samples from the given file.',
+ **kwd))
+ elif params.get('add_sample_button', False) == 'Add New':
+ # save the all (saved+unsaved) sample info in 'current_samples'
+ self.__update_samples(request, **kwd)
+ # add an empty or filled sample
+ # if the user has selected a sample no. to copy then copy the contents
+ # of the src sample to the new sample else an empty sample
+ src_sample_index = int(params.get( 'copy_sample', -1 ))
+ if src_sample_index == -1:
+ # empty sample
+ self.current_samples.append(['Sample_%i' % (len(self.current_samples)+1),['' for field in request.type.sample_form.fields]])
+ else:
+ self.current_samples.append([self.current_samples[src_sample_index][0]+'_%i' % (len(self.current_samples)+1),
+ [val for val in self.current_samples[src_sample_index][1]]])
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=self.current_samples,
+ sample_copy=self.__copy_sample(),
+ details_state=self.details_state,
+ edit_mode=self.edit_mode)
+ elif params.get('save_samples_button', False) == 'Save':
+ # update current_samples
+ self.__update_samples(request, **kwd)
+ # check for duplicate sample names
+ msg = ''
+ for index in range(len(self.current_samples)-len(request.samples)):
+ sample_index = index + len(request.samples)
+ sample_name = self.current_samples[sample_index][0]
+ if not sample_name.strip():
+ msg = 'Please enter the name of sample number %i' % sample_index
+ break
+ count = 0
+ for i in range(len(self.current_samples)):
+ if sample_name == self.current_samples[i][0]:
+ count = count + 1
+ if count > 1:
+ msg = "This request has <b>%i</b> samples with the name <b>%s</b>.\nSamples belonging to a request must have unique names." % (count, sample_name)
+ break
+ if msg:
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples = self.current_samples,
+ sample_copy=self.__copy_sample(), details_state=self.details_state,
+ messagetype='error', msg=msg)
+ # save all the new/unsaved samples entered by the user
+ if not self.edit_mode:
+ for index in range(len(self.current_samples)-len(request.samples)):
+ sample_index = index + len(request.samples)
+ sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
+ sample_values = []
+ for field_index in range(len(request.type.sample_form.fields)):
+ sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
+ form_values = trans.app.model.FormValues(request.type.sample_form, sample_values)
+ form_values.flush()
+ s = trans.app.model.Sample(sample_name, '', request, form_values)
+ s.flush()
+ else:
+ for index in range(len(self.current_samples)):
+ sample_index = index
+ sample_name = self.current_samples[sample_index][0]
+ new_sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
+ sample_values = []
+ for field_index in range(len(request.type.sample_form.fields)):
+ sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
+ sample = request.has_sample(sample_name)
+ if sample:
+ form_values = trans.app.model.FormValues.get(sample.values.id)
+ form_values.content = sample_values
+ form_values.flush()
+ sample.name = new_sample_name
+ sample.flush()
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ operation='show_request',
+ id=trans.security.encode_id(request.id)) )
+ elif params.get('edit_samples_button', False) == 'Edit samples':
+ self.edit_mode = True
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=self.current_samples,
+ sample_copy=self.__copy_sample(),
+ details_state=self.details_state,
+ edit_mode=self.edit_mode)
+ elif params.get('cancel_changes_button', False) == 'Cancel':
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ operation='show_request',
+ id=trans.security.encode_id(request.id)) )
+
+
+ @web.expose
+ @web.require_admin
+ def delete_sample(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ request = trans.app.model.Request.get(int(params.get('request_id', 0)))
+ sample_index = int(params.get('sample_id', 0))
+ sample_name = self.current_samples[sample_index][0]
+ s = request.has_sample(sample_name)
+ if s:
+ s.delete()
+ s.flush()
+ request.flush()
+ del self.current_samples[sample_index]
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples = self.current_samples,
+ sample_copy=self.__copy_sample(),
+ details_state=self.details_state,
+ edit_mode=self.edit_mode)
+
+ @web.expose
+ @web.require_admin
def toggle_request_details(self, trans, **kwd):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -128,24 +532,28 @@
# list of widgets to be rendered on the request form
request_details = []
# main details
+ request_details.append(dict(label='User',
+ value=str(request.user.email),
+ helptext=''))
request_details.append(dict(label='Description',
value=request.desc,
helptext=''))
request_details.append(dict(label='Type',
value=request.type.name,
helptext=''))
+ request_details.append(dict(label='State',
+ value=request.state,
+ helptext=''))
request_details.append(dict(label='Date created',
value=request.create_time,
helptext=''))
- request_details.append(dict(label='Date updated',
- value=request.create_time,
- helptext=''))
- request_details.append(dict(label='User',
- value=str(request.user.email),
- helptext=''))
# library associated
+ if request.library:
+ value=request.library.name
+ else:
+ value = None
request_details.append(dict(label='Data library',
- value=trans.app.model.Library.get(request.library_id).name,
+ value=value,
helptext='Data library where the resultant dataset will be stored'))
# form fields
for index, field in enumerate(request.type.request_form.fields):
@@ -167,15 +575,262 @@
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
return request_details
+
+ def __select_request_type(self, trans, rtid):
+ rt_ids = ['none']
+ for rt in trans.app.model.RequestType.query().all():
+ if not rt.deleted:
+ rt_ids.append(str(rt.id))
+ select_reqtype = SelectField('select_request_type',
+ refresh_on_change=True,
+ refresh_on_change_values=rt_ids[1:])
+ if rtid == 'none':
+ select_reqtype.add_option('Select one', 'none', selected=True)
+ else:
+ select_reqtype.add_option('Select one', 'none')
+ for rt in trans.app.model.RequestType.query().all():
+ if not rt.deleted:
+ if rtid == rt.id:
+ select_reqtype.add_option(rt.name, rt.id, selected=True)
+ else:
+ select_reqtype.add_option(rt.name, rt.id)
+ return select_reqtype
+ @web.expose
+ @web.require_admin
+ def new(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ if params.get('select_request_type', False) == 'True':
+ return trans.fill_template( '/admin/requests/new_request.mako',
+ select_request_type=self.__select_request_type(trans, 'none'),
+ widgets=[],
+ msg=msg,
+ messagetype=messagetype)
+ elif params.get('create', False) == 'True':
+ if params.get('create_request_button', False) == 'Save' \
+ or params.get('create_request_samples_button', False) == 'Add samples':
+ request_type = trans.app.model.RequestType.get(int(params.select_request_type))
+ if not util.restore_text(params.get('name', '')) \
+ or util.restore_text(params.get('select_user', '')) == unicode('none'):
+ msg = 'Please enter the <b>Name</b> of the request and the <b>user</b> on behalf of whom this request will be submitted before saving this request'
+ kwd['create'] = 'True'
+ kwd['messagetype'] = 'error'
+ kwd['msg'] = msg
+ kwd['create_request_button'] = None
+ kwd['create_request_samples_button'] = None
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='new',
+ **kwd) )
+ request = self.__save_request(trans, None, **kwd)
+ msg = 'The new request named %s has been created' % request.name
+ if params.get('create_request_button', False) == 'Save':
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ show_filter=trans.app.model.Request.states.UNSUBMITTED,
+ message=msg ,
+ status='done') )
+ elif params.get('create_request_samples_button', False) == 'Add samples':
+ new_kwd = {}
+ new_kwd['id'] = trans.security.encode_id(request.id)
+ new_kwd['operation'] = 'show_request'
+ new_kwd['add_sample'] = True
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ message=msg ,
+ status='done',
+ **new_kwd) )
+ else:
+ return self.__show_request_form(trans, **kwd)
+ elif params.get('refresh', False) == 'true':
+ return self.__show_request_form(trans, **kwd)
+ def __show_request_form(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ try:
+ request_type = trans.app.model.RequestType.get(int(params.select_request_type))
+ except:
+ return trans.fill_template( '/admin/requests/new_request.mako',
+ select_request_type=self.__select_request_type(trans, 'none'),
+ widgets=[],
+ msg=msg,
+ messagetype=messagetype)
+ form_values = None
+ select_request_type = self.__select_request_type(trans, request_type.id)
+ # user
+ user_id = params.get( 'select_user', 'none' )
+ try:
+ user = trans.app.model.User.get(int(user_id))
+ except:
+ user = None
+ # list of widgets to be rendered on the request form
+ widgets = []
+ widgets.append(dict(label='Select user',
+ widget=self.__select_user(trans, user_id),
+ helptext='The request would be submitted on behalf of this user (Required)'))
+ widgets.append(dict(label='Name',
+ widget=TextField('name', 40,
+ util.restore_text( params.get( 'name', '' ) )),
+ helptext='(Required)'))
+ widgets.append(dict(label='Description',
+ widget=TextField('desc', 40,
+ util.restore_text( params.get( 'desc', '' ) )),
+ helptext='(Optional)'))
+ # libraries selectbox
+ libui = self.__library_ui(trans, user, **kwd)
+ widgets = widgets + libui
+ widgets = widgets + get_form_widgets(trans, request_type.request_form, contents=[], user=user, **kwd)
+ return trans.fill_template( '/admin/requests/new_request.mako',
+ select_request_type=select_request_type,
+ request_type=request_type,
+ widgets=widgets,
+ msg=msg,
+ messagetype=messagetype)
+ def __select_user(self, trans, userid):
+ user_ids = ['none']
+ for user in trans.app.model.User.query().all():
+ if not user.deleted:
+ user_ids.append(str(user.id))
+ select_user = SelectField('select_user',
+ refresh_on_change=True,
+ refresh_on_change_values=user_ids[1:])
+ if userid == 'none':
+ select_user.add_option('Select one', 'none', selected=True)
+ else:
+ select_user.add_option('Select one', 'none')
+ for user in trans.app.model.User.query().all():
+ if not user.deleted:
+ if userid == str(user.id):
+ select_user.add_option(user.email, user.id, selected=True)
+ else:
+ select_user.add_option(user.email, user.id)
+ return select_user
+
+ def __library_ui(self, trans, user, request=None, **kwd):
+ params = util.Params( kwd )
+ lib_id = params.get( 'library_id', 'none' )
+ if not user:
+ libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all()
+ else:
+ libraries = get_authorized_libs(trans, user)
+ lib_list = SelectField('library_id', refresh_on_change=True,
+ refresh_on_change_values=['new'])
+ if request and lib_id == 'none':
+ if request.library:
+ lib_id = str(request.library.id)
+ if lib_id == 'none':
+ lib_list.add_option('Select one', 'none', selected=True)
+ else:
+ lib_list.add_option('Select one', 'none')
+ for lib in libraries:
+ if str(lib.id) == lib_id:
+ lib_list.add_option(lib.name, lib.id, selected=True)
+ else:
+ lib_list.add_option(lib.name, lib.id)
+ if lib_id == 'new':
+ lib_list.add_option('Create a new data library', 'new', selected=True)
+ else:
+ lib_list.add_option('Create a new data library', 'new')
+ widget = dict(label='Data library',
+ widget=lib_list,
+ helptext='Data library where the resultant dataset will be stored.')
+ if lib_id == 'new':
+ new_lib = dict(label='Create a new Library',
+ widget=TextField('new_library_name', 40,
+ util.restore_text( params.get( 'new_library_name', '' ) )),
+ helptext='Enter a library name here to request a new library')
+ return [widget, new_lib]
+ else:
+ return [widget]
+ def __validate(self, trans, request):
+ '''
+ Validates the request entered by the user
+ '''
+ empty_fields = []
+# if not request.library:
+# empty_fields.append('Library')
+ # check rest of the fields of the form
+ for index, field in enumerate(request.type.request_form.fields):
+ if field['required'] == 'required' and request.values.content[index] in ['', None]:
+ empty_fields.append(field['label'])
+ if empty_fields:
+ msg = 'Fill the following fields of the request <b>%s</b> before submitting<br/>' % request.name
+ for ef in empty_fields:
+ msg = msg + '<b>' +ef + '</b><br/>'
+ return msg
+ return None
+ def __save_request(self, trans, request=None, **kwd):
+ '''
+ This method saves a new request if request_id is None.
+ '''
+ params = util.Params( kwd )
+ request_type = trans.app.model.RequestType.get(int(params.select_request_type))
+ if request:
+ user = request.user
+ else:
+ user = trans.app.model.User.get(int(params.get('select_user', '')))
+ name = util.restore_text(params.get('name', ''))
+ desc = util.restore_text(params.get('desc', ''))
+ # library
+ try:
+ library = trans.app.model.Library.get(int(params.get('library_id', None)))
+ except:
+ library = None
+ # fields
+ values = []
+ for index, field in enumerate(request_type.request_form.fields):
+ if field['type'] == 'AddressField':
+ value = util.restore_text(params.get('field_%i' % index, ''))
+ if value == 'new':
+ # save this new address in the list of this user's addresses
+ user_address = trans.app.model.UserAddress( user=user )
+ user_address.desc = util.restore_text(params.get('field_%i_short_desc' % index, ''))
+ user_address.name = util.restore_text(params.get('field_%i_name' % index, ''))
+ user_address.institution = util.restore_text(params.get('field_%i_institution' % index, ''))
+ user_address.address = util.restore_text(params.get('field_%i_address1' % index, ''))+' '+util.restore_text(params.get('field_%i_address2' % index, ''))
+ user_address.city = util.restore_text(params.get('field_%i_city' % index, ''))
+ user_address.state = util.restore_text(params.get('field_%i_state' % index, ''))
+ user_address.postal_code = util.restore_text(params.get('field_%i_postal_code' % index, ''))
+ user_address.country = util.restore_text(params.get('field_%i_country' % index, ''))
+ user_address.phone = util.restore_text(params.get('field_%i_phone' % index, ''))
+ user_address.flush()
+ trans.user.refresh()
+ values.append(int(user_address.id))
+ elif value == unicode('none'):
+ values.append('')
+ else:
+ values.append(int(value))
+ else:
+ values.append(util.restore_text(params.get('field_%i' % index, '')))
+ form_values = trans.app.model.FormValues(request_type.request_form, values)
+ form_values.flush()
+ if not request:
+ request = trans.app.model.Request(name, desc, request_type,
+ user, form_values,
+ library=library,
+ state=trans.app.model.Request.states.UNSUBMITTED)
+ request.flush()
+ else:
+ request.name = name
+ request.desc = desc
+ request.type = request_type
+ request.user = user
+ request.values = form_values
+ request.library = library
+ request.flush()
+ return request
@web.expose
@web.require_admin
def bar_codes(self, trans, **kwd):
params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
request_id = params.get( 'request_id', None )
if request_id:
request = trans.app.model.Request.get( int( request_id ))
if not request:
- return trans.response.send_redirect( web.url_for( controller='requests',
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
status='error',
message="Invalid request ID",
@@ -191,7 +846,9 @@
bc))
return trans.fill_template( '/admin/samples/bar_codes.mako',
samples_list=[s for s in request.samples],
- user=request.user, request=request, widgets=widgets)
+ user=request.user, request=request, widgets=widgets,
+ messagetype=messagetype,
+ msg=msg)
@web.expose
@web.require_admin
def save_bar_codes(self, trans, **kwd):
@@ -199,7 +856,7 @@
try:
request = trans.app.model.Request.get(int(params.get('request_id', None)))
except:
- return trans.response.send_redirect( web.url_for( controller='requests',
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
status='error',
message="Invalid request ID",
@@ -255,9 +912,10 @@
sample.bar_code = bar_code
sample.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='list',
- operation='show_request',
- id=trans.security.encode_id(request.id)) )
+ action='bar_codes',
+ request_id=request.id,
+ msg='Bar codes has been saved for this request',
+ messagetype='done'))
def __set_request_state(self, request):
# check if all the samples of the current request are in the final state
complete = True
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/tool_runner.py
--- a/lib/galaxy/web/controllers/tool_runner.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/tool_runner.py Sat Aug 22 23:20:09 2009 -0400
@@ -82,7 +82,7 @@
job = assoc.job
break
if not job:
- raise Exception("Failed to get job information for dataset hid %d" % hid)
+ raise Exception("Failed to get job information for dataset hid %d" % data.hid)
# Get the tool object
tool_id = job.tool_id
try:
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/controllers/user.py Sat Aug 22 23:20:09 2009 -0400
@@ -229,6 +229,8 @@
def manage_addresses(self, trans, **kwd):
if trans.user:
params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) )
if show_filter == 'All':
addresses = [address for address in trans.user.addresses]
@@ -238,7 +240,9 @@
addresses = [address for address in trans.user.addresses if not address.deleted]
return trans.fill_template( 'user/address.mako',
addresses=addresses,
- show_filter=show_filter)
+ show_filter=show_filter,
+ msg=msg,
+ messagetype=messagetype)
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." )
diff -r fbad627b45ac -r e6dda627e6b0 lib/galaxy/web/framework/base.py
--- a/lib/galaxy/web/framework/base.py Sat Aug 22 23:18:47 2009 -0400
+++ b/lib/galaxy/web/framework/base.py Sat Aug 22 23:20:09 2009 -0400
@@ -216,11 +216,18 @@
# tempfiles. Necessary for externalizing the upload tool. It's a little hacky
# but for performance reasons it's way better to use Paste's tempfile than to
# create a new one and copy.
-import cgi
+import cgi, tempfile
class FieldStorage( cgi.FieldStorage ):
def make_file(self, binary=None):
- import tempfile
return tempfile.NamedTemporaryFile()
+ def read_lines(self):
+ # Always make a new file
+ self.file = self.make_file()
+ self.__file = None
+ if self.outerboundary:
+ self.read_lines_to_outerboundary()
+ else:
+ self.read_lines_to_eof()
cgi.FieldStorage = FieldStorage
class Request( webob.Request ):
diff -r fbad627b45ac -r e6dda627e6b0 static/welcome.html
--- a/static/welcome.html Sat Aug 22 23:18:47 2009 -0400
+++ b/static/welcome.html Sat Aug 22 23:20:09 2009 -0400
@@ -71,7 +71,7 @@
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td>
- <a href="javascript:parent.show_in_overlay({url:'http://screencast.g2.bx.psu.edu/galaxy/quickie1_TabSeq/flow.html',width:640,height:500,scroll:'no'})">
+ <a href="javascript:parent.show_in_overlay({url:'http://screencast.g2.bx.psu.edu/galaxy/quickie1_TabSeq/quickie1_TabSeq.flv',width:640,height:500,scroll:'no'})">
<div class="quickie">
<img src="images/qk/quickie1_small.png" border="0">
</div>
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/forms/edit_form.mako
--- a/templates/admin/forms/edit_form.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/forms/edit_form.mako Sat Aug 22 23:20:09 2009 -0400
@@ -70,7 +70,7 @@
</%def>
<div class="toolForm">
- <div class="toolFormTitle">Edit form definition '${form.name}'</div>
+ <div class="toolFormTitle">Edit form definition "${form.name}"</div>
<form id="edit_form" name="edit_form" action="${h.url_for( controller='forms', action='edit', form_id=form.id, num_fields=len(form.fields) )}" method="post" >
%for label, input in form_details:
<div class="form-row">
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/requests/add_states.mako
--- a/templates/admin/requests/add_states.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/requests/add_states.mako Sat Aug 22 23:20:09 2009 -0400
@@ -12,9 +12,9 @@
%for element_count in range( num_states ):
<div class="form-row">
<label>${1+element_count}) State name:</label>
- <input type="text" name="new_element_name_${element_count}" value="" size="40"/>
+ <input type="text" name="state_name_${element_count}" value="" size="40"/>
<label>State help text (optional):</label>
- <input type="text" name="new_element_description_${element_count}" value="" size="40"/>
+ <input type="text" name="state_desc_${element_count}" value="" size="40"/>
</div>
<div style="clear: both"></div>
%endfor
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/requests/edit_request.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/admin/requests/edit_request.mako Sat Aug 22 23:20:09 2009 -0400
@@ -0,0 +1,88 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<script type="text/javascript">
+$( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_request" ).submit();
+ }
+ });
+});
+</script>
+
+<br/>
+<br/>
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='list', operation='show_request', id=trans.security.encode_id(request.id) )}">
+ <span>Browse this request</span></a>
+ </li>
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='list')}">
+ <span>Browse requests</span></a>
+ </li>
+</ul>
+
+<div class="toolForm">
+ <div class="toolFormTitle">Edit request "${request.name}" from ${request.user.email}</div>
+ %if len(select_request_type.options) == 1:
+ There are no request types created for a new request.
+ %else:
+ <div class="toolFormBody">
+ <form name="edit_request" id="edit_request" action="${h.url_for( controller='requests_admin', action='edit', request_id=request.id)}" method="post" >
+ <div class="form-row">
+ <label>
+ Select Request Type:
+ </label>
+ ${select_request_type.get_html()}
+ </div>
+
+ %if select_request_type.get_selected() != ('Select one', 'none'):
+ %for i, field in enumerate(widgets):
+ <div class="form-row">
+ <label>${field['label']}</label>
+ ${field['widget'].get_html()}
+ %if field['label'] == 'Library' and new_library:
+ ${new_library.get_html()}
+ %endif
+ <div class="toolParamHelp" style="clear: both;">
+ ${field['helptext']}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="hidden" name="refresh" value="true" size="40"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="save_changes_request_button" value="Save changes"/>
+ ##<input type="submit" name="edit_samples_button" value="Edit samples"/>
+ </div>
+ %endif
+ </form>
+ </div>
+</div>
+%endif
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/requests/grid.mako
--- a/templates/admin/requests/grid.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/requests/grid.mako Sat Aug 22 23:20:09 2009 -0400
@@ -76,29 +76,28 @@
<div class="grid-header">
<h2>${grid.title}</h2>
- ##%if len(query.all()):
+ %if len(trans.app.model.Request.query().all()):
##<span class="title">Filter:</span>
%for i, filter in enumerate( grid.standard_filters ):
%if i > 0:
<span>|</span>
%endif
- %if 'state' in grid.default_filter:
- %if grid.default_filter['state'] == filter.label:
- <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span>
- %else:
- <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}">${filter.label}</a></span>
- %endif
+ %if grid.show_filter == filter.label:
+ <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span>
%else:
- %if filter.label == 'All':
- <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span>
- %else:
- <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}">${filter.label}</a></span>
- %endif
+ <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}">${filter.label}</a></span>
%endif
%endfor
- ##%endif
+ %endif
</div>
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='new', select_request_type=True )}">
+ <img src="${h.url_for('/static/images/silk/add.png')}" />
+ <span>Create a new request</span></a>
+ </li>
+</ul>
%if not len(query.all()):
There are no requests.
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/requests/new_request.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/admin/requests/new_request.mako Sat Aug 22 23:20:09 2009 -0400
@@ -0,0 +1,84 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<script type="text/javascript">
+$( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#new_request" ).submit();
+ }
+ });
+});
+</script>
+
+<br/>
+<br/>
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='list')}">
+ <span>Browse requests</span></a>
+ </li>
+</ul>
+
+<div class="toolForm">
+ <div class="toolFormTitle">Add a new request</div>
+ %if len(select_request_type.options) == 1:
+ There are no request types created for a new request.
+ %else:
+ <div class="toolFormBody">
+ <form name="new_request" id="new_request" action="${h.url_for( controller='requests_admin', action='new', create=True )}" method="post" >
+ <div class="form-row">
+ <label>
+ Select Request Type
+ </label>
+ ${select_request_type.get_html()}
+ </div>
+
+ %if select_request_type.get_selected() != ('Select one', 'none'):
+ %for i, field in enumerate(widgets):
+ <div class="form-row">
+ <label>${field['label']}</label>
+ ${field['widget'].get_html()}
+ %if field['label'] == 'Library' and new_library:
+ ${new_library.get_html()}
+ %endif
+ <div class="toolParamHelp" style="clear: both;">
+ ${field['helptext']}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="hidden" name="refresh" value="true" size="40"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="create_request_button" value="Save"/>
+ <input type="submit" name="create_request_samples_button" value="Add samples"/>
+ </div>
+ %endif
+ </form>
+ </div>
+</div>
+%endif
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/requests/show_request.mako
--- a/templates/admin/requests/show_request.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/requests/show_request.mako Sat Aug 22 23:20:09 2009 -0400
@@ -12,18 +12,49 @@
</div>
<ul class="manage-table-actions">
- <li>
- <a class="action-button" href="${h.url_for( controller='requests_admin', action='bar_codes', request_id=request.id)}">
- <span>Bar codes</span></a>
- </li>
+ %if request.unsubmitted() and request.samples:
+ <li>
+ <a class="action-button" confirm="More samples cannot be added to this request once it is submitted. Click OK to submit." href="${h.url_for( controller='requests_admin', action='submit_request', id=request.id)}">
+ <span>Submit request</span></a>
+ </li>
+ %endif
+ %if request.submitted() and request.samples:
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='bar_codes', request_id=request.id)}">
+ <span>Bar codes</span></a>
+ </li>
+ %endif
</ul>
+
+<%def name="render_sample_form( index, sample_name, sample_values )">
+ <td>
+ <input type="text" name=sample_${index}_name value="${sample_name}" size="10"/>
+ <div class="toolParamHelp" style="clear: both;">
+ <i>${' (required)' }</i>
+ </div>
+ </td>
+ <td>
+ </td>
+ %for field_index, field in enumerate(request.type.sample_form.fields):
+ <td>
+ <input type="text" name=sample_${index}_field_${field_index} value="${sample_values[field_index]}" size="7"/>
+ <div class="toolParamHelp" style="clear: both;">
+ <i>${'('+field['required']+')' }</i>
+ </div>
+ </td>
+ %endfor
+</%def>
<%def name="render_sample( index, sample )">
<td>
${sample.name}
</td>
<td>
- <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
+ %if sample.request.unsubmitted():
+ Unsubmitted
+ %else:
+ <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
+ %endif
</td>
%for field_index, field in enumerate(request.type.sample_form.fields):
<td>
@@ -34,10 +65,10 @@
%endif
</td>
%endfor
+
</%def>
<div class="toolForm">
- ##<div class="toolFormTitle">Request Details: '${request_details[0]['value']}'</div>
<div class="form-row">
<a href="${h.url_for( controller='requests_admin', action='toggle_request_details', request_id=request.id )}">${details_state}</a>
</div>
@@ -57,13 +88,21 @@
</div>
<div style="clear: both"></div>
%endfor
+ <div class="form-row">
+ <ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='edit', show=True, request_id=request.id)}">
+ <span>Edit request details</span></a>
+ </li>
+ </ul>
+ </div>
%endif
</div>
</div>
<div class="toolForm">
##<div class="toolFormTitle">Samples (${len(request.samples)})</div>
- <form id="edit_form" name="edit_form" action="${h.url_for( controller='requests', action='show_request', request_id=request.id )}" method="post" >
+ <form id="edit_form" name="edit_form" action="${h.url_for( controller='requests_admin', action='show_request' )}" enctype="multipart/form-data" method="post" >
<div class="form-row">
%if current_samples:
<table class="grid">
@@ -80,22 +119,88 @@
</div>
</th>
%endfor
+ <th></th>
</tr>
<thead>
<tbody>
+ <%
+ request.refresh()
+ %>
%for sample_index, sample in enumerate(current_samples):
- <tr>
- <td>${sample_index+1}</td>
- ${render_sample( sample_index, request.samples[sample_index] )}
- </tr>
+ %if edit_mode:
+ <tr>
+ <td>${sample_index+1}</td>
+ ${render_sample_form( sample_index, sample[0], sample[1])}
+ </tr>
+ %else:
+ <tr>
+ <td>${sample_index+1}</td>
+ %if sample_index in range(len(request.samples)):
+ ${render_sample( sample_index, request.samples[sample_index] )}
+ %else:
+ ${render_sample_form( sample_index, sample[0], sample[1])}
+ %endif
+ <td>
+ %if request.unsubmitted():
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='delete_sample', request_id=request.id, sample_id=sample_index)}">
+ <img src="${h.url_for('/static/images/delete_icon.png')}" />
+ <span></span></a>
+ %endif
+ </td>
+ </tr>
+ %endif
%endfor
</tbody>
</table>
%else:
<label>There are no samples.</label>
%endif
-
</div>
- ##</div>
+ %if not edit_mode:
+ <table class="grid">
+ <tbody>
+ <tr>
+ <div class="form-row">
+ <td>
+ %if current_samples and not request.complete():
+ <input type="submit" name="edit_samples_button" value="Edit samples"/>
+ %endif
+ </td>
+ %if request.unsubmitted():
+ <td>
+ <label>Import from csv file</label>
+ <input type="file" name="file_data" />
+ <input type="submit" name="import_samples_button" value="Import samples"/>
+ </td>
+ <td>
+ %if current_samples:
+ <label>Copy from sample</label>
+ ${sample_copy.get_html()}
+ %endif
+ <input type="submit" name="add_sample_button" value="Add New"/>
+ </td>
+ %endif
+ </div>
+ </tr>
+ </tbody>
+ </table>
+ %endif
+ %if request.samples or current_samples:
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="hidden" name="refresh" value="true" size="40"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ %if edit_mode:
+ <input type="submit" name="save_samples_button" value="Save"/>
+ <input type="submit" name="cancel_changes_button" value="Cancel"/>
+ %elif request.unsubmitted():
+ <input type="submit" name="save_samples_button" value="Save"/>
+ %endif
+ </div>
+ %endif
+ <input type="hidden" name="request_id" value="${request.id}" />
</form>
</div>
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/samples/bar_codes.mako
--- a/templates/admin/samples/bar_codes.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/samples/bar_codes.mako Sat Aug 22 23:20:09 2009 -0400
@@ -40,7 +40,7 @@
</tbody>
</table>
<div class="form-row">
- <input type="submit" name="save_new_sample_type" value="Save"/>
+ <input type="submit" name="save_bar_codes" value="Save"/>
</div>
</form>
</div>
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 templates/admin/samples/events.mako
--- a/templates/admin/samples/events.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/admin/samples/events.mako Sat Aug 22 23:20:09 2009 -0400
@@ -56,7 +56,7 @@
</div>
%endfor
<div class="form-row">
- <input type="submit" name="add_event" value="Save"/>
+ <input type="submit" name="add_event_button" value="Save"/>
</div>
</form>
</div>
diff -r fbad627b45ac -r e6dda627e6b0 templates/base_panels.mako
--- a/templates/base_panels.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/base_panels.mako Sat Aug 22 23:20:09 2009 -0400
@@ -138,7 +138,7 @@
${tab( "libraries", "Data Libraries", h.url_for( controller='library', action='index' ))}
- %if trans.request_types():
+ %if trans.user and trans.request_types():
<td class="tab">
<a>Lab</a>
<div class="submenu">
diff -r fbad627b45ac -r e6dda627e6b0 templates/requests/grid.mako
--- a/templates/requests/grid.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/requests/grid.mako Sat Aug 22 23:20:09 2009 -0400
@@ -76,7 +76,7 @@
<div class="grid-header">
<h2>${grid.title}</h2>
- ##%if len(query.all()):
+ %if len(trans.user.requests):
##<span class="title">Filter:</span>
%for i, filter in enumerate( grid.standard_filters ):
%if i > 0:
@@ -88,17 +88,16 @@
<span class="filter"><a href="${h.url_for( controller='requests', action='list', show_filter=filter.label )}">${filter.label}</a></span>
%endif
%endfor
- ##%endif
+ %endif
</div>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='requests', action='new', select_request_type=True )}">
<img src="${h.url_for('/static/images/silk/add.png')}" />
- <span>New request</span></a>
+ <span>Create a new request</span></a>
</li>
</ul>
-
%if not len(query.all()):
There are no request(s).
@@ -215,4 +214,4 @@
</tfoot>
</table>
</form>
-%endif
\ No newline at end of file
+%endif
diff -r fbad627b45ac -r e6dda627e6b0 templates/requests/show_request.mako
--- a/templates/requests/show_request.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/requests/show_request.mako Sat Aug 22 23:20:09 2009 -0400
@@ -68,7 +68,6 @@
</%def>
<div class="toolForm">
- ##<div class="toolFormTitle">Request Details: '${request_details[0]['value']}'</div>
<div class="form-row">
<a href="${h.url_for( controller='requests', action='toggle_request_details', request_id=request.id )}">${details_state}</a>
</div>
@@ -217,7 +216,6 @@
%endif
</div>
%endif
- ##</div>
- <input type="hidden" name="request_id" value="${request.id}" />
+ <input type="hidden" name="request_id" value="${request.id}" />
</form>
</div>
diff -r fbad627b45ac -r e6dda627e6b0 templates/user/address.mako
--- a/templates/user/address.mako Sat Aug 22 23:18:47 2009 -0400
+++ b/templates/user/address.mako Sat Aug 22 23:20:09 2009 -0400
@@ -33,51 +33,48 @@
</div>
-
-<div class="toolForm">
- ##<div class="toolFormTitle">Addresses</div>
- <div class="toolFormBody">
- <% trans.user.refresh() %>
- %if not trans.user.addresses:
- <label>There are no addresses</label>
- %else:
- <table class="grid">
- <tbody>
- %for index, address in enumerate(addresses):
- <tr class="libraryRow libraryOrFolderRow" id="libraryRow">
-
- <td>
- <div class="form-row">
- <label>${address.desc}</label>
- ${address.display()}
- </div>
- <div class="form-row">
- <ul class="manage-table-actions">
- <li>
- %if not address.deleted:
- <a class="action-button" href="${h.url_for( controller='user', action='edit_address', address_id=address.id,
- short_desc=address.desc,
- name=address.name, institution=address.institution,
- address1=address.address, city=address.city,
- state=address.state, postal_code=address.postal_code,
- country=address.country, phone=address.phone)}">
- <span>Edit</span></a>
- <a class="action-button" href="${h.url_for( controller='user', action='delete_address', address_id=address.id)}">
- <span>Delete address</span></a>
- %else:
- <a class="action-button" href="${h.url_for( controller='user', action='undelete_address', address_id=address.id)}">
- <span>Undelete address</span></a>
- %endif
-
- </li>
- </ul>
- </div>
- </td>
- </tr>
- %endfor
- </tbody>
- </table>
- %endif
+%if not addresses:
+ <label>There are no addresses</label>
+%else:
+ <div class="toolForm">
+ <div class="toolFormBody">
+ <% trans.user.refresh() %>
+ <table class="grid">
+ <tbody>
+ %for index, address in enumerate(addresses):
+ <tr class="libraryRow libraryOrFolderRow" id="libraryRow">
+ <td>
+ <div class="form-row">
+ <label>${address.desc}</label>
+ ${address.display()}
+ </div>
+ <div class="form-row">
+ <ul class="manage-table-actions">
+ <li>
+ %if not address.deleted:
+ <a class="action-button" href="${h.url_for( controller='user', action='edit_address', address_id=address.id,
+ short_desc=address.desc,
+ name=address.name, institution=address.institution,
+ address1=address.address, city=address.city,
+ state=address.state, postal_code=address.postal_code,
+ country=address.country, phone=address.phone)}">
+ <span>Edit</span></a>
+ <a class="action-button" href="${h.url_for( controller='user', action='delete_address', address_id=address.id)}">
+ <span>Delete</span></a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='user', action='undelete_address', address_id=address.id)}">
+ <span>Undelete</span></a>
+ %endif
+
+ </li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </tbody>
+ </table>
+ %endif
+ </div>
</div>
-</div>
%endif
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Sat Aug 22 23:18:47 2009 -0400
+++ b/test/base/twilltestcase.py Sat Aug 22 23:20:09 2009 -0400
@@ -972,7 +972,7 @@
self.home()
# Form stuff
- def create_form( self, name='Form One', description='This is Form One', num_fields=1 ):
+ def create_form( self, name='Form One', desc='This is Form One', num_fields=1 ):
"""
Create a new form definition. Testing framework is still limited to only testing
one instance for each repeat. This has to do with the 'flat' nature of defining
@@ -988,7 +988,7 @@
self.visit_url( "%s/forms/new" % self.url )
self.check_page_for_string( 'Create a new form definition' )
tc.fv( "1", "name", name ) # form field 1 is the field named name...
- tc.fv( "1", "description", description ) # form field 1 is the field named name...
+ tc.fv( "1", "description", desc ) # form field 1 is the field named name...
tc.submit( "create_form_button" )
for index in range( num_fields ):
field_name = 'field_name_%i' % index
@@ -1001,7 +1001,140 @@
check_str = "The form '%s' has been updated with the changes." % name
self.check_page_for_string( check_str )
self.home()
-
+ def edit_form( self, form_id, form_name, new_form_name="Form One's Name (Renamed)", new_form_desc="This is Form One's description (Re-described)"):
+ """
+ Edit form details; name & description
+ """
+ self.home()
+ self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.check_page_for_string( 'Edit form definition "%s"' % form_name )
+ tc.fv( "1", "name", new_form_name )
+ tc.fv( "1", "description", new_form_desc )
+ tc.submit( "save_changes_button" )
+ self.check_page_for_string( "The form '%s' has been updated with the changes." % new_form_name )
+ self.home()
+ def form_add_field( self, form_id, form_name, field_index, fields):
+ """
+ Add a new fields to the form definition
+ """
+ self.home()
+ self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.check_page_for_string( 'Edit form definition "%s"' % form_name)
+ for i, field in enumerate(fields):
+ index = i+field_index
+ tc.submit( "add_field_button" )
+ tc.fv( "1", "field_name_%i" % index, field['name'] )
+ tc.fv( "1", "field_helptext_%i" % index, field['desc'] )
+ tc.fv( "1", "field_type_%i" % index, field['type'] )
+ tc.fv( "1", "field_required_%i" % index, field['required'] )
+# if field['type'] == 'SelectField':
+# for option_index, option in enumerate(field['selectlist']):
+# self.visit_url( "%s/forms/edit?select_box_options=add&form_id=%i&field_index=%i" % \
+# (self.url, form_id, index))
+# #data = self.last_page()
+# #file( "rc.html", 'wb' ).write(data)
+# tc.fv( "1", "field_%i_option_%i" % (index, option_index), option )
+ tc.submit( "save_changes_button" )
+ check_str = "The form '%s' has been updated with the changes." % form_name
+ self.check_page_for_string( check_str )
+ self.home()
+ def form_remove_field( self, form_id, form_name, field_name):
+ """
+ Remove a field from the form definition
+ """
+ self.home()
+ self.visit_url( "%s/forms/edit?form_id=%i&show_form=True" % (self.url, form_id) )
+ self.check_page_for_string( 'Edit form definition "%s"' % form_name)
+ tc.submit( "remove_button" )
+ tc.submit( "save_changes_button" )
+ check_str = "The form '%s' has been updated with the changes." % form_name
+ self.check_page_for_string( check_str )
+ self.home()
+ # Requests stuff
+ def create_request_type( self, name, desc, request_form_id, sample_form_id, states ):
+ self.home()
+ self.visit_url( "%s/admin/request_type?create=True" % self.url )
+ self.check_page_for_string( 'Create a new request type' )
+ tc.fv( "1", "name", name )
+ tc.fv( "1", "description", desc )
+ tc.fv( "1", "request_form_id", request_form_id )
+ tc.fv( "1", "sample_form_id", sample_form_id )
+ tc.fv( "1", "num_states", str( len( states ) ) )
+ tc.submit( "define_states_button" )
+ self.check_page_for_string( "Create %i states for the '%s' request type" % ( len(states), name ))
+ for index, state in enumerate(states):
+ tc.fv("1", "state_name_%i" % index, state[0])
+ tc.fv("1", "state_desc_%i" % index, state[1])
+ tc.submit( "save_request_type" )
+ self.check_page_for_string( "Request type <b>%s</b> has been created" % name )
+ def create_request( self, request_type_id, name, desc, library_id, fields ):
+ self.home()
+ self.visit_url( "%s/requests/new?create=True&select_request_type=%i" % (self.url, request_type_id) )
+ self.check_page_for_string( 'Add a new request' )
+ tc.fv( "1", "name", name )
+ tc.fv( "1", "desc", desc )
+ tc.fv( "1", "library_id", str(library_id) )
+ for index, field_value in enumerate(fields):
+ tc.fv( "1", "field_%i" % index, field_value )
+ tc.submit( "create_request_button" )
+ def create_request_admin( self, request_type_id, user_id, name, desc, library_id, fields ):
+ self.home()
+ self.visit_url( "%s/requests_admin/new?create=True&select_request_type=%i" % (self.url, request_type_id) )
+ self.check_page_for_string( 'Add a new request' )
+ tc.fv( "1", "select_user", str(user_id) )
+ tc.fv( "1", "name", name )
+ tc.fv( "1", "desc", desc )
+ tc.fv( "1", "library_id", str(library_id) )
+ for index, field_value in enumerate(fields):
+ tc.fv( "1", "field_%i" % index, field_value )
+ tc.submit( "create_request_button" )
+ def edit_request( self, request_id, name, new_name, new_desc, new_library_id, new_fields):
+ self.home()
+ self.visit_url( "%s/requests/edit?request_id=%i&show=True" % (self.url, request_id) )
+ self.check_page_for_string( 'Edit request "%s"' % name )
+ tc.fv( "1", "name", new_name )
+ tc.fv( "1", "desc", new_desc )
+ tc.fv( "1", "library_id", str(new_library_id) )
+ for index, field_value in enumerate(new_fields):
+ tc.fv( "1", "field_%i" % index, field_value )
+ tc.submit( "save_changes_request_button" )
+ def add_samples( self, request_id, request_name, samples ):
+ self.home()
+ self.visit_url( "%s/requests/list?sort=-create_time&operation=show_request&id=%s" % ( self.url, self.security.encode_id( request_id ) ))
+ self.check_page_for_string( 'Sequencing Request "%s"' % request_name )
+ for sample_index, sample in enumerate(samples):
+ tc.submit( "add_sample_button" )
+ sample_name, fields = sample
+ tc.fv( "1", "sample_%i_name" % sample_index, sample_name )
+ for field_index, field_value in enumerate(fields):
+ tc.fv( "1", "sample_%i_field_%i" % ( sample_index, field_index ), field_value )
+ tc.submit( "save_samples_button" )
+ def submit_request( self, request_id, request_name ):
+ self.home()
+ self.visit_url( "%s/requests/submit_request?id=%i" % ( self.url, request_id ))
+ self.check_page_for_string( 'The request <b>%s</b> has been submitted.' % request_name )
+ def add_bar_codes( self, request_id, request_name, bar_codes ):
+ self.home()
+ self.visit_url( "%s/requests_admin/bar_codes?request_id=%i" % (self.url, request_id) )
+ self.check_page_for_string( 'Bar codes for Samples of Request "%s"' % request_name )
+ for index, bar_code in enumerate(bar_codes):
+ tc.fv( "1", "sample_%i_bar_code" % index, bar_code )
+ tc.submit( "save_bar_codes" )
+ def change_sample_state( self, sample_name, sample_id, new_state_id, comment='' ):
+ self.home()
+ self.visit_url( "%s/requests_admin/show_events?sample_id=%i" % (self.url, sample_id) )
+ self.check_page_for_string( 'Events for Sample "%s"' % sample_name )
+ tc.fv( "1", "select_state", str(new_state_id) )
+ tc.fv( "1", "comment", comment )
+ tc.submit( "add_event_button" )
+ # Address stuff
+ def create_address( self, address ):
+ self.home()
+ self.visit_url( "%s/user/new_address" % self.url )
+ self.check_page_for_string( 'New address' )
+ for name, value in address.iteritems():
+ tc.fv( "1", name, value )
+ tc.submit( "Save_button" )
# Library stuff
def create_library( self, name='Library One', description='This is Library One' ):
"""Create a new library"""
diff -r fbad627b45ac -r e6dda627e6b0 test/functional/test_forms_and_requests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/functional/test_forms_and_requests.py Sat Aug 22 23:20:09 2009 -0400
@@ -0,0 +1,274 @@
+import galaxy.model
+from galaxy.model.orm import *
+from base.twilltestcase import *
+
+not_logged_in_as_admin_security_msg = 'You must be logged in as an administrator to access this feature.'
+logged_in_as_admin_security_msg = 'You must be an administrator to access this feature.'
+not_logged_in_security_msg = 'You must be logged in to create/submit sequencing requests'
+form_one_name = "Request Form"
+form_two_name = "Sample Form"
+request_type_name = 'Test Requestype'
+sample_states = [ ( 'New', 'Sample entered into the system' ),
+ ( 'Received', 'Sample tube received' ),
+ ( 'Done', 'Sequence run complete' ) ]
+address1 = dict( short_desc="Office",
+ name="James Bond",
+ institution="MI6" ,
+ address1="MI6 Headquaters",
+ address2="",
+ city="London",
+ state="London",
+ postal_code="007",
+ country="United Kingdom",
+ phone="007-007-0007" )
+
+
+def get_latest_form(form_name):
+ fdc_list = galaxy.model.FormDefinitionCurrent.filter( galaxy.model.FormDefinitionCurrent.table.c.deleted==False )\
+ .order_by( galaxy.model.FormDefinitionCurrent.table.c.create_time.desc() )
+ for fdc in fdc_list:
+ if form_name == fdc.latest_form.name:
+ return fdc.latest_form
+ return None
+
+
+class TestFormsAndRequests( TwillTestCase ):
+ def test_000_create_form( self ):
+ """Testing creating a new form and editing it"""
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ # create a form
+ global form_one_name
+ name = form_one_name
+ desc = "This is Form One's description"
+ self.create_form( name=name, desc=desc )
+ self.home()
+ self.visit_page( 'forms/manage' )
+ self.check_page_for_string( name )
+ self.check_page_for_string( desc )
+ # Get the form_definition object for later tests
+ form_one = galaxy.model.FormDefinition.filter( and_( galaxy.model.FormDefinition.table.c.name==name,
+ galaxy.model.FormDefinition.table.c.desc==desc ) ).all()[-1]
+ assert form_one is not None, 'Problem retrieving form named "%s" from the database' % name
+ # edit form & add few more fields
+ new_name = "Request Form (Renamed)"
+ new_desc = "This is Form One's Re-described"
+ self.edit_form( form_one.id, form_one.name, new_form_name=new_name, new_form_desc=new_desc )
+ self.home()
+ self.visit_page( 'forms/manage' )
+ self.check_page_for_string( new_name )
+ self.check_page_for_string( new_desc )
+ form_one_name = new_name
+ def test_005_add_form_fields( self ):
+ """Testing adding fields to a form definition"""
+ fields = [dict(name='Test field name one',
+ desc='Test field description one',
+ type='TextField',
+ required='required'),
+ dict(name='Test field name two',
+ desc='Test field description two',
+ type='AddressField',
+ required='optional')]
+ form_one = get_latest_form(form_one_name)
+ self.form_add_field(form_one.id, form_one.name, field_index=len(form_one.fields), fields=fields)
+ form_one_latest = get_latest_form(form_one_name)
+ assert len(form_one_latest.fields) == len(form_one.fields)+len(fields)
+#This following test has been commented out as it is causing:
+#TwillException: multiple matches to "remove_button"
+# def test_010_remove_form_fields( self ):
+# """Testing removing fields from a form definition"""
+# form_one = get_latest_form(form_one_name)
+# self.form_remove_field( form_one.id, form_one.name, 'Test field name one' )
+# form_one_latest = get_latest_form(form_one_name)
+# assert len(form_one_latest.fields) == len(form_one.fields)-1
+ def test_015_create_sample_form( self ):
+ """Testing creating another form (for samples)"""
+ global form_two_name
+ name = form_two_name
+ desc = "This is Form One's description"
+ self.create_form( name=name, desc=desc )
+ self.home()
+ self.visit_page( 'forms/manage' )
+ self.check_page_for_string( name )
+ self.check_page_for_string( desc )
+ def test_020_create_request_type( self ):
+ """Testing creating a new requestype"""
+ request_form = get_latest_form(form_one_name)
+ sample_form = get_latest_form(form_two_name)
+ self.create_request_type(request_type_name, "test request type",
+ str(request_form.id), str(sample_form.id), sample_states )
+ global request_type
+ request_type = galaxy.model.RequestType.filter( and_( galaxy.model.RequestType.table.c.name==request_type_name ) ).all()[-1]
+ assert request_type is not None, 'Problem retrieving request type named "%s" from the database' % request_type_name
+ def test_025_create_address_and_library( self ):
+ """Testing address & library creation"""
+ # first create a regular user
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ # first create a library for the request so that it can be submitted later
+ lib_name = 'TestLib001'
+ self.create_library( lib_name, '' )
+ self.visit_page( 'admin/browse_libraries' )
+ self.check_page_for_string( lib_name )
+ # Get the library object for later tests
+ global library_one
+ library_one = galaxy.model.Library.filter( and_( galaxy.model.Library.table.c.name==lib_name,
+ galaxy.model.Library.table.c.deleted==False ) ).first()
+ assert library_one is not None, 'Problem retrieving library named "%s" from the database' % lib_name
+ global admin_user
+ admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test(a)bx.psu.edu' ).first()
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ # Get the admin user's private role for later use
+ global admin_user_private_role
+ admin_user_private_role = None
+ for role in admin_user.all_roles():
+ if role.name == admin_user.email and role.description == 'Private Role for %s' % admin_user.email:
+ admin_user_private_role = role
+ break
+ if not admin_user_private_role:
+ raise AssertionError( "Private role not found for user '%s'" % admin_user.email )
+ global regular_user1
+ regular_user1 = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test1(a)bx.psu.edu' ).first()
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ # Get the regular user's private role for later use
+ global regular_user1_private_role
+ regular_user1_private_role = None
+ for role in regular_user1.all_roles():
+ if role.name == regular_user1.email and role.description == 'Private Role for %s' % regular_user1.email:
+ regular_user1_private_role = role
+ break
+ if not regular_user1_private_role:
+ raise AssertionError( "Private role not found for user '%s'" % regular_user1.email )
+ # Set permissions on the library, sort for later testing
+ permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ]
+ permissions_out = []
+ # Role one members are: admin_user, regular_user1. Each of these users will be permitted to
+ # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE for library items.
+ self.set_library_permissions( str( library_one.id ), library_one.name, str( regular_user1_private_role.id ), permissions_in, permissions_out )
+ # create address
+ #self.create_address( user_address1 )
+ #self.check_page_for_string( 'Address <b>%s</b> has been added' % user_address1[ 'short_desc' ] )
+ ## TODO: FIX HACK
+ ## the user address creation should be done as a test.
+ global user_address
+ user_address = galaxy.model.UserAddress()
+ user_address.user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test1(a)bx.psu.edu' ).first()
+ user_address.desc = address1[ 'short_desc' ]
+ user_address.name = address1[ 'name' ]
+ user_address.institution = address1[ 'institution' ]
+ user_address.address = address1[ 'address1' ]+' '+address1[ 'address2' ]
+ user_address.city = address1[ 'city' ]
+ user_address.state = address1[ 'state' ]
+ user_address.postal_code = address1[ 'postal_code' ]
+ user_address.country = address1[ 'country' ]
+ user_address.phone = address1[ 'phone' ]
+ user_address.flush()
+ user_address.user.refresh()
+ def test_030_create_request( self ):
+ """Testing creating, editing and submitting a request as a regular user"""
+ # login as a regular user
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu' )
+ # set field values
+ fields = ['field one value', 'field two value', str(user_address.id)]
+ # create the request
+ request_name, request_desc = 'Request One', 'Request One Description'
+ self.create_request(request_type.id, request_name, request_desc, library_one.id, fields)
+ self.check_page_for_string( request_name )
+ self.check_page_for_string( request_desc )
+ global request_one
+ request_one = galaxy.model.Request.filter( and_( galaxy.model.Request.table.c.name==request_name,
+ galaxy.model.Request.table.c.deleted==False ) ).first()
+ # check if the request's state is now set to 'unsubmitted'
+ assert request_one.state is not request_one.states.UNSUBMITTED, "The state of the request '%s' should be set to '%s'" % ( request_one.name, request_one.states.UNSUBMITTED )
+ # sample fields
+ samples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
+ ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
+ # add samples to this request
+ self.add_samples( request_one.id, request_one.name, samples )
+ for sample_name, fields in samples:
+ self.check_page_for_string( sample_name )
+ self.check_page_for_string( 'Unsubmitted' )
+ for field_value in fields:
+ self.check_page_for_string( field_value )
+ # edit this request
+ fields = ['field one value (editted)', 'field two value (editted)', str(user_address.id)]
+ self.edit_request(request_one.id, request_one.name, request_one.name+' (Renamed)', request_one.desc+' (Re-described)', library_one.id, fields)
+ request_one.refresh()
+ self.check_page_for_string( request_name+' (Renamed)' )
+ self.check_page_for_string( request_desc+' (Re-described)' )
+ # submit the request
+ self.submit_request( request_one.id, request_one.name )
+ request_one.refresh()
+ # check if the request's state is now set to 'submitted'
+ assert request_one.state is not request_one.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" % ( request_one.name, request_one.states.SUBMITTED )
+ def test_035_request_lifecycle( self ):
+ """Testing request lifecycle as it goes through all the states"""
+ # goto admin manage requests page
+ self.logout()
+ self.login( email='test(a)bx.psu.edu' )
+ self.home()
+ self.visit_page( 'requests_admin/list' )
+ self.check_page_for_string( request_one.name )
+ self.visit_url( "%s/requests_admin/list?sort=-create_time&operation=show_request&id=%s" \
+ % ( self.url, self.security.encode_id( request_one.id ) ))
+ self.check_page_for_string( 'Sequencing Request "%s"' % request_one.name )
+ # set bar codes for the samples
+ bar_codes = [ '1234567890', '0987654321' ]
+ self.add_bar_codes( request_one.id, request_one.name, bar_codes )
+ self.check_page_for_string( 'Bar codes has been saved for this request' )
+ # change the states of all the samples of this request
+ for sample in request_one.samples:
+ self.change_sample_state( sample.name, sample.id, request_type.states[1].id )
+ self.check_page_for_string( request_type.states[1].name )
+ self.check_page_for_string( request_type.states[1].desc )
+ self.change_sample_state( sample.name, sample.id, request_type.states[2].id )
+ self.check_page_for_string( request_type.states[2].name )
+ self.check_page_for_string( request_type.states[2].desc )
+ self.home()
+ request_one.refresh()
+ # check if the request's state is now set to 'complete'
+ assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" % ( request_one.name, request_one.states.COMPLETE )
+# def test_40_admin_create_request_on_behalf_of_regular_user( self ):
+# """Testing creating and submitting a request as an admin on behalf of a regular user"""
+# self.logout()
+# self.login( email='test(a)bx.psu.edu' )
+## permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ]
+## permissions_out = []
+## self.set_library_permissions( str( library_one.id ), library_one.name, str( admin_user_private_role.id ), permissions_in, permissions_out )
+# # set field values
+# fields = ['field one value', 'field two value', str(user_address.id)]
+# # create the request
+# request_name, request_desc = 'Request Two', 'Request Two Description'
+# self.create_request_admin(request_type.id, regular_user1.id, request_name, request_desc, library_one.id, fields)
+# self.check_page_for_string( request_name )
+# self.check_page_for_string( request_desc )
+# global request_two
+# request_one = galaxy.model.Request.filter( and_( galaxy.model.Request.table.c.name==request_name,
+# galaxy.model.Request.table.c.deleted==False ) ).first()
+# # check if the request's state is now set to 'unsubmitted'
+# assert request_two.state is not request_two.states.UNSUBMITTED, "The state of the request '%s' should be set to '%s'" % ( request_two.name, request_two.states.UNSUBMITTED )
+# # sample fields
+# samples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
+# ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
+# # add samples to this request
+# self.add_samples( request_two.id, request_two.name, samples )
+# for sample_name, fields in samples:
+# self.check_page_for_string( sample_name )
+# self.check_page_for_string( 'Unsubmitted' )
+# for field_value in fields:
+# self.check_page_for_string( field_value )
+# # submit the request
+# self.submit_request( request_two.id, request_two.name )
+# request_two.refresh()
+# # check if the request's state is now set to 'submitted'
+# assert request_two.state is not request_two.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" % ( request_two.name, request_two.states.SUBMITTED )
+
+
+
+
+
+
+
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 test/functional/test_security_and_libraries.py
--- a/test/functional/test_security_and_libraries.py Sat Aug 22 23:18:47 2009 -0400
+++ b/test/functional/test_security_and_libraries.py Sat Aug 22 23:20:09 2009 -0400
@@ -196,7 +196,7 @@
dhps.sort()
# Compare DefaultHistoryPermissions and actions_in - should be the same
if dhps != actions_in:
- raise AssertionError( 'DefaultHistoryPermissions "%s" for history id %d differ from actions "%s" passed for changing' \
+ raise AssertionError( 'DefaultHistoryPermissions "%s" for history id %d differ from actions "%s" passed for changing' \
% ( str( dhps ), latest_history.id, str( actions_in ) ) )
# Make sure DatasetPermissionss are correct
if len( latest_dataset.actions ) != len( latest_history.default_permissions ):
@@ -209,7 +209,7 @@
dps.sort()
# Compare DatasetPermissionss and DefaultHistoryPermissions - should be the same
if dps != dhps:
- raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s"' \
+ raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s"' \
% ( str( dps ), latest_dataset.id, str( dhps ) ) )
self.logout()
def test_020_create_new_user_account_as_admin( self ):
diff -r fbad627b45ac -r e6dda627e6b0 tools/extract/liftOver_wrapper_code.py
--- a/tools/extract/liftOver_wrapper_code.py Sat Aug 22 23:18:47 2009 -0400
+++ b/tools/extract/liftOver_wrapper_code.py Sat Aug 22 23:20:09 2009 -0400
@@ -3,7 +3,6 @@
to_dbkey = param_dict['to_dbkey'].split('.')[0].split('To')[1]
to_dbkey = to_dbkey[0].lower()+to_dbkey[1:]
out_data['out_file1'].set_dbkey(to_dbkey)
- out_data['out_file2'].set_dbkey(to_dbkey)
out_data['out_file1'].name = out_data['out_file1'].name + " [ MAPPED COORDINATES ]"
out_data['out_file2'].name = out_data['out_file2'].name + " [ UNMAPPED COORDINATES ]"
diff -r fbad627b45ac -r e6dda627e6b0 tools/metag_tools/split_paired_reads.py
--- a/tools/metag_tools/split_paired_reads.py Sat Aug 22 23:18:47 2009 -0400
+++ b/tools/metag_tools/split_paired_reads.py Sat Aug 22 23:20:09 2009 -0400
@@ -1,7 +1,7 @@
#! /usr/bin/python
"""
-Split Solexa paired end reads
+Split fixed length paired end reads
"""
import os, sys
@@ -12,9 +12,13 @@
outfile_end1 = open(sys.argv[2], 'w')
outfile_end2 = open(sys.argv[3], 'w')
- for i, line in enumerate(file(infile)):
+ i = 0
+
+ for line in file( infile ):
line = line.rstrip()
- if not line or line.startswith('#'): continue
+
+ if not line:
+ continue
end1 = ''
end2 = ''
@@ -42,5 +46,9 @@
outfile_end1.write('%s\n' %(end1))
outfile_end2.write('%s\n' %(end2))
+ i += 1
+
+ if i % 4 != 0 :
+ sys.stderr.write("WARNING: Number of lines in the input file was not divisible by 4.\nCheck consistency of the input fastq file.\n")
outfile_end1.close()
outfile_end2.close()
\ No newline at end of file
diff -r fbad627b45ac -r e6dda627e6b0 tools/solid_tools/maq_cs_wrapper.py
--- a/tools/solid_tools/maq_cs_wrapper.py Sat Aug 22 23:18:47 2009 -0400
+++ b/tools/solid_tools/maq_cs_wrapper.py Sat Aug 22 23:20:09 2009 -0400
@@ -48,9 +48,9 @@
cmd1 = "solid2fastq_modified.pl 'yes' %s %s %s %s %s %s %s 2>&1" %(tmpf.name,tmpr.name,tmps.name,f3_read_fname,f3_qual_fname,r3_read_fname,r3_qual_fname)
try:
os.system(cmd1)
- os.system('zcat -f %s >> %s' %(tmpf.name,tmpffastq.name))
- os.system('zcat -f %s >> %s' %(tmpr.name,tmprfastq.name))
- os.system('zcat -f %s >> %s' %(tmps.name,tmpsfastq.name))
+ os.system('gunzip -c %s >> %s' %(tmpf.name,tmpffastq.name))
+ os.system('gunzip -c %s >> %s' %(tmpr.name,tmprfastq.name))
+ os.system('gunzip -c %s >> %s' %(tmps.name,tmpsfastq.name))
except Exception, eq:
stop_err("Error converting data to fastq format." + str(eq))
@@ -135,7 +135,7 @@
cmd1 = "solid2fastq_modified.pl 'no' %s %s %s %s %s %s %s 2>&1" %(tmpf.name,None,None,f3_read_fname,f3_qual_fname,None,None)
try:
os.system(cmd1)
- os.system('zcat -f %s >> %s' %(tmpf.name,tmpfastq.name))
+ os.system('gunzip -c %s >> %s' %(tmpf.name,tmpfastq.name))
tmpf.close()
except:
stop_err("Error converting data to fastq format.")
1
0

24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/3e9b7ec9a305
changeset: 2610:3e9b7ec9a305
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 12:31:05 2009 -0400
description:
Backed out changeset 19b86ccccf6f (not quite ready yet)
5 file(s) affected in this change:
lib/galaxy/model/__init__.py
lib/galaxy/model/mapping.py
lib/galaxy/model/migrate/versions/0014_pages.py
lib/galaxy/web/controllers/user.py
templates/user/index.mako
diffs (220 lines):
diff -r 19b86ccccf6f -r 3e9b7ec9a305 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/model/__init__.py Sun Aug 23 12:31:05 2009 -0400
@@ -33,7 +33,6 @@
self.external = False
self.deleted = False
self.purged = False
- self.username = None
# Relationships
self.histories = []
@@ -1119,20 +1118,7 @@
self.country+'<br/>'+ \
'Phone: '+self.phone
-class Page( object ):
- def __init__( self ):
- self.id = None
- self.user = None
- self.title = None
- self.slug = None
- self.latest_revision_id = None
- self.revisions = []
-class PageRevision( object ):
- def __init__( self ):
- self.user = None
- self.title = None
- self.content = None
diff -r 19b86ccccf6f -r 3e9b7ec9a305 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/model/mapping.py Sun Aug 23 12:31:05 2009 -0400
@@ -42,7 +42,6 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
- Column( "username", TrimmedString( 255 ), index=True, unique=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
@@ -524,26 +523,6 @@
Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ),
Column( "comment", TEXT ) )
-Page.table = Table( "page", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
- Column( "latest_revision_id", Integer,
- ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
- Column( "title", TEXT ),
- Column( "slug", TEXT, unique=True, index=True ),
- )
-
-PageRevision.table = Table( "page_revision", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
- Column( "title", TEXT ),
- Column( "content", TEXT )
- )
-
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
@@ -926,18 +905,6 @@
assign_mapper( context, MetadataFile, MetadataFile.table,
properties=dict( history_dataset=relation( HistoryDatasetAssociation ), library_dataset=relation( LibraryDatasetDatasetAssociation ) ) )
-assign_mapper( context, PageRevision, PageRevision.table )
-
-assign_mapper( context, Page, Page.table,
- properties=dict( user=relation( User ),
- revisions=relation( PageRevision, backref='page',
- cascade="all, delete-orphan",
- primaryjoin=( Page.table.c.id == PageRevision.table.c.page_id ) ),
- latest_revision=relation( PageRevision, post_update=True,
- primaryjoin=( Page.table.c.latest_revision_id == PageRevision.table.c.id ),
- lazy=False )
- ) )
-
def db_next_hid( self ):
"""
Override __next_hid to generate from the database in a concurrency
diff -r 19b86ccccf6f -r 3e9b7ec9a305 lib/galaxy/model/migrate/versions/0014_pages.py
--- a/lib/galaxy/model/migrate/versions/0014_pages.py Sun Aug 23 12:26:46 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-from sqlalchemy import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-
-import logging
-log = logging.getLogger( __name__ )
-
-metadata = MetaData( migrate_engine )
-
-Page_table = Table( "page", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
- Column( "latest_revision_id", Integer,
- ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
- Column( "title", TEXT ),
- Column( "slug", TEXT, unique=True, index=True ),
- )
-
-PageRevision_table = Table( "page_revision", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
- Column( "title", TEXT ),
- Column( "content", TEXT )
- )
-
-def upgrade():
- metadata.reflect()
- try:
- Page_table.create()
- except:
- log.debug( "Could not create page table" )
- try:
- PageRevision_table.create()
- except:
- log.debug( "Could not create page_revision table" )
-
- # Add 1 column to the user table
- User_table = Table( "galaxy_user", metadata, autoload=True )
- col = Column( 'username', String(255), index=True, unique=True, default=False )
- print type( col ), col
- col.create( User_table )
- assert col is User_table.c.username
-
-def downgrade():
- metadata.reflect()
- Page_table.drop()
- PageRevision_table.drop()
- User_table = Table( "galaxy_user", metadata, autoload=True )
- User_table.c.username.drop()
\ No newline at end of file
diff -r 19b86ccccf6f -r 3e9b7ec9a305 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Sun Aug 23 12:26:46 2009 -0400
+++ b/lib/galaxy/web/controllers/user.py Sun Aug 23 12:31:05 2009 -0400
@@ -4,7 +4,7 @@
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util
-import logging, os, string, re
+import logging, os, string
from random import choice
log = logging.getLogger( __name__ )
@@ -19,8 +19,6 @@
"""
require_login_nocreation_template = require_login_template % ""
require_login_creation_template = require_login_template % " If you don't already have an account, <a href='%s'>you may create one</a>."
-
-VALID_USERNAME_RE = re.compile( "^[a-zA-Z0-9\-\_]+$" )
class User( BaseController ):
edit_address_id = None
@@ -80,37 +78,6 @@
.add_text( "email", "Email", value=email, error=email_err )
.add_text( "conf_email", "Confirm Email", value='', error=conf_email_err )
.add_password( "password", "Password", value='', error=pass_err ) )
-
- @web.expose
- def change_username(self, trans, username='', **kwd):
- username_err = ''
- user = trans.get_user()
- if not user:
- trans.response.send_redirect( web.url_for( action='login' ) )
- if trans.request.method == "POST":
- if len( username ) < 4:
- username_err = "Username must be at least 4 characters in length"
- elif len( username ) > 255:
- username_err = "USername must be at most 255 characters in length"
- elif not( VALID_USERNAME_RE.match( username ) ):
- username_err = "Username must contain only letters, numbers, '-', and '_'"
- elif trans.app.model.User.filter_by( username=username ).first():
- username_err = "This username is not available"
- else:
- user.username = username
- user.flush()
- trans.log_event( "User change username" )
- return trans.show_ok_message( "Username been set to: " + user.username )
- else:
- username = user.username or ''
- return trans.show_form(
- web.FormBuilder( web.url_for(), "Change username", submit_text="Submit" )
- .add_text( "username", "Username", value=username, error=username_err,
- help="""Your username is an optional identifier that
- will be used to generate adresses for information
- you share publicly. Usernames must be at least
- four characters in length and contain only letters,
- numbers, and the '-' and '_' characters""" ) )
@web.expose
def login( self, trans, email='', password='' ):
diff -r 19b86ccccf6f -r 3e9b7ec9a305 templates/user/index.mako
--- a/templates/user/index.mako Sun Aug 23 12:26:46 2009 -0400
+++ b/templates/user/index.mako Sun Aug 23 12:31:05 2009 -0400
@@ -9,7 +9,6 @@
<ul>
<li><a href="${h.url_for( action='change_password' )}">${_('Change your password')}</a></li>
<li><a href="${h.url_for( action='change_email' )}">${_('Update your email address')}</a></li>
- <li><a href="${h.url_for( action='change_username' )}">${_('Change your public username')}</a></li>
<li><a href="${h.url_for( action='set_default_permissions' )}">${_('Change default permissions')}</a> for new histories</li>
<li><a href="${h.url_for( action='manage_addresses' )}">${_('Manage your addresses')}</a></li>
<li><a href="${h.url_for( action='logout' )}">${_('Logout')}</a></li>
1
0

24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/abdb523727ed
changeset: 2604:abdb523727ed
user: James Taylor <james(a)jamestaylor.org>
date: Thu Aug 06 10:29:51 2009 -0400
description:
Rework popup menu styles. Popups are now larger, have borders, and have better highlight styles. The history options button is now a popup menu. (Also misc style fixes and improvements).
16 file(s) affected in this change:
lib/galaxy/web/controllers/history.py
static/june_2007_style/base.css.tmpl
static/june_2007_style/blue/base.css
static/june_2007_style/blue/history-buttons.png
static/june_2007_style/blue/history-states.png
static/june_2007_style/blue/library.css
static/june_2007_style/blue/panel_layout.css
static/june_2007_style/blue_colors.ini
static/june_2007_style/panel_layout.css.tmpl
static/scripts/galaxy.base.js
templates/base_panels.mako
templates/history/clone.mako
templates/history/grid.mako
templates/root/index.mako
templates/workflow/editor.mako
templates/workflow/list.mako
diffs (688 lines):
diff -r 542471b183d7 -r abdb523727ed lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Thu Aug 20 18:44:35 2009 -0400
+++ b/lib/galaxy/web/controllers/history.py Thu Aug 06 10:29:51 2009 -0400
@@ -229,6 +229,7 @@
# No message
return None, None
@web.expose
+ @web.require_login( "work with shared histories" )
def list_shared( self, trans, **kwargs ):
"""List histories shared with current user by others"""
msg = util.restore_text( kwargs.get( 'msg', '' ) )
@@ -617,6 +618,7 @@
if send_to_err:
msg += send_to_err
return self.sharing( trans, histories=shared_histories, msg=msg )
+
@web.expose
@web.require_login( "share histories with other users" )
def sharing( self, trans, histories=[], id=None, **kwd ):
@@ -644,6 +646,7 @@
shared_msg = "History (%s) now shared with: %d users. " % ( history.name, len( history.users_shared_with ) )
msg = '%s%s' % ( shared_msg, msg )
return trans.fill_template( 'history/sharing.mako', histories=histories, msg=msg, messagetype='done' )
+
@web.expose
@web.require_login( "rename histories" )
def rename( self, trans, id=None, name=None, **kwd ):
@@ -681,19 +684,26 @@
else:
change_msg = change_msg + "<p>History: "+cur_names[i]+" does not appear to belong to you.</p>"
return trans.show_message( "<p>%s" % change_msg, refresh_frames=['history'] )
+
@web.expose
@web.require_login( "clone shared Galaxy history" )
- def clone( self, trans, id, **kwd ):
+ def clone( self, trans, id=None, **kwd ):
"""Clone a list of histories"""
params = util.Params( kwd )
- ids = util.listify( id )
- histories = []
- for history_id in ids:
- history = get_history( trans, history_id, check_ownership=False )
- histories.append( history )
+ # If clone_choice was not specified, display form passing along id
+ # argument
clone_choice = params.get( 'clone_choice', None )
if not clone_choice:
- return trans.fill_template( "/history/clone.mako", history=history )
+ return trans.fill_template( "/history/clone.mako", id_argument=id )
+ # Extract histories for id argument, defaulting to current
+ if id is None:
+ histories = [ trans.history ]
+ else:
+ ids = util.listify( id )
+ histories = []
+ for history_id in ids:
+ history = get_history( trans, history_id, check_ownership=False )
+ histories.append( history )
user = trans.get_user()
for history in histories:
if history.user == user:
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/base.css.tmpl
--- a/static/june_2007_style/base.css.tmpl Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/base.css.tmpl Thu Aug 06 10:29:51 2009 -0400
@@ -2,6 +2,19 @@
body{font:13px/1.231 verdana,arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% verdana,arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
body{font-size:75%;}
+## Mixins
+.unselectable {
+ user-select: none;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+}
+
+.shadow {
+ -moz-box-shadow: 0 3px 30px black;
+ -webkit-box-shadow: 0 3px 30px black;
+}
+
+## Real styles
body
{
background: $base_bg_bottom;
@@ -48,7 +61,7 @@
padding-left: 10px;
padding-right: 10px;
background: $form_title_bg_bottom;
- background-image: url(form_title_bg.png);
+ ## background-image: url(form_title_bg.png);
background-repeat: repeat-x;
background-position: top;
border-bottom: solid $form_border 1px;
@@ -524,10 +537,11 @@
## Button styles
.action-button {
- background: #eeeeee;
+ background: transparent;
+ line-height: 16px;
color: #333;
text-decoration: none;
- font-size: 95%;
+ font-size: 100%;
font-weight: bold;
display: inline-block;
cursor: pointer;
@@ -556,39 +570,139 @@
background: #aaaaaa;
}
-## Popup menu styles
+## A menu button is a button that has an attached popup menu
-div.popupmenu {
- display: none;
- background: #eeeeee;
- color: #333;
- font-size: 110%;
- font-weight: bold;
- font-style: normal;
- white-space: nowrap;
- position: absolute;
- z-index: 20000;
- border: solid #aaaaaa 1px;
- padding: 3px 0;
+.menubutton {
+ display: inline-block;
+ cursor: pointer;
+ position: relative;
+ .unselectable;
+
+ border: solid transparent 1px;
-moz-border-radius: 0.5em;
-webkit-border-radius: 0.5em;
border-radius: 0.5em;
- user-select: none;
- -moz-user-select: none;
- -webkit-user-select: none;
+
+ padding: 3px 0.5em;
+ margin: -3px -0.5em;
+ padding-right: 1.5em;
+
+ .label, .arrow {
+ position: relative;
+ display: block;
+ }
+
+ .label {
+ border-right: none;
+ }
+
+ .arrow {
+ padding-left: 2px;
+ width: 1em;
+ position: absolute;
+ top: 0;
+ right: 5px;
+ height: 100%;
+ }
+
+ .arrow > span {
+ display: inline-block;
+ padding-top: 3px;
+ }
+
}
-div.popupmenu-item {
- padding: 3px 1em;
- cursor: pointer;
+.menubutton:hover {
+ border-color: #aaaaaa;
+ ## background: #eeeeee;
+ ## color: #333;
}
-div.popupmenu-item:hover {
- background: #aaaaaa;
+## A split menu button, the main button has an action, the arrow causes the
+## popup menu to appear
+
+.menubutton.split {
+ padding-right: 2em;
+ .arrow {
+ border-left: solid transparent 1px;
+ }
+}
+
+.menubutton.split:hover {
+ .arrow {
+ border-left: solid #aaaaaa 1px;
+ }
+}
+
+## Popup menu styles
+
+.overlay-border {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ padding: 1em;
+ margin: -1em;
+ background-color: rgba(0,0,0,0.5);
+ -moz-border-radius: 1em;
+ -webkit-border-radius: 1em;
+ z-index: -1;
+}
+
+div.popmenu-wrapper {
+
+ position: absolute;
+ top: 100%;
+ z-index: 20000;
+
+ ul {
+
+ display: block;
+ margin: 0;
+ padding: 0;
+
+ background: white;
+ color: #333;
+ font-weight: bold;
+ font-style: normal;
+ white-space: nowrap;
+ border: solid #aaaaaa 1px;
+ padding: 3px 0;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ ## margin: -3px -0.5em;
+ ## min-width: 100%;
+
+ .unselectable;
+
+ li {
+ display: block;
+ padding: 3px 1em;
+ cursor: pointer;
+ border-top: solid transparent 1px;
+ border-bottom: solid transparent 1px;
+ }
+
+ li.head {
+ color: #999;
+ font-style: italic;
+ }
+ }
+}
+
+div.popmenu-wrapper ul li:hover {
+ background: #EEEEFF;
+ border-color: #aaa;
+}
+
+div.popmenu-wrapper ul li.head:hover {
+ background: inherit;
+ border-color: transparent;
}
.popup-arrow {
- font-size: 80%;
cursor: pointer;
text-decoration: none;
color: #555;
@@ -632,7 +746,7 @@
}
.grid thead th {
background: $table_header_bg;
- background-image: url(form_title_bg.png);
+ ## background-image: url(form_title_bg.png);
background-repeat: repeat-x;
background-position: top;
border-top: solid $table_border 1px;
@@ -648,4 +762,4 @@
}
.grid .current {
background-color: #EEEEFF;
-}
\ No newline at end of file
+}
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/blue/base.css Thu Aug 06 10:29:51 2009 -0400
@@ -3,13 +3,15 @@
table{font-size:inherit;font:100%;}
pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
body{font-size:75%;}
+.unselectable{user-select:none;-moz-user-select:none;-webkit-user-select:none;}
+.shadow{-moz-box-shadow:0 3px 30px black;-webkit-box-shadow:0 3px 30px black;}
body{background:#FFFFFF;color:#303030;background-image:url(base_bg.png);background-repeat:repeat-x;background-position:top;margin:10px;}
img{border:0;}
a:link,a:visited,a:active{color:#303030;}
h1,h2,h3,h4{color:#023858;}
hr{border:none;height:0px;border-bottom:dotted #303030 1px;}
div.toolForm{border:solid #d8b365 1px;}
-div.toolFormTitle{font-weight:bold;padding:5px;padding-left:10px;padding-right:10px;background:#d2c099;background-image:url(form_title_bg.png);background-repeat:repeat-x;background-position:top;border-bottom:solid #d8b365 1px;}
+div.toolFormTitle{font-weight:bold;padding:5px;padding-left:10px;padding-right:10px;background:#ebd9b2;background-repeat:repeat-x;background-position:top;border-bottom:solid #d8b365 1px;}
div.toolParamHelp{color:#666;}
div.toolParamHelp a{color:#666;}
div.toolFormBody{background:#FFFFFF;background-image:url(form_body_bg.png);background-repeat:repeat-x;background-position:top;padding:5px 0;}
@@ -20,7 +22,7 @@
div.toolHelpBody{width:100%;overflow:auto;}
div.titleRow{font-weight:bold;border-bottom:dotted gray 1px;margin-bottom:0.5em;padding-bottom:0.25em;}
div.form{border:solid #d8b365 1px;}
-div.form-title{font-weight:bold;padding:5px 10px;background:#d2c099;background-image:url(form_title_bg.png);background-repeat:repeat-x;background-position:top;border-bottom:solid #d8b365 1px;}
+div.form-title{font-weight:bold;padding:5px 10px;background:#ebd9b2;background-image:url(form_title_bg.png);background-repeat:repeat-x;background-position:top;border-bottom:solid #d8b365 1px;}
div.form-body{padding:5px 0;}
div.form-row{padding:5px 10px;}
div.form-title-row{padding:5px 10px;}
@@ -77,14 +79,28 @@
.state-fg-ok{color:#66AA66;}
.state-fg-running{color:#AAAA66;}
.state-fg-error{color:#AA6666;}
-.action-button{background:#eeeeee;color:#333;text-decoration:none;font-size:95%;font-weight:bold;display:inline-block;cursor:pointer;padding:2px;border:solid #aaaaaa 1px;padding-right:0.5em;padding-left:0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;user-select:none;-moz-user-select:none;-webkit-user-select:none;}
+.action-button{background:transparent;line-height:16px;color:#333;text-decoration:none;font-size:100%;font-weight:bold;display:inline-block;cursor:pointer;padding:2px;border:solid #aaaaaa 1px;padding-right:0.5em;padding-left:0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;user-select:none;-moz-user-select:none;-webkit-user-select:none;}
.action-button > *{vertical-align:middle;}
.action-button:hover{color:black;background:#dddddd;}
.action-button:active{color:white;background:#aaaaaa;}
-div.popupmenu{display:none;background:#eeeeee;color:#333;font-size:110%;font-weight:bold;font-style:normal;white-space:nowrap;position:absolute;z-index:20000;border:solid #aaaaaa 1px;padding:3px 0;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;user-select:none;-moz-user-select:none;-webkit-user-select:none;}
-div.popupmenu-item{padding:3px 1em;cursor:pointer;}
-div.popupmenu-item:hover{background:#aaaaaa;}
-.popup-arrow{font-size:80%;cursor:pointer;text-decoration:none;color:#555;}
+.menubutton{display:inline-block;cursor:pointer;position:relative;user-select:none;-moz-user-select:none;-webkit-user-select:none;border:solid transparent 1px;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;padding:3px 0.5em;margin:-3px -0.5em;padding-right:1.5em;}
+.menubutton .label,.menubutton .arrow{position:relative;display:block;}
+.menubutton .label{border-right:none;}
+.menubutton .arrow{padding-left:2px;width:1em;position:absolute;top:0;right:5px;height:100%;}
+.menubutton .arrow > span{display:inline-block;padding-top:3px;}
+.menubutton:hover{border-color:#aaaaaa;}
+.menubutton.split{padding-right:2em;}
+.menubutton.split .arrow{border-left:solid transparent 1px;}
+.menubutton.split:hover{}
+.menubutton.split:hover .arrow{border-left:solid #aaaaaa 1px;}
+.overlay-border{position:absolute;top:0;left:0;height:100%;width:100%;padding:1em;margin:-1em;background-color:rgba(0,0,0,0.5);-moz-border-radius:1em;-webkit-border-radius:1em;z-index:-1;}
+div.popmenu-wrapper{position:absolute;top:100%;z-index:20000;}
+div.popmenu-wrapper ul{display:block;margin:0;padding:0;background:white;color:#333;font-weight:bold;font-style:normal;white-space:nowrap;border:solid #aaaaaa 1px;padding:3px 0;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;user-select:none;-moz-user-select:none;-webkit-user-select:none;}
+div.popmenu-wrapper ul li{display:block;padding:3px 1em;cursor:pointer;border-top:solid transparent 1px;border-bottom:solid transparent 1px;}
+div.popmenu-wrapper ul li.head{color:#999;font-style:italic;}
+div.popmenu-wrapper ul li:hover{background:#EEEEFF;border-color:#aaa;}
+div.popmenu-wrapper ul li.head:hover{background:inherit;border-color:transparent;}
+.popup-arrow{cursor:pointer;text-decoration:none;color:#555;}
.popup-arrow:hover{color:black;}
div.permissionContainer{padding-left:20px;}
.grid-header{padding-bottom:1em;}
@@ -93,6 +109,6 @@
.grid{padding-top:1em;border-collapse:collapse;width:100%;}
.grid tbody td{border-top:solid #DDDDDD 1px;border-bottom:solid #DDDDDD 1px;padding:0.5em 1em;}
.grid tbody td:empty{padding:0;}
-.grid thead th{background:#ebd9b2;background-image:url(form_title_bg.png);background-repeat:repeat-x;background-position:top;border-top:solid #d8b365 1px;border-bottom:solid #d8b365 1px;padding:0.5em 1em;text-align:left;}
+.grid thead th{background:#ebd9b2;background-repeat:repeat-x;background-position:top;border-top:solid #d8b365 1px;border-bottom:solid #d8b365 1px;padding:0.5em 1em;text-align:left;}
.grid tfoot td{background-color:#F8F8F8;border-top:solid #DDDDDD 1px;border-bottom:solid #DDDDDD 1px;padding:0.5em 1em;}
.grid .current{background-color:#EEEEFF;}
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue/history-buttons.png
Binary file static/june_2007_style/blue/history-buttons.png has changed
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue/history-states.png
Binary file static/june_2007_style/blue/history-states.png has changed
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue/library.css
--- a/static/june_2007_style/blue/library.css Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/blue/library.css Thu Aug 06 10:29:51 2009 -0400
@@ -1,4 +1,4 @@
-.libraryRow{background-color:#d2c099;}
+.libraryRow{background-color:#ebd9b2;}
.datasetHighlighted{background-color:#C1C9E5;}
.libraryItemDeleted-True{font-style:italic;}
div.historyItemBody{padding:4px 4px 2px 4px;}
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue/panel_layout.css
--- a/static/june_2007_style/blue/panel_layout.css Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/blue/panel_layout.css Thu Aug 06 10:29:51 2009 -0400
@@ -24,7 +24,7 @@
.unified-panel-header-inner{padding-top:0.45em;}
.menu-bg{background:#C1C9E5 url(menu_bg.png) top repeat-x;}
div.unified-panel-body{position:absolute;top:2em;bottom:0;width:100%;margin-top:1px;}
-.panel-header-button{color:#333;text-decoration:none;display:inline-block;cursor:pointer;margin:-1px;padding:1px;border:0px;padding-right:0.5em;padding-left:0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;background:transparent;}
+.panel-header-button{color:#333;text-decoration:none;display:inline-block;cursor:pointer;margin:-1px;padding:1px;padding-right:0.5em;padding-left:0.5em;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em;background:#bbb;}
.panel-header-button:hover{color:black;background:#aaaaaa;}
.panel-header-button:active{color:white;background:#aaaaaa;}
#overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:20000;}
@@ -37,9 +37,8 @@
.panel-done-message{background-image:url(done_small.png);background-color:#CCFFCC;}
.panel-info-message{background-image:url(info_small.png);background-color:#CCCCFF;}
#masthead{position:absolute;top:0;left:0;width:100%;height:32px;background:#2C3143;color:#fff;border-bottom:solid #444 1px;z-index:15000;padding:0;}
-#masthead a{color:#eeeeee;}
+#masthead a{color:#eeeeee;text-decoration:none;}
#masthead .title{padding:3px 10px;font-size:175%;font-weight:bold;}
-#masthead a{text-decoration:none;}
#masthead a:hover{text-decoration:underline;}
.tab-group{margin:0;padding:0 10px;height:100%;white-space:nowrap;cursor:default;background:transparent;}
.tab-group .tab{background:#2C3143;position:relative;float:left;margin:0;padding:0 1em;height:32px;line-height:32px;text-align:left;}
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/blue_colors.ini
--- a/static/june_2007_style/blue_colors.ini Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/blue_colors.ini Thu Aug 06 10:29:51 2009 -0400
@@ -9,7 +9,7 @@
#menu_bg_hatch=#AAAAFF
# Forms
form_title_bg_top=#ebd9b2
-form_title_bg_bottom=#d2c099
+form_title_bg_bottom=#ebd9b2
form_title_bg_hatch=-
form_border=#d8b365
#form_body_bg=#FFFFFF
diff -r 542471b183d7 -r abdb523727ed static/june_2007_style/panel_layout.css.tmpl
--- a/static/june_2007_style/panel_layout.css.tmpl Thu Aug 20 18:44:35 2009 -0400
+++ b/static/june_2007_style/panel_layout.css.tmpl Thu Aug 06 10:29:51 2009 -0400
@@ -144,13 +144,12 @@
display: inline-block;
cursor: pointer;
margin: -1px; padding: 1px;
- border: 0px;
padding-right: 0.5em;
padding-left: 0.5em;
-moz-border-radius: 0.5em;
-webkit-border-radius: 0.5em;
border-radius: 0.5em;
- background: transparent;
+ background: #bbb;
}
.panel-header-button:hover {
@@ -230,8 +229,7 @@
## Masthead
-#masthead
-{
+#masthead {
position:absolute;
top:0;
left:0;
@@ -242,27 +240,20 @@
border-bottom: solid ${layout_masthead_border} 1px;
z-index: 15000;
padding: 0;
+
+ a {
+ color: ${masthead_link};
+ text-decoration: none;
+ }
+
+ .title {
+ padding: 3px 10px;
+ font-size: 175%;
+ font-weight: bold;
+ }
}
-#masthead a
-{
- color: $masthead_link;
-}
-
-#masthead .title
-{
- padding: 3px 10px;
- font-size: 175%;
- font-weight: bold;
-}
-
-#masthead a
-{
- text-decoration: none;
-}
-
-#masthead a:hover
-{
+#masthead a:hover {
text-decoration: underline;
}
diff -r 542471b183d7 -r abdb523727ed static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Thu Aug 20 18:44:35 2009 -0400
+++ b/static/scripts/galaxy.base.js Thu Aug 06 10:29:51 2009 -0400
@@ -54,30 +54,52 @@
function make_popupmenu( button_element, options ) {
ensure_popup_helper();
- $(button_element).css( "position", "relative" );
- var menu_element = $( "<div class='popupmenu' id='" + button_element.attr('id') + "-menu'></div>" )
- .css( "position", "absolute" )
- .appendTo( button_element );
+ var container_element = $(button_element);
+ // if ( container_element.parent().hasClass( "combo-button" ) ) {
+ // container_element = container_element.parent();
+ // }
+ // ontainer_element).css( "position", "relative" );
+ var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></div>" );
$.each( options, function( k, v ) {
- $( "<div class='popupmenu-item' />" ).html( k ).click( v ).appendTo( menu_element );
+ if ( v ) {
+ $( "<li/>" ).html( k ).click( v ).appendTo( menu_element );
+ } else {
+ $( "<li class='head'/>" ).html( k ).appendTo( menu_element );
+ }
});
+ var wrapper = $( "<div class='popmenu-wrapper'>" );
+ wrapper.append( menu_element )
+ .append( "<div class='overlay-border'>" )
+ .css( "position", "absolute" )
+ .appendTo( "body" )
+ .hide();
+ attach_popupmenu( button_element, wrapper );
+};
+
+function attach_popupmenu( button_element, wrapper ) {
+ console.log( button_element, wrapper );
var clean = function() {
- $(menu_element).unbind().hide();
- // $("#popup-helper").unbind().hide();
- $(document).unbind( "click.popupmenu" );
+ wrapper.unbind().hide();
+ $("#popup-helper").unbind( "click.popupmenu" ).hide();
+ // $(document).unbind( "click.popupmenu" );
};
var click = function( e ) {
+ console.log( e );
var o = $(button_element).offset();
- // $("#popup-helper").mousedown( clean ).show();
- $(document).bind( "click.popupmenu", clean );
+ $("#popup-helper").bind( "click.popupmenu", clean ).show();
+ // $(document).bind( "click.popupmenu", clean );
// Show off screen to get size right
- $( menu_element ).click( clean ).css( { left: 0, top: -1000 } ).show();
+ wrapper.click( clean ).css( { left: 0, top: -1000 } ).show();
// console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
- // var x = Math.min( e.pageX - 2, $(document).scrollLeft() + $(window).width() - $(menu_element).width() - 5 );
+ var x = e.pageX - wrapper.width() / 2
+ x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 20 );
+ x = Math.max( x, $(document).scrollLeft() + 20 );
// console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
- $( menu_element ).css( {
- top: 0, //e.pageY - 2,
- left: 0 // x
+
+
+ wrapper.css( {
+ top: e.pageY - 5,
+ left: x
} );
return false;
};
diff -r 542471b183d7 -r abdb523727ed templates/base_panels.mako
--- a/templates/base_panels.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/base_panels.mako Thu Aug 06 10:29:51 2009 -0400
@@ -20,7 +20,7 @@
## Default stylesheets
<%def name="stylesheets()">
- ${h.css('panel_layout')}
+ ${h.css('base','panel_layout')}
<style type="text/css">
#center {
%if not self.has_left_panel:
@@ -50,7 +50,7 @@
<%def name="late_javascripts()">
## Scripts can be loaded later since they progressively add features to
## the panels, but do not change layout
- ${h.js( 'jquery', 'jquery.event.drag', 'jquery.event.hover', 'jquery.form', 'galaxy.panels' )}
+ ${h.js( 'jquery', 'jquery.event.drag', 'jquery.event.hover', 'jquery.form', 'galaxy.base', 'galaxy.panels' )}
<script type="text/javascript">
ensure_dd_helper();
diff -r 542471b183d7 -r abdb523727ed templates/history/clone.mako
--- a/templates/history/clone.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/history/clone.mako Thu Aug 06 10:29:51 2009 -0400
@@ -7,7 +7,9 @@
<div class="toolFormBody">
<form action="${h.url_for( controller='history', action='clone' )}" method="post" >
<div class="form-row">
- <input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
+ %if id_argument is not None:
+ <input type="hidden" name="id" value="${trans.security.encode_id( id_argument )}">
+ %endif
You can clone the history such that the clone will include all items in the original
history, or you can eliminate the original history's deleted items from the clone.
</div>
diff -r 542471b183d7 -r abdb523727ed templates/history/grid.mako
--- a/templates/history/grid.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/history/grid.mako Thu Aug 06 10:29:51 2009 -0400
@@ -153,16 +153,15 @@
<%
# Attach popup menu?
if column.attach_popup and cellnum == 0:
- extra = '<a id="grid-%d-popup" class="popup-arrow" style="display: none;">▼</a>' % i
+ extra = '<a id="grid-%d-popup" class="arrow" style="display: none;"><span>▼</span></a>' % i
else:
extra = ""
%>
%if href:
- <td><a href="${href}">${v}</a> ${extra}</td>
+ <td><div class="menubutton split"><a class="label" href="${href}">${v}${extra}</a></td>
%else:
<td >${v}${extra}</td>
%endif
- </td>
%endfor
%endif
%endfor
diff -r 542471b183d7 -r abdb523727ed templates/root/index.mako
--- a/templates/root/index.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/root/index.mako Thu Aug 06 10:29:51 2009 -0400
@@ -1,4 +1,46 @@
<%inherit file="/base_panels.mako"/>
+
+<%def name="late_javascripts()">
+ ${parent.late_javascripts()}
+ <script type="text/javascript">
+ $(function(){
+ $("#history-options-button").css( "position", "relative" );
+ make_popupmenu( $("#history-options-button"), {
+ "List your histories": null,
+ "Stored by you": function() {
+ galaxy_main.location = "${h.url_for( controller='history', action='list')}";
+ },
+ "Shared with you": function() {
+ galaxy_main.location = "${h.url_for( controller='history', action='list_shared')}";
+ },
+ "Current History": null,
+ "Create new": function() {
+ galaxy_history.location = "${h.url_for( controller='root', action='history_new' )}";
+ },
+ "Clone": function() {
+ galaxy_main.location = "${h.url_for( controller='history', action='clone')}";
+ },
+ "Manage sharing": function() {
+ galaxy_main.location = "${h.url_for( controller='history', action='share' )}";
+ },
+ "Extract workflow": function() {
+ galaxy_main.location = "${h.url_for( controller='workflow', action='build_from_current_history' )}";
+ },
+ "Dataset security": function() {
+ galaxy_main.location = "${h.url_for( controller='root', action='history_set_default_permissions' )}";
+ },
+ "Show deleted datasets": function() {
+ galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
+ },
+ "Delete": function() {
+ if ( confirm( "Really delete the current history?" ) ) {
+ galaxy_main.location = "${h.url_for( controller='history', action='delete_current' )}";
+ }
+ }
+ });
+ });
+ </script>
+</%def>
<%def name="init()">
<%
@@ -48,7 +90,7 @@
<div class="unified-panel-header" unselectable="on">
<div class="unified-panel-header-inner">
<div style="float: right">
- <a class='panel-header-button' href="${h.url_for( controller='root', action='history_options' )}" target="galaxy_main"><span>${_('Options')}</span></a>
+ <a id="history-options-button" class='panel-header-button' href="${h.url_for( controller='root', action='history_options' )}" target="galaxy_main"><span>${_('Options')}<span>▼</span></span></a>
</div>
<div class="panel-header-text">${_('History')}</div>
</div>
diff -r 542471b183d7 -r abdb523727ed templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/workflow/editor.mako Thu Aug 06 10:29:51 2009 -0400
@@ -677,9 +677,8 @@
<div class="unified-panel-header" unselectable="on">
<div class="unified-panel-header-inner" style="float: right">
- <span class="panel-header-button-group">
<a id="layout-button" class="panel-header-button">Layout</a>
- </span>
+
<a id="save-button" class="panel-header-button">Save</a>
<a id="close-button" class="panel-header-button">Close</a>
</div>
diff -r 542471b183d7 -r abdb523727ed templates/workflow/list.mako
--- a/templates/workflow/list.mako Thu Aug 20 18:44:35 2009 -0400
+++ b/templates/workflow/list.mako Thu Aug 06 10:29:51 2009 -0400
@@ -37,8 +37,10 @@
%for i, workflow in enumerate( workflows ):
<tr>
<td>
+ <div class="menubutton">
+ <a id="wf-${i}-popup" class="arrow" style="display: none;"><span>▼</span></a>
${workflow.name}
- <a id="wf-${i}-popup" class="popup-arrow" style="display: none;">▼</a>
+ </div>
</td>
<td>${len(workflow.latest_workflow.steps)}</td>
## <td>${str(workflow.update_time)[:19]}</td>
1
0

24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/fbad627b45ac
changeset: 2605:fbad627b45ac
user: James Taylor <james(a)jamestaylor.org>
date: Sat Aug 22 23:18:47 2009 -0400
description:
Fixing styles for history rename and share interfaces
6 file(s) affected in this change:
static/june_2007_style/base.css.tmpl
static/june_2007_style/blue/base.css
static/scripts/packed/galaxy.base.js
templates/history/rename.mako
templates/history/share.mako
templates/root/index.mako
diffs (390 lines):
diff -r abdb523727ed -r fbad627b45ac static/june_2007_style/base.css.tmpl
--- a/static/june_2007_style/base.css.tmpl Thu Aug 06 10:29:51 2009 -0400
+++ b/static/june_2007_style/base.css.tmpl Sat Aug 22 23:18:47 2009 -0400
@@ -3,6 +3,7 @@
body{font-size:75%;}
## Mixins
+
.unselectable {
user-select: none;
-moz-user-select: none;
@@ -15,8 +16,8 @@
}
## Real styles
-body
-{
+
+body {
background: $base_bg_bottom;
color: $base_text;
background-image: url(base_bg.png);
@@ -25,60 +26,55 @@
margin: 10px;
}
-img
-{
+img {
border: 0;
}
-a:link, a:visited, a:active
-{
+a:link, a:visited, a:active {
color: $link_text;
}
-h1, h2, h3, h4
-{
+h1, h2, h3, h4 {
color: $header_text;
/*text-shadow: #bbb 2px 2px 1px;*/
}
-hr
-{
+hr {
border: none;
height: 0px;
border-bottom: dotted $base_text 1px;
}
-div.toolForm
-{
- border: solid $form_border 1px;
+th {
+ text-align: left;
}
-div.toolFormTitle
-{
- font-weight: bold;
- padding: 5px;
- padding-left: 10px;
- padding-right: 10px;
- background: $form_title_bg_bottom;
- ## background-image: url(form_title_bg.png);
- background-repeat: repeat-x;
- background-position: top;
- border-bottom: solid $form_border 1px;
+div.toolForm {
+ border: solid $form_border 1px;
}
-div.toolParamHelp
-{
- color: #666;
+div.toolFormTitle {
+ font-weight: bold;
+ padding: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ background: $form_title_bg_bottom;
+ ## background-image: url(form_title_bg.png);
+ background-repeat: repeat-x;
+ background-position: top;
+ border-bottom: solid $form_border 1px;
}
-div.toolParamHelp a
-{
- color: #666;
+div.toolParamHelp {
+ color: #666;
}
-div.toolFormBody
-{
+div.toolParamHelp a {
+ color: #666;
+}
+
+div.toolFormBody {
background: $form_body_bg_bottom;
background-image: url(form_body_bg.png);
background-repeat: repeat-x;
@@ -86,8 +82,7 @@
padding: 5px 0;
}
-div.toolFormBody div.toolFormTitle
-{
+div.toolFormBody div.toolFormTitle {
background: transparent;
border: none;
font-weight: bold;
@@ -104,12 +99,10 @@
border-color: ${layout_border};
}
-div.toolHelp
-{
+div.toolHelp {
}
-div.toolHelpBody
-{
+div.toolHelpBody {
width: 100%;
overflow: auto;
}
@@ -121,15 +114,13 @@
padding-bottom: 0.25em;
}
-/* Forms */
+## Forms
-div.form
-{
+div.form {
border: solid $form_border 1px;
}
-div.form-title
-{
+div.form-title {
font-weight: bold;
padding: 5px 10px;
background: $form_title_bg_bottom;
@@ -139,53 +130,44 @@
border-bottom: solid $form_border 1px;
}
-div.form-body
-{
+div.form-body {
padding: 5px 0;
}
-div.form-row
-{
+div.form-row {
padding: 5px 10px;
}
-div.form-title-row
-{
+div.form-title-row {
padding: 5px 10px;
}
-div.repeat-group-item
-{
+div.repeat-group-item {
border-left: solid $form_border 5px;
margin-left: 10px;
margin-bottom: 10px;
}
-div.form-row-error
-{
+div.form-row-error {
background: $error_message_bg;
}
-div.form-row label
-{
+div.form-row label {
font-weight: bold;
display: block;
margin-bottom: .2em;
}
-div.form-row-input
-{
+div.form-row-input {
float: left;
width: 300px;
}
-div.form-row-input > input
-{
+div.form-row-input > input {
max-width: 300px;
}
-div.form-row-error-message
-{
+div.form-row-error-message {
width: 300px;
float: left;
color: red;
@@ -193,19 +175,17 @@
padding: 3px 0 0 1em;
}
-select, input, textarea
-{
+select, input, textarea {
font: inherit;
font-size: 115%;
}
-select, textarea, input[type="text"], input[type="file"], input[type="password"]
-{
+select, textarea, input[type="text"], input[type="file"], input[type="password"] {
-webkit-box-sizing: border-box;
max-width: 300px;
}
-/* Messages */
+## Messages
.errormessage, .warningmessage, .donemessage, .infomessage, .welcomeBlue, .welcomeRed , .screencastBox, .yellowbox, .redbox, .bluebox, .greenbox
{
diff -r abdb523727ed -r fbad627b45ac static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css Thu Aug 06 10:29:51 2009 -0400
+++ b/static/june_2007_style/blue/base.css Sat Aug 22 23:18:47 2009 -0400
@@ -10,6 +10,7 @@
a:link,a:visited,a:active{color:#303030;}
h1,h2,h3,h4{color:#023858;}
hr{border:none;height:0px;border-bottom:dotted #303030 1px;}
+th{text-align:left;}
div.toolForm{border:solid #d8b365 1px;}
div.toolFormTitle{font-weight:bold;padding:5px;padding-left:10px;padding-right:10px;background:#ebd9b2;background-repeat:repeat-x;background-position:top;border-bottom:solid #d8b365 1px;}
div.toolParamHelp{color:#666;}
diff -r abdb523727ed -r fbad627b45ac static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Thu Aug 06 10:29:51 2009 -0400
+++ b/static/scripts/packed/galaxy.base.js Sat Aug 22 23:18:47 2009 -0400
@@ -1,1 +1,1 @@
-$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,b){ens
ure_popup_helper();$(d).css("position","relative");var a=$("<div class='popupmenu' id='"+d.attr("id")+"-menu'></div>").css("position","absolute").appendTo(d);$.each(b,function(g,f){$("<div class='popupmenu-item' />").html(g).click(f).appendTo(a)});var c=function(){$(a).unbind().hide();$(document).unbind("click.popupmenu")};var e=function(f){var g=$(d).offset();$(document).bind("click.popupmenu",c);$(a).click(c).css({left:0,top:-1000}).show();$(a).css({top:0,left:0});return false};$(d).click(e)};
\ No newline at end of file
+$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){console.log(b,d);var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){console.log(g);var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)};
\ No newline at end of file
diff -r abdb523727ed -r fbad627b45ac templates/history/rename.mako
--- a/templates/history/rename.mako Thu Aug 06 10:29:51 2009 -0400
+++ b/templates/history/rename.mako Sat Aug 22 23:18:47 2009 -0400
@@ -3,39 +3,37 @@
<%def name="title()">${_('Rename History')}</%def>
<div class="toolForm">
- <div class="toolFormTitle">${_('Rename History')}</div>
+ <div class="toolFormTitle">${_('Rename')}</div>
<div class="toolFormBody">
<form action="${h.url_for( controller='history', action='rename' )}" method="post" >
- <table class="grid">
+ <div class="form-row">
+ <table>
+ <thead>
+ <tr>
+ <th>${_('Current Name')}</th>
+ <th>${_('New Name')}</th>
+ </tr>
+ </thead>
+ <tbody>
%for history in histories:
<tr>
<td>
- <div class="form-row">
- <input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
- <label>${_('Current Name')}</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- ${history.name}
- </div>
- </div>
+ <input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
+ ${history.name}
</td>
<td>
- <div class="form-row">
- <label>${_('New Name')}</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="name" value="${history.name}" size="40">
- </div>
- </div>
+ <input type="text" name="name" value="${history.name}" size="40">
</td>
</tr>
%endfor
+ </tbody>
<tr>
<td colspan="2">
- <div class="form-row">
- <input type="submit" name="history_rename_btn" value="${_('Rename Histories')}">
- </div>
+ <input type="submit" name="history_rename_btn" value="${_('Rename Histories')}">
</td>
</tr>
</table>
+ </div>
</form>
</div>
</div>
diff -r abdb523727ed -r fbad627b45ac templates/history/share.mako
--- a/templates/history/share.mako Thu Aug 06 10:29:51 2009 -0400
+++ b/templates/history/share.mako Sat Aug 22 23:18:47 2009 -0400
@@ -8,32 +8,32 @@
%if not can_change and not cannot_change and not no_change_needed:
## We are sharing histories that contain only public datasets
<form name='share' id='share' action="${h.url_for( controller="history", action='share' )}" method="post" >
- %for history in histories:
- <input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
- <div class="toolForm">
- <div class="form-row">
- <label>${_('History Name:')}</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- ${history.name}
- </div>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <label>${_('Number of Datasets:')}</label>
- <div style="float: left; width: 250px; margin-right: 10px;">
- %if len( history.datasets ) < 1:
- <div class="warningmark">${_('This history contains no data.')}</div>
- %else:
- ${len(history.datasets)}
- %endif
- </td>
- </div>
- </div>
- <div style="clear: both"></div>
- <p/>
- </div>
- %endfor
- <p/>
+ <div class="form-title-row"><b>Histories to be shared:</b></div>
+ <div class="form-row" style="padding-left: 2em;">
+ <table width="100%">
+ <thead>
+ <th>${_('History Name')}</th>
+ <th>${_('Number of Datasets')}</th>
+ </thead>
+ <tbody>
+ %for history in histories:
+ <tr>
+ <td>
+ <input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
+ ${history.name}
+ </td>
+ <td>
+ %if len( history.datasets ) < 1:
+ <div class="warningmark">${_('This history contains no data.')}</div>
+ %else:
+ ${len(history.datasets)}
+ %endif
+ </td>
+ </tr>
+ %endfor
+ </tbody>
+ </table>
+ </div>
<div style="clear: both"></div>
<div class="form-row">
<label>Galaxy user emails with which to share histories</label>
diff -r abdb523727ed -r fbad627b45ac templates/root/index.mako
--- a/templates/root/index.mako Thu Aug 06 10:29:51 2009 -0400
+++ b/templates/root/index.mako Sat Aug 22 23:18:47 2009 -0400
@@ -20,7 +20,7 @@
"Clone": function() {
galaxy_main.location = "${h.url_for( controller='history', action='clone')}";
},
- "Manage sharing": function() {
+ "Share": function() {
galaxy_main.location = "${h.url_for( controller='history', action='share' )}";
},
"Extract workflow": function() {
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/62e24f51b518
changeset: 2602:62e24f51b518
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Aug 20 12:51:39 2009 -0400
description:
Require json2.js
2 file(s) affected in this change:
static/scripts/packed/galaxy.workflow_editor.canvas.js
templates/workflow/editor.mako
diffs (19 lines):
diff -r 0517fd342fc8 -r 62e24f51b518 static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js Thu Aug 20 12:41:37 2009 -0400
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js Thu Aug 20 12:51:39 2009 -0400
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connecto
rs,function(j,k){f[h.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},enable_auto_save:function(){outer_this=this;$(".toolFormBody").find("input,textarea,select").each(function(){$(this).focus(function(){outer_this.active_form_has_changes=true})})},check_changes_in_active_form:functio
n(){if(this.active_form_has_changes){this.has_changes=true;$(".toolFormBody").find("form").each(function(){$(this).submit()});this.active_form_has_changes=false}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){this.check_changes_in_active_form();var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){l
evel_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this
.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></d
iv>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).
offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.c
ss("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_n
odes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var
g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connecto
rs,function(j,k){f[h.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},clear_active_node:function(){if(this.acti
ve_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){this.check_changes_in_active_form();var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];fo
r(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_
up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float:
right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type
=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:functi
on(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*
j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent
().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
diff -r 0517fd342fc8 -r 62e24f51b518 templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Thu Aug 20 12:41:37 2009 -0400
+++ b/templates/workflow/editor.mako Thu Aug 20 12:51:39 2009 -0400
@@ -31,6 +31,7 @@
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.hover.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.form.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.jstore-all.js')}"> </script>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/json2.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.base.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.workflow_editor.canvas.js')}"> </script>
1
0