galaxy-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
galaxy-dist commit a68c74ec8cfb: OpenID support for Galaxy.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1290006822 18000
# Node ID a68c74ec8cfbc641db4b6fe424e3f77b9f3c5d3c
# Parent 56431b214df16653a966b96bf399c7646da267b8
OpenID support for Galaxy.
--- a/eggs.ini
+++ b/eggs.ini
@@ -44,6 +44,7 @@ Paste = 1.6
PasteDeploy = 1.3.3
PasteScript = 1.7.3
pexpect = 2.4
+python_openid = 2.2.5
Routes = 1.12.3
SQLAlchemy = 0.5.6
sqlalchemy_migrate = 0.5.4
--- /dev/null
+++ b/templates/user/openid_manage.mako
@@ -0,0 +1,17 @@
+## Template generates a grid that enables user to select items.
+<%namespace file="../grid_base.mako" import="make_grid" />
+<%namespace file="login.mako" import="render_openid_form" />
+
+<%inherit file="../grid_base.mako" />
+
+<%def name="grid_body( grid )">
+ ${make_grid( grid )}
+ <h2>Associate more OpenIDs</h2>
+ ${render_openid_form( kwargs['referer'], True, kwargs['openid_providers'] )}
+</%def>
+
+<%def name="center_panel()">
+ <div style="margin: 1em;">
+ ${grid_body( grid )}
+ </div>
+</%def>
Binary file static/images/openid-16x16.gif has changed
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1953,6 +1953,12 @@ class UserAddress( object ):
html = html + '<br/>' + 'Phone: ' + self.phone
return html
+class UserOpenID( object ):
+ def __init__( self, user=None, session=None, openid=None ):
+ self.user = user
+ self.session = session
+ self.openid = openid
+
class Page( object ):
def __init__( self ):
self.id = None
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -15,6 +15,9 @@
%if trans.app.config.enable_api:
<li><a href="${h.url_for( controller='user', action='api_keys' )}">${_('Manage your API Keys')}</a> for new histories</li>
%endif
+ %if trans.app.config.enable_openid:
+ <li><a href="${h.url_for( controller='user', action='openid_manage' )}">${ ('Manage OpenIDs')}</a> linked to your account</li>
+ %endif
%else:
<li><a href="${h.url_for( controller='user', action='show_info', webapp='community' )}">${_('Manage your information')}</a></li>
%endif
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0062_user_openid_table.py
@@ -0,0 +1,48 @@
+"""
+Migration script to create table for associating sessions and users with
+OpenIDs.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+# Table to add
+
+UserOpenID_table = Table( "galaxy_user_openid", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, index=True, default=now, onupdate=now ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "openid", TEXT, index=True, unique=True ),
+ )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Create galaxy_user_openid table
+ try:
+ UserOpenID_table.create()
+ except Exception, e:
+ log.debug( "Creating galaxy_user_openid table failed: %s" % str( e ) )
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop galaxy_user_openid table
+ try:
+ UserOpenID_table.drop()
+ except Exception, e:
+ log.debug( "Dropping galaxy_user_openid table failed: %s" % str( e ) )
--- a/templates/user/login.mako
+++ b/templates/user/login.mako
@@ -1,23 +1,77 @@
-<%inherit file="/base.mako"/>
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ if context.get('webapp'):
+ webapp = context.get('webapp')
+ else:
+ webapp = 'galaxy'
+ return '/webapps/%s/base_panels.mako' % webapp
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
+
<%namespace file="/message.mako" import="render_msg" />
-%if redirect_url:
- <script type="text/javascript">
- top.location.href = '${redirect_url}';
- </script>
-%endif
+<%def name="center_panel()">
+ ${body()}
+</%def>
-%if not redirect_url and message:
- ${render_msg( message, status )}
-%endif
+<%def name="body()">
-%if not trans.user:
+ %if redirect_url:
+ <script type="text/javascript">
+ top.location.href = '${redirect_url}';
+ </script>
+ %endif
+
+ %if context.get('use_panels'):
+ <div style="margin: 1em;">
+ %else:
+ <div>
+ %endif
+
+ %if message:
+ ${render_msg( message, status )}
+ %endif
+
+ %if not trans.user:
+
+ ${render_login_form()}
+
+ %if trans.app.config.enable_openid:
+ <br/>
+ ${render_openid_form( referer, False, openid_providers )}
+ %endif
+
+ %endif
+
+ </div>
+
+</%def>
+
+<%def name="render_login_form( form_action=None )">
+
+ <%
+ if form_action is None:
+ form_action = h.url_for( controller='user', action='login', use_panels=use_panels )
+ %>
+
%if header:
${header}
%endif
<div class="toolForm"><div class="toolFormTitle">Login</div>
- <form name="login" id="login" action="${h.url_for( controller='user', action='login' )}" method="post" >
+ <form name="login" id="login" action="${form_action}" method="post" ><div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email}" size="40"/>
@@ -36,4 +90,32 @@
</div></form></div>
-%endif
+
+</%def>
+
+<%def name="render_openid_form( referer, auto_associate, openid_providers )">
+
+ <div class="toolForm">
+ <div class="toolFormTitle">OpenID Login</div>
+ <form name="openid" id="openid" action="${h.url_for( controller='user', action='openid_auth' )}" method="post" >
+ <div class="form-row">
+ <label>OpenID URL:</label>
+ <input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/>
+ <input type="hidden" name="webapp" value="${webapp}" size="40"/>
+ <input type="hidden" name="referer" value="${referer}" size="40"/>
+ <input type="hidden" name="auto_associate" value="${auto_associate}" size="40"/>
+ </div>
+ <div class="form-row">
+ Or, authenticate with your <select name="openid_provider">
+ %for provider in openid_providers.keys():
+ <option>${provider}</option>
+ %endfor
+ </select> account.
+ </div>
+ <div class="form-row">
+ <input type="submit" name="login_button" value="Login"/>
+ </div>
+ </form>
+ </div>
+
+</%def>
--- a/lib/galaxy/eggs/__init__.py
+++ b/lib/galaxy/eggs/__init__.py
@@ -321,6 +321,7 @@ class GalaxyConfig( object ):
"pbs_python": lambda: "pbs" in self.config.get( "app:main", "start_job_runners" ).split(","),
"threadframe": lambda: self.config.get( "app:main", "use_heartbeat" ),
"guppy": lambda: self.config.get( "app:main", "use_memdump" ),
+ "python_openid": lambda: self.config.get( "app:main", "enable_openid" ),
"GeneTrack": lambda: sys.version_info[:2] >= ( 2, 5 ),
"pysam": check_pysam()
}.get( egg_name, lambda: True )()
--- /dev/null
+++ b/templates/user/openid_associate.mako
@@ -0,0 +1,75 @@
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ if context.get('webapp'):
+ webapp = context.get('webapp')
+ else:
+ webapp = 'galaxy'
+ return '/webapps/%s/base_panels.mako' % webapp
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
+
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="login.mako" import="render_login_form" />
+<%namespace file="register.mako" import="render_registration_form" />
+
+<%def name="center_panel()">
+ ${body()}
+</%def>
+
+<%def name="body()">
+
+ %if context.get('use_panels'):
+ <div style="margin: 1em;">
+ %else:
+ <div>
+ %endif
+
+ %if message:
+ ${render_msg( message, status )}
+ %endif
+
+ <h2>OpenID Account Association</h2>
+ <div>
+ OpenIDs must be associated with a Galaxy account before they can be used for authentication. This only needs to be done once per OpenID. You may associate your OpenID with an existing Galaxy account, or create a new one.
+ </div>
+ <br/>
+
+ %if len( openids ) > 1:
+ <div>
+ The following OpenIDs will be associated with the account chosen or created below.
+ <ul>
+ %for openid in openids:
+ <li>${openid.openid}</li>
+ %endfor
+ </ul>
+ </div>
+ %else:
+ <div>
+ The OpenID <strong>${openids[0].openid}</strong> will be associated with the account chosen or created.
+ </div>
+ %endif
+ <br/>
+
+ <% form_action = h.url_for( use_panels=use_panels ) %>
+
+ ${render_login_form( form_action=form_action )}
+
+ <br/>
+
+ ${render_registration_form( form_action=form_action )}
+
+ </div>
+
+</%def>
--- a/templates/user/register.mako
+++ b/templates/user/register.mako
@@ -22,8 +22,18 @@
## An admin user may be creating a new user account, in which case we want to display the registration form.
## But if the current user is not an admin user, then don't display the registration form.
%if trans.user_is_admin() or not trans.user:
+ ${render_registration_form()}
+%endif
+
+<%def name="render_registration_form( form_action=None )">
+
+ <%
+ if form_action is None:
+ form_action = h.url_for( controller='user', action='create', admin_view=admin_view )
+ %>
+
<div class="toolForm">
- <form name="registration" id="registration" action="${h.url_for( controller='user', action='create', admin_view=admin_view )}" method="post" >
+ <form name="registration" id="registration" action="${form_action}" method="post" ><div class="toolFormTitle">Create account</div><div class="form-row"><label>Email address:</label>
@@ -83,4 +93,5 @@
</div></form></div>
-%endif
+
+</%def>
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -324,6 +324,10 @@ use_interactive = True
# WYSIWYG editor that is very similar to a word processor.
#enable_pages = False
+# Enable authentication via OpenID. Allows users to log in to their Galaxy
+# account by authenticating with an OpenID provider.
+#enable_openid = False
+
# Enable the (experimental! beta!) Web API. Documentation forthcoming.
#enable_api = False
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -68,6 +68,15 @@ UserAddress.table = Table( "user_address
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ) )
+UserOpenID.table = Table( "galaxy_user_openid", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, index=True, default=now, onupdate=now ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "openid", TEXT, index=True, unique=True ),
+ )
+
History.table = Table( "history", metadata,
Column( "id", Integer, primary_key=True),
Column( "create_time", DateTime, default=now ),
@@ -968,6 +977,17 @@ assign_mapper( context, UserAddress, Use
order_by=desc(UserAddress.table.c.update_time)),
) )
+assign_mapper( context, UserOpenID, UserOpenID.table,
+ properties=dict(
+ session=relation( GalaxySession,
+ primaryjoin=( UserOpenID.table.c.session_id == GalaxySession.table.c.id ),
+ backref='openids',
+ order_by=desc( UserOpenID.table.c.update_time ) ),
+ user=relation( User,
+ primaryjoin=( UserOpenID.table.c.user_id == User.table.c.id ),
+ backref='openids',
+ order_by=desc( UserOpenID.table.c.update_time ) ) ) )
+
assign_mapper( context, ValidationError, ValidationError.table )
--- a/templates/display_common.mako
+++ b/templates/display_common.mako
@@ -85,6 +85,8 @@
class_plural = "Forms"
elif a_class == model.RequestType:
class_plural = "sequencer configurations"
+ elif a_class == model.UserOpenID:
+ class_plural = "OpenIDs"
else:
class_plural = a_class.__name__ + "s"
return class_plural
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -60,6 +60,10 @@ class UniverseApplication( object ):
self.heartbeat = None
self.memdump = None
self.memory_usage = None
+ # Container for OpenID authentication routines
+ if self.config.enable_openid:
+ from galaxy.web.framework import openid_manager
+ self.openid_manager = openid_manager.OpenIDManager( self.config.openid_consumer_cache_path )
# Start the heartbeat process if configured and available
if self.config.use_heartbeat:
from galaxy.util import heartbeat
--- /dev/null
+++ b/lib/galaxy/web/framework/openid_manager.py
@@ -0,0 +1,53 @@
+"""
+Mange the OpenID consumer and related data stores.
+"""
+
+import os, pickle, logging
+
+from galaxy import eggs
+eggs.require( 'python-openid' )
+
+import openid
+from openid import oidutil
+from openid.store import filestore
+from openid.consumer import consumer
+from openid.extensions import sreg
+
+log = logging.getLogger( __name__ )
+def oidlog( message, level=0 ):
+ log.debug( message )
+oidutil.log = oidlog
+
+class OpenIDManager( object ):
+ def __init__( self, cache_path ):
+ self.session_path = os.path.join( cache_path, 'session' )
+ self.store_path = os.path.join( cache_path, 'store' )
+ for dir in self.session_path, self.store_path:
+ if not os.path.exists( dir ):
+ os.makedirs( dir )
+ self.store = filestore.FileOpenIDStore( self.store_path )
+ def get_session( self, trans ):
+ session_file = os.path.join( self.session_path, str( trans.galaxy_session.id ) )
+ if not os.path.exists( session_file ):
+ pickle.dump( dict(), open( session_file, 'w' ) )
+ return pickle.load( open( session_file ) )
+ def persist_session( self, trans, oidconsumer ):
+ session_file = os.path.join( self.session_path, str( trans.galaxy_session.id ) )
+ pickle.dump( oidconsumer.session, open( session_file, 'w' ) )
+ def get_consumer( self, trans ):
+ return consumer.Consumer( self.get_session( trans ), self.store )
+ def add_sreg( self, trans, request, required=None, optional=None ):
+ if required is None:
+ required = []
+ if optional is None:
+ optional = []
+ sreg_request = sreg.SRegRequest( required=required, optional=optional )
+ request.addExtension( sreg_request )
+ def get_sreg( self, info ):
+ return sreg.SRegResponse.fromSuccessResponse( info )
+
+ # so I don't have to expose all of openid.consumer.consumer
+ FAILURE = consumer.FAILURE
+ SUCCESS = consumer.SUCCESS
+ CANCEL = consumer.CANCEL
+ SETUP_NEEDED = consumer.SETUP_NEEDED
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -39,9 +39,11 @@ class Configuration( object ):
# Where dataset files are stored
self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root )
self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root )
+ self.openid_consumer_cache_path = resolve_path( kwargs.get( "openid_consumer_cache_path", "database/openid_consumer_cache" ), self.root )
self.cookie_path = kwargs.get( "cookie_path", "/" )
# web API
self.enable_api = string_as_bool( kwargs.get( 'enable_api', False ) )
+ self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
# Communication with a sequencer
self.enable_sequencer_communication = string_as_bool( kwargs.get( 'enable_sequencer_communication', False ) )
# dataset Track files
@@ -161,7 +163,17 @@ class Configuration( object ):
if not os.path.isdir( path ):
raise ConfigurationError("Directory does not exist: %s" % path )
# Create the directories that it makes sense to create
- for path in self.file_path, self.new_file_path, self.job_working_directory, self.cluster_files_directory, self.template_cache, self.ftp_upload_dir, self.library_import_dir, self.user_library_import_dir, self.nginx_upload_store, './static/genetrack/plots', os.path.join( self.tool_data_path, 'shared', 'jars' ):
+ for path in self.file_path, \
+ self.new_file_path, \
+ self.job_working_directory, \
+ self.cluster_files_directory, \
+ self.template_cache, \
+ self.ftp_upload_dir, \
+ self.library_import_dir, \
+ self.user_library_import_dir, \
+ self.nginx_upload_store, \
+ './static/genetrack/plots', \
+ os.path.join( self.tool_data_path, 'shared', 'jars' ):
if path not in [ None, False ] and not os.path.isdir( path ):
try:
os.makedirs( path )
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -1,9 +1,10 @@
"""
Contains the user interface in the Universe class
"""
+from galaxy.web.framework.helpers import time_ago, grids
from galaxy.web.base.controller import *
from galaxy.model.orm import *
-from galaxy import util
+from galaxy import util, model
import logging, os, string, re, smtplib, socket
from random import choice
from email.MIMEText import MIMEText
@@ -26,48 +27,337 @@ require_login_creation_template = requir
VALID_USERNAME_RE = re.compile( "^[a-z0-9\-]+$" )
+OPENID_PROVIDERS = { 'Google' : 'https://www.google.com/accounts/o8/id',
+ 'Yahoo!' : 'http://yahoo.com',
+ 'AOL/AIM' : 'http://openid.aol.com',
+ 'Flickr' : 'http://flickr.com',
+ 'Launchpad' : 'http://login.launchpad.net',
+ }
+
+class UserOpenIDGrid( grids.Grid ):
+ use_panels = False
+ title = "OpenIDs linked to your account"
+ model_class = model.UserOpenID
+ template = '/user/openid_manage.mako'
+ default_filter = { "openid" : "All" }
+ default_sort_key = "-create_time"
+ columns = [
+ grids.TextColumn( "OpenID URL", key="openid" ),
+ grids.GridColumn( "Created", key="create_time", format=time_ago ),
+ ]
+ operations = [
+ grids.GridOperation( "Delete", async_compatible=True ),
+ ]
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id )
+
class User( BaseController, UsesFormDefinitionWidgets ):
+ user_openid_grid = UserOpenIDGrid()
@web.expose
def index( self, trans, webapp='galaxy', **kwd ):
return trans.fill_template( '/user/index.mako', webapp=webapp )
@web.expose
+ def openid_auth( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ message = 'Unspecified failure authenticating via OpenID'
+ status = kwd.get( 'status', 'done' )
+ openid_url = kwd.get( 'openid_url', '' )
+ openid_provider = kwd.get( 'openid_provider', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ auto_associate = util.string_as_bool( kwd.get( 'auto_associate', False ) )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
+ action = 'login'
+ if auto_associate:
+ action = 'openid_manage'
+ if not referer:
+ referer = url_for( '/' )
+ consumer = trans.app.openid_manager.get_consumer( trans )
+ process_url = trans.request.base.rstrip( '/' ) + url_for( controller='user', action='openid_process', referer=referer, auto_associate=auto_associate )
+ if not openid_url and openid_provider and openid_provider in OPENID_PROVIDERS:
+ openid_url = OPENID_PROVIDERS[openid_provider]
+ if openid_url:
+ request = None
+ try:
+ request = consumer.begin( openid_url )
+ if request is None:
+ message = 'No OpenID services are available at %s' % openid_url
+ except Exception, e:
+ message = 'Failed to begin OpenID authentication: %s' % str( e )
+ if request is not None:
+ trans.app.openid_manager.add_sreg( trans, request, optional=[ 'nickname', 'email' ] )
+ if request.shouldSendRedirect():
+ redirect_url = request.redirectURL(
+ trans.request.base, process_url )
+ trans.app.openid_manager.persist_session( trans, consumer )
+ trans.response.send_redirect( redirect_url )
+ return
+ else:
+ form = request.htmlMarkup( trans.request.base, process_url, form_tag_attrs={'id':'openid_message','target':'_top'} )
+ trans.app.openid_manager.persist_session( trans, consumer )
+ return form
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=use_panels,
+ message=message,
+ status='error' ) )
+ @web.expose
+ def openid_process( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ auto_associate = util.string_as_bool( kwd.get( 'auto_associate', False ) )
+ action = 'login'
+ if auto_associate:
+ action = 'openid_manage'
+ if trans.app.config.bugs_email is not None:
+ contact = '<a href="mailto:%s">contact support</a>' % trans.app.config.bugs_email
+ else:
+ contact = 'contact support'
+ message = 'Verification failed for an unknown reason. Please contact support for assistance.'
+ status = 'error'
+ consumer = trans.app.openid_manager.get_consumer( trans )
+ info = consumer.complete( kwd, trans.request.url )
+ display_identifier = info.getDisplayIdentifier()
+ redirect_url = kwd.get( 'referer', url_for( '/' ) )
+ if info.status == trans.app.openid_manager.FAILURE and display_identifier:
+ message = "Login via OpenID failed. The technical reason for this follows, please include this message in your email if you need to %s to resolve this problem: %s" % ( contact, info.message )
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=True,
+ message=message,
+ status='error' ) )
+ elif info.status == trans.app.openid_manager.SUCCESS:
+ if info.endpoint.canonicalID:
+ display_identifier = info.endpoint.canonicalID
+ user_openid = trans.sa_session.query( trans.app.model.UserOpenID ).filter( trans.app.model.UserOpenID.table.c.openid == display_identifier ).first()
+ if not user_openid:
+ user_openid = trans.app.model.UserOpenID( session=trans.galaxy_session, openid=display_identifier )
+ elif not user_openid.user and user_openid.session.id != trans.galaxy_session.id:
+ user_openid.session = trans.galaxy_session
+ elif user_openid.user and not auto_associate:
+ trans.handle_user_login( user_openid.user, webapp )
+ trans.log_event( "User logged in via OpenID: %s" % display_identifier )
+ trans.response.send_redirect( redirect_url )
+ return
+ if auto_associate and trans.user:
+ # The user is already logged in and requested association from
+ # the user prefs as opposed to using the OpenID form on the
+ # login page.
+ if user_openid.user and user_openid.user.id != trans.user.id:
+ message = "The OpenID <strong>%s</strong> is already associated with another Galaxy account, <strong>%s</strong>. Please disassociate it from that account before attempting to associate it with a new account." % ( display_identifier, user_openid.user.email )
+ status = "error"
+ elif user_openid.user and user_openid.user.id == trans.user.id:
+ message = "The OpenID <strong>%s</strong> is already associated with your Galaxy account, <strong>%s</strong>." % ( display_identifier, trans.user.email )
+ status = "warning"
+ else:
+ user_openid.user_id = trans.user.id
+ trans.sa_session.add( user_openid )
+ trans.sa_session.flush()
+ trans.log_event( "User associated OpenID: %s" % display_identifier )
+ message = "The OpenID <strong>%s</strong> has been associated with your Galaxy account, <strong>%s</strong>." % ( display_identifier, trans.user.email )
+ status = "done"
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_manage',
+ use_panels=True,
+ message=message,
+ status=status ) )
+ return
+ trans.sa_session.add( user_openid )
+ trans.sa_session.flush()
+ message = "OpenID authentication was successful, but you need to associate your OpenID with a Galaxy account."
+ sreg_resp = trans.app.openid_manager.get_sreg( info )
+ try:
+ username = sreg_resp.get( 'nickname', '' )
+ except AttributeError:
+ username = ''
+ try:
+ email = sreg_resp.get( 'email', '' )
+ except AttributeError:
+ email = ''
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_associate',
+ use_panels=True,
+ username=username,
+ email=email,
+ message=message,
+ status='warning' ) )
+ elif info.status == trans.app.openid_manager.CANCEL:
+ message = "Login via OpenID was cancelled by an action at the OpenID provider's site."
+ status = "warning"
+ elif info.status == trans.app.openid_manager.SETUP_NEEDED:
+ if info.setup_url:
+ return trans.response.send_redirect( info.setup_url )
+ else:
+ message = "Unable to log in via OpenID. Setup at the provider is required before this OpenID can be used. Please visit your provider's site to complete this step."
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=True,
+ message=message,
+ status=status ) )
+ @web.expose
+ def openid_associate( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ email = kwd.get( 'email', '' )
+ username = kwd.get( 'username', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ params = util.Params( kwd )
+ admin_view = util.string_as_bool( params.get( 'admin_view', False ) )
+ openids = trans.galaxy_session.openids
+ if not openids:
+ return trans.show_error_message( 'You have not successfully completed an OpenID authentication in this session. You can do so on the <a href="%s">login</a> page.' % url_for( controller='user', action='login', use_panels=use_panels ) )
+ elif admin_view:
+ return trans.show_error_message( 'Associating OpenIDs with accounts cannot be done by administrators.' )
+ if kwd.get( 'login_button', False ):
+ message, status, user, success = self.__validate_login( trans, webapp, **kwd )
+ if success:
+ for openid in openids:
+ openid.user = user
+ trans.sa_session.add( openid )
+ trans.sa_session.flush()
+ for openid in openids:
+ trans.log_event( "User associated OpenID: %s" % openid.openid )
+ redirect_url = referer
+ if not redirect_url:
+ redirect_url = url_for( '/' )
+ trans.response.send_redirect( redirect_url )
+ return
+ if kwd.get( 'create_user_button', False ):
+ password = kwd.get( 'password', '' )
+ confirm = kwd.get( 'confirm', '' )
+ subscribe = params.get( 'subscribe', '' )
+ subscribe_checked = CheckboxField.is_checked( subscribe )
+ error = ''
+ if not trans.app.config.allow_user_creation and not trans.user_is_admin():
+ error = 'User registration is disabled. Please contact your Galaxy administrator for an account.'
+ else:
+ # Check email and password validity
+ error = self.__validate( trans, params, email, password, confirm, username, webapp )
+ if not error:
+ # all the values are valid
+ message, status, user, success = self.__register( trans, webapp, email, password, username, subscribe_checked, kwd )
+ if success:
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ for openid in openids:
+ openid.user = user
+ trans.sa_session.add( openid )
+ trans.sa_session.flush()
+ for openid in openids:
+ trans.log_event( "User associated OpenID: %s" % openid.openid )
+ redirect_url = referer
+ if not redirect_url:
+ redirect_url = url_for( '/' )
+ trans.response.send_redirect( redirect_url )
+ else:
+ message = error
+ status = 'error'
+ if webapp == 'galaxy':
+ user_info_select, user_info_form, widgets = self.__user_info_ui( trans, **kwd )
+ else:
+ user_info_select = []
+ user_info_form = []
+ widgets = []
+ return trans.fill_template( '/user/openid_associate.mako',
+ webapp=webapp,
+ email=email,
+ password='',
+ confirm='',
+ username=username,
+ header='',
+ use_panels=use_panels,
+ redirect_url='',
+ referer='',
+ refresh_frames=[],
+ message=message,
+ status=status,
+ active_view="user",
+ subscribe_checked=False,
+ admin_view=False,
+ user_info_select=user_info_select,
+ user_info_form=user_info_form,
+ widgets=widgets,
+ openids=openids )
+ @web.expose
+ @web.require_login( 'manage OpenIDs' )
+ def openid_disassociate( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ params = util.Params( kwd )
+ ids = params.get( 'id', None )
+ message = params.get( 'message', None )
+ status = params.get( 'status', None )
+ use_panels = params.get( 'use_panels', False )
+ user_openids = []
+ if not ids:
+ message = 'You must select at least one OpenID to disassociate from your Galaxy account.'
+ status = 'error'
+ else:
+ ids = util.listify( params.id )
+ for id in ids:
+ id = trans.security.decode_id( id )
+ user_openid = trans.sa_session.query( trans.app.model.UserOpenID ).get( int( id ) )
+ if not user_openid or ( trans.user.id != user_openid.user_id ):
+ message = 'The selected OpenID(s) are not associated with your Galaxy account.'
+ status = 'error'
+ user_openids = []
+ break
+ user_openids.append( user_openid )
+ if user_openids:
+ deleted_urls = []
+ for user_openid in user_openids:
+ trans.sa_session.delete( user_openid )
+ deleted_urls.append( user_openid.openid )
+ trans.sa_session.flush()
+ for deleted_url in deleted_urls:
+ trans.log_event( "User disassociated OpenID: %s" % deleted_url )
+ message = '%s OpenIDs were disassociated from your Galaxy account.' % len( ids )
+ status = 'done'
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_manage',
+ use_panels=use_panels,
+ message=message,
+ status=status ) )
+ @web.expose
+ @web.require_login( 'manage OpenIDs' )
+ def openid_manage( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ use_panels = kwd.get( 'use_panels', False )
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if operation == "delete":
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_disassociate',
+ use_panels=use_panels,
+ id=kwd['id'] ) )
+ kwd['referer'] = url_for( controller='user', action='openid_manage', use_panels=True )
+ kwd['openid_providers'] = OPENID_PROVIDERS
+ return self.user_openid_grid( trans, **kwd )
+ @web.expose
def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ):
referer = kwd.get( 'referer', trans.request.referer )
- use_panels = util.string_as_bool( kwd.get( 'use_panels', True ) )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
header = ''
user = None
email = kwd.get( 'email', '' )
if kwd.get( 'login_button', False ):
- password = kwd.get( 'password', '' )
- referer = kwd.get( 'referer', '' )
if webapp == 'galaxy' and not refresh_frames:
if trans.app.config.require_login:
refresh_frames = [ 'masthead', 'history', 'tools' ]
else:
refresh_frames = [ 'masthead', 'history' ]
- user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
- if not user:
- message = "No such user"
- status = 'error'
- elif user.deleted:
- message = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
- status = 'error'
- elif user.external:
- message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
- status = 'error'
- elif not user.check_password( password ):
- message = "Invalid password"
- status = 'error'
- else:
- trans.handle_user_login( user, webapp )
- trans.log_event( "User logged in" )
- message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
- ( user.email, referer, url_for( '/' ) )
- if trans.app.config.require_login:
- message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' )
+ message, status, user, success = self.__validate_login( trans, webapp, **kwd )
+ if success and referer:
redirect_url = referer
+ elif success:
+ redirect_url = url_for( '/' )
if not user and trans.app.config.require_login:
if trans.app.config.allow_user_creation:
header = require_login_creation_template % web.url_for( action='create' )
@@ -83,7 +373,37 @@ class User( BaseController, UsesFormDefi
refresh_frames=refresh_frames,
message=message,
status=status,
+ openid_providers=OPENID_PROVIDERS,
active_view="user" )
+ def __validate_login( self, trans, webapp='galaxy', **kwd ):
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ email = kwd.get( 'email', '' )
+ password = kwd.get( 'password', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ success = False
+ user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
+ if not user:
+ message = "No such user"
+ status = 'error'
+ elif user.deleted:
+ message = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
+ status = 'error'
+ elif user.external:
+ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
+ status = 'error'
+ elif not user.check_password( password ):
+ message = "Invalid password"
+ status = 'error'
+ else:
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User logged in" )
+ message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
+ ( user.email, referer, url_for( '/' ) )
+ if trans.app.config.require_login:
+ message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' )
+ success = True
+ return ( message, status, user, success )
@web.expose
def logout( self, trans, webapp='galaxy' ):
if webapp == 'galaxy':
@@ -138,54 +458,25 @@ class User( BaseController, UsesFormDefi
error = self.__validate( trans, params, email, password, confirm, username, webapp )
if not error:
# all the values are valid
- user = trans.app.model.User( email=email )
- user.set_password_cleartext( password )
- user.username = username
- trans.sa_session.add( user )
- trans.sa_session.flush()
- trans.app.security_agent.create_private_user_role( user )
- message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
- if webapp == 'galaxy':
- # We set default user permissions, before we log in and set the default history permissions
- trans.app.security_agent.user_set_default_permissions( user,
- default_access_private=trans.app.config.new_user_dataset_access_role_default_private )
- # save user info
- self.__save_user_info( trans, user, action='create', new_user=True, **kwd )
- if subscribe_checked:
- # subscribe user to email list
- if trans.app.config.smtp_server is None:
- error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
- else:
- msg = MIMEText( 'Join Mailing list.\n' )
- to = msg[ 'To' ] = trans.app.config.mailing_join_addr
- frm = msg[ 'From' ] = email
- msg[ 'Subject' ] = 'Join Mailing List'
- try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
- except:
- error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
- if not error and not admin_view:
- # The handle_user_login() method has a call to the history_set_default_permissions() method
- # (needed when logging in with a history), user needs to have default permissions set before logging in
- trans.handle_user_login( user, webapp )
- trans.log_event( "User created a new account" )
- trans.log_event( "User logged in" )
- elif not error:
- trans.response.send_redirect( web.url_for( controller='admin',
- action='users',
- message='Created new user account (%s)' % user.email,
- status='done' ) )
- elif not admin_view:
+ message, status, user, success = self.__register( trans, webapp, email, password, username, subscribe_checked, kwd )
+ if success and not admin_view and webapp != 'galaxy':
# Must be logging into the community space webapp
trans.handle_user_login( user, webapp )
- if not error:
- redirect_url = referer
- if error:
- message=error
- status='error'
+ redirect_url = referer
+ if success and not admin_view:
+ # The handle_user_login() method has a call to the history_set_default_permissions() method
+ # (needed when logging in with a history), user needs to have default permissions set before logging in
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ elif success:
+ trans.response.send_redirect( web.url_for( controller='admin',
+ action='users',
+ message='Created new user account (%s)' % user.email,
+ status='done' ) )
+ else:
+ message = error
+ status = 'error'
if webapp == 'galaxy':
user_info_select, user_info_form, widgets = self.__user_info_ui( trans, **kwd )
else:
@@ -209,6 +500,57 @@ class User( BaseController, UsesFormDefi
refresh_frames=refresh_frames,
message=message,
status=status )
+ def __register( self, trans, webapp, email, password, username, subscribe_checked, kwd ):
+ status = kwd.get( 'status', 'done' )
+ admin_view = util.string_as_bool( kwd.get( 'admin_view', False ) )
+ user = trans.app.model.User( email=email )
+ user.set_password_cleartext( password )
+ user.username = username
+ trans.sa_session.add( user )
+ trans.sa_session.flush()
+ trans.app.security_agent.create_private_user_role( user )
+ error = ''
+ if webapp == 'galaxy':
+ # We set default user permissions, before we log in and set the default history permissions
+ trans.app.security_agent.user_set_default_permissions( user,
+ default_access_private=trans.app.config.new_user_dataset_access_role_default_private )
+ # save user info
+ self.__save_user_info( trans, user, action='create', new_user=True, **kwd )
+ if subscribe_checked:
+ # subscribe user to email list
+ if trans.app.config.smtp_server is None:
+ error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
+ else:
+ msg = MIMEText( 'Join Mailing list.\n' )
+ to = msg[ 'To' ] = trans.app.config.mailing_join_addr
+ frm = msg[ 'From' ] = email
+ msg[ 'Subject' ] = 'Join Mailing List'
+ try:
+ s = smtplib.SMTP()
+ s.connect( trans.app.config.smtp_server )
+ s.sendmail( frm, [ to ], msg.as_string() )
+ s.close()
+ except:
+ error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
+ if not error and not admin_view:
+ # The handle_user_login() method has a call to the history_set_default_permissions() method
+ # (needed when logging in with a history), user needs to have default permissions set before logging in
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ elif not error:
+ trans.response.send_redirect( web.url_for( controller='admin',
+ action='users',
+ message='Created new user account (%s)' % user.email,
+ status='done' ) )
+ if error:
+ message = error
+ status = 'error'
+ success = False
+ else:
+ message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
+ success = True
+ return ( message, status, user, success )
def __save_user_info(self, trans, user, action, new_user=True, **kwd):
'''
This method saves the user information for new users as well as editing user
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -29,12 +29,19 @@
##
<%def name="center_panel()">
- ${make_grid( grid )}
+ ${self.grid_body( grid )}
</%def>
## Render the grid's basic elements. Each of these elements can be subclassed.
<%def name="body()">
- ${make_grid( grid )}
+ ${self.grid_body( grid )}
+</%def>
+
+## Because body() is special and always exists even if not explicitly defined,
+## it's not possible to override body() in the topmost template in the chain.
+## Because of this, override grid_body() instead.
+<%def name="grid_body( grid )">
+ ${self.make_grid( grid )}
</%def><%def name="title()">${grid.title}</%def>
1
0
galaxy-dist commit 1bf064c8ab88: Fixed functional tests and samples grid alignment bug
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289928056 18000
# Node ID 1bf064c8ab88621dd58890f6cd56ad4900d10d6b
# Parent 2e2ee0289d67d244954aa05bfe315dbb5ff413eb
Fixed functional tests and samples grid alignment bug
--- a/test/functional/test_sample_tracking.py
+++ b/test/functional/test_sample_tracking.py
@@ -341,7 +341,7 @@ class TestFormsAndRequests( TwillTestCas
request_id=self.security.encode_id( request1.id ),
strings_displayed=[ 'History of sequencing request "%s"' % request1.name,
request1.states.NEW,
- 'Request created' ],
+ 'Sequencing request created' ],
strings_not_displayed=[ request1.states.SUBMITTED,
request1.states.COMPLETE,
request1.states.REJECTED ] )
@@ -412,7 +412,7 @@ class TestFormsAndRequests( TwillTestCas
self.add_samples( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
sample_value_tuples=sample_value_tuples,
- strings_displayed=[ 'Add Samples to Request "%s"' % request1.name,
+ strings_displayed=[ 'Add Samples to Sequencing Request "%s"' % request1.name,
'<input type="text" name="sample_0_name" value="Sample_1" size="10"/>' ], # sample name input field
strings_displayed_after_submit=strings_displayed_after_submit )
# check the new sample field values on the request page
@@ -446,7 +446,7 @@ class TestFormsAndRequests( TwillTestCas
self.edit_samples( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
sample_value_tuples=new_sample_value_tuples,
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name,
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name,
'<input type="text" name="sample_0_name" value="Sample1" size="10"/>' ], # sample name input field
strings_displayed_after_submit=strings_displayed_after_submit )
# check the changed sample field values on the request page
@@ -465,14 +465,14 @@ class TestFormsAndRequests( TwillTestCas
self.submit_request( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
request_name=request1.name,
- strings_displayed_after_submit=[ 'The request has been submitted.' ] )
+ strings_displayed_after_submit=[ 'The sequencing request has been submitted.' ] )
refresh( request1 )
# Make sure the request is showing in the 'submitted' filter
self.check_request_grid( cntrller='requests',
state=request1.states.SUBMITTED,
strings_displayed=[ request1.name ] )
# Make sure the request's state is now set to 'submitted'
- assert request1.state is not request1.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
+ assert request1.state is not request1.states.SUBMITTED, "The state of the sequencing request '%s' should be set to '%s'" \
% ( request1.name, request1.states.SUBMITTED )
# the sample state should appear once for each sample
strings_displayed_count = [ ( request1.type.states[0].name, len( request1.samples ) ) ]
@@ -485,8 +485,8 @@ class TestFormsAndRequests( TwillTestCas
strings_displayed_count=strings_displayed_count,
strings_not_displayed=strings_not_displayed )
strings_displayed=[ 'History of sequencing request "%s"' % request1.name,
- 'Request submitted by %s' % regular_user1.email,
- 'Request created' ]
+ 'Sequencing request submitted by %s' % regular_user1.email,
+ 'Sequencing request created' ]
strings_displayed_count = [ ( request1.states.SUBMITTED, 1 ) ]
self.view_request_history( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
@@ -519,7 +519,7 @@ class TestFormsAndRequests( TwillTestCas
self.add_bar_codes( cntrller='requests_admin',
request_id=self.security.encode_id( request1.id ),
bar_codes=bar_codes,
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name ],
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name ],
strings_displayed_after_submit=strings_displayed_after_submit )
# the second sample state should appear once for each sample
strings_displayed_count = [ ( request1.type.states[1].name, len( request1.samples ) ),
@@ -538,7 +538,7 @@ class TestFormsAndRequests( TwillTestCas
# check history of each sample
for sample in request1.samples:
strings_displayed = [ 'Events for Sample "%s"' % sample.name,
- 'Request submitted and sample state set to %s' % request1.type.states[0].name,
+ 'Sequencing request submitted and sample state set to %s' % request1.type.states[0].name,
request1.type.states[0].name,
request1.type.states[1].name ]
self.view_sample_history( cntrller='requests_admin',
@@ -558,9 +558,9 @@ class TestFormsAndRequests( TwillTestCas
if index > 1:
# status message
if index == len( request_type1.states ) - 1:
- status_msg = 'All samples of this request are in the final sample state (%s).' % state.name
+ status_msg = 'All samples of this sequencing request are in the final sample state (%s).' % state.name
else:
- status_msg = 'All samples of this request are in the (%s) sample state. ' % state.name
+ status_msg = 'All samples of this sequencing request are in the (%s) sample state. ' % state.name
# check email notification message
email_msg = ''
if state.id in [ email_state.id for email_state in email_notification_sample_states ]:
@@ -568,7 +568,7 @@ class TestFormsAndRequests( TwillTestCas
self.change_sample_state( request_id=self.security.encode_id( request1.id ),
sample_ids=[ sample.id for sample in request1.samples ],
new_sample_state_id=self.security.encode_id( state.id ),
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name ],
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name ],
strings_displayed_after_submit = [ status_msg, email_msg ] )
# check request history page
if index == len( request_type1.states ) - 1:
@@ -584,7 +584,7 @@ class TestFormsAndRequests( TwillTestCas
self.check_request_grid( cntrller='requests_admin',
state='Complete',
strings_displayed=[ request1.name ] )
- assert request1.state is not request1.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
+ assert request1.state is not request1.states.COMPLETE, "The state of the sequencing request '%s' should be set to '%s'" \
% ( request1.name, request1.states.COMPLETE )
# def test_045_admin_create_request_on_behalf_of_regular_user( self ):
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -113,27 +113,23 @@
</script></%def>
-<%def name="render_editable_sample_row( cntrller, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )">
+<%def name="render_editable_sample_row( cntrller, request, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )"><%
+ trans.sa_session.refresh( request )
is_admin = cntrller == 'requests_admin' and trans.user_is_admin()
+ is_rejected = request.is_rejected
+ is_complete = request.is_complete
+ is_submitted = request.is_submitted
+ is_unsubmitted = request.is_unsubmitted
if sample:
- trans.sa_session.refresh( sample.request )
- is_complete = sample.request.is_complete
- is_rejected = request.is_rejected
- is_submitted = sample.request.is_submitted
- is_unsubmitted = sample.request.is_unsubmitted
can_delete_samples = editing_samples and request.samples and ( ( is_admin and not is_complete ) or is_unsubmitted )
display_checkboxes = editing_samples and ( is_complete or is_rejected or is_submitted )
- display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
display_datasets = request.samples and ( is_complete or is_submitted )
else:
- is_complete = False
- is_submitted = False
- is_unsubmitted = False
can_delete_samples = False
display_checkboxes = False
- display_bar_code = False
display_datasets = False
+ display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
%><%
if display_checkboxes and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
@@ -152,15 +148,13 @@
</td>
%if display_bar_code:
<td valign="top">
- %if is_admin:
+ %if is_admin and is_submitted:
<input type="text" name="sample_${sample_widget_index}_bar_code" value="${sample_widget['bar_code']}" size="10"/>
%else:
${sample_widget['bar_code']}
<input type="hidden" name="sample_${sample_widget_index}_bar_code" value="${sample_widget['bar_code']}"/>
%endif
</td>
- %else:
- <td></td>
%endif
%if sample:
%if is_unsubmitted:
@@ -305,7 +299,7 @@
sample = None
%>
%if editing_samples:
- <tr>${render_editable_sample_row( cntrller, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
+ <tr>${render_editable_sample_row( cntrller, request, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
%elif sample:
<tr><td>
@@ -401,7 +395,7 @@
</tr>
%else:
## The Add sample button was clicked for this sample_widget
- <tr>${render_editable_sample_row( cntrller, None, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
+ <tr>${render_editable_sample_row( cntrller, request, None, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
%endif
%endfor
</tbody>
1
0
galaxy-dist commit 918a25ed14f5: Bug fix due to my last commit - Requests do not have supported_field_types, FormDefinitions do.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1290008781 18000
# Node ID 918a25ed14f5427f70970b0c436159fc58fd111e
# Parent 7bded9108bd8297ea609e9ec06bbe516b5f0b83a
Bug fix due to my last commit - Requests do not have supported_field_types, FormDefinitions do.
--- a/lib/galaxy/web/controllers/forms.py
+++ b/lib/galaxy/web/controllers/forms.py
@@ -601,7 +601,7 @@ class Forms( BaseController ):
for ft in trans.model.Sample.supported_field_types:
self.fieldtype.add_option( ft.__name__, ft.__name__ )
else:
- for ft in trans.model.Request.supported_field_types:
+ for ft in trans.model.FormDefinition.supported_field_types:
self.fieldtype.add_option( ft.__name__, ft__name__ )
self.required = SelectField('field_required_'+str(index), display='radio')
self.required.add_option('Required', 'required')
@@ -641,7 +641,7 @@ class Forms( BaseController ):
else:
self.fieldtype.add_option( ft.__name__, ft.__name__ )
else:
- for ft in trans.model.Request.supported_field_types:
+ for ft in trans.model.FormDefinition.supported_field_types:
if ft.__name__ == field[ 'type' ]:
self.fieldtype.add_option( ft.__name__, ft.__name__, selected=True )
if ft == 'SelectField':
1
0
galaxy-dist commit 2e2ee0289d67: Fix BLAST+ regression from changeset 535d276c92bc (loc file columns)
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User peterjc <p.j.a.cock(a)googlemail.com>
# Date 1289925107 0
# Node ID 2e2ee0289d67d244954aa05bfe315dbb5ff413eb
# Parent d2d0c199c20ddf942e1e2587dc9aede8acd9cebc
Fix BLAST+ regression from changeset 535d276c92bc (loc file columns)
--- a/tools/ncbi_blast_plus/ncbi_blastn_wrapper.xml
+++ b/tools/ncbi_blast_plus/ncbi_blastn_wrapper.xml
@@ -40,10 +40,13 @@ blastn
</param><when value="db"><param name="database" type="select" label="Nucleotide BLAST database">
- <!-- <options from_data_table="blastdb" /> -->
+ <!-- The BLAST loc file has three columns:
+ column 0 is an identifier (not used here, see legacy megablast wrapper),
+ column 1 is the caption (show this to the user),
+ column 2 is the database path (given to BLAST+) --><options from_file="blastdb.loc">
- <column name="name" index="2"/>
- <column name="value" index="0"/>
+ <column name="name" index="1"/>
+ <column name="value" index="2"/></options></param><param name="subject" type="hidden" value="" />
--- a/tools/ncbi_blast_plus/ncbi_blastp_wrapper.xml
+++ b/tools/ncbi_blast_plus/ncbi_blastp_wrapper.xml
@@ -41,10 +41,13 @@ blastp
</param><when value="db"><param name="database" type="select" label="Protein BLAST database">
- <!-- <options from_data_table="blastdb_p" /> -->
+ <!-- The BLAST loc file has three columns:
+ column 0 is an identifier (not used),
+ column 1 is the caption (show this to the user),
+ column 2 is the database path (given to BLAST+) --><options from_file="blastdb_p.loc">
- <column name="name" index="2"/>
- <column name="value" index="0"/>
+ <column name="name" index="1"/>
+ <column name="value" index="2"/></options></param><param name="subject" type="hidden" value="" />
--- a/tools/ncbi_blast_plus/ncbi_tblastx_wrapper.xml
+++ b/tools/ncbi_blast_plus/ncbi_tblastx_wrapper.xml
@@ -39,10 +39,13 @@ tblastx
</param><when value="db"><param name="database" type="select" label="Nucleotide BLAST database">
- <!-- <options from_data_table="blastdb" /> -->
+ <!-- The BLAST loc file has three columns:
+ column 0 is an identifier (not used here, see legacy megablast wrapper),
+ column 1 is the caption (show this to the user),
+ column 2 is the database path (given to BLAST+) --><options from_file="blastdb.loc">
- <column name="name" index="2"/>
- <column name="value" index="0"/>
+ <column name="name" index="1"/>
+ <column name="value" index="2"/></options></param><param name="subject" type="hidden" value="" />
--- a/tools/ncbi_blast_plus/ncbi_blastx_wrapper.xml
+++ b/tools/ncbi_blast_plus/ncbi_blastx_wrapper.xml
@@ -40,10 +40,13 @@ blastx
</param><when value="db"><param name="database" type="select" label="Protein BLAST database">
- <!-- <options from_data_table="blastdb_p" /> -->
+ <!-- The BLAST loc file has three columns:
+ column 0 is an identifier (not used),
+ column 1 is the caption (show this to the user),
+ column 2 is the database path (given to BLAST+) --><options from_file="blastdb_p.loc">
- <column name="name" index="2"/>
- <column name="value" index="0"/>
+ <column name="name" index="1"/>
+ <column name="value" index="2"/></options></param><param name="subject" type="hidden" value="" />
--- a/tools/ncbi_blast_plus/ncbi_tblastn_wrapper.xml
+++ b/tools/ncbi_blast_plus/ncbi_tblastn_wrapper.xml
@@ -40,10 +40,13 @@ tblastn
</param><when value="db"><param name="database" type="select" label="Nucleotide BLAST database">
- <!-- <options from_data_table="blastdb" /> -->
+ <!-- The BLAST loc file has three columns:
+ column 0 is an identifier (not used here, see legacy megablast wrapper),
+ column 1 is the caption (show this to the user),
+ column 2 is the database path (given to BLAST+) --><options from_file="blastdb.loc">
- <column name="name" index="2"/>
- <column name="value" index="0"/>
+ <column name="name" index="1"/>
+ <column name="value" index="2"/></options></param><param name="subject" type="hidden" value="" />
1
0
galaxy-dist commit 394d8186f666: tool_form: Make radio and select box labels explicitly inline. Workflow: add colons after parameter names where appropriate. Fixes #419
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1289929775 18000
# Node ID 394d8186f666b506cd0a93aefb7a079e0c9ec59b
# Parent 1bf064c8ab88621dd58890f6cd56ad4900d10d6b
tool_form: Make radio and select box labels explicitly inline. Workflow: add colons after parameter names where appropriate. Fixes #419
--- a/static/june_2007_style/base.css.tmpl
+++ b/static/june_2007_style/base.css.tmpl
@@ -210,6 +210,10 @@ div.form-row label {
margin-bottom: .2em;
}
+div.form-row label.inline {
+ display: inline;
+}
+
div.form-row-input {
float: left;
}
--- a/templates/workflow/editor_tool_form.mako
+++ b/templates/workflow/editor_tool_form.mako
@@ -7,8 +7,8 @@ from galaxy.util.expressions import Expr
<% ctx = ExpressionContext( values, ctx ) %>
%for input_index, input in enumerate( inputs.itervalues() ):
%if input.type == "repeat":
- <div class="repeat-group">
- <div class="form-title-row"><b>${input.title_plural}</b></div>
+ <div class="repeat-group form-row">
+ <label>${input.title_plural}:</label><% repeat_values = values[input.name] %>
%for i in range( len( repeat_values ) ):
<%
@@ -19,7 +19,7 @@ from galaxy.util.expressions import Expr
index = repeat_values[i]['__index__']
%><div class="repeat-group-item">
- <div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
+ <div class="form-title-row"><label>${input.title} ${i + 1}</label></div>
${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", ctx )}
<div class="form-row"><input type="submit" name="${prefix}${input.name}_${index}_remove" value="Remove ${input.title} ${i+1}"></div></div>
@@ -63,7 +63,7 @@ from galaxy.util.expressions import Expr
%else:
%if isinstance( value, RuntimeValue ):
<label>
- ${param.get_label()}
+ ${param.get_label()}:
<span class="popupmenu"><button type="submit" name="make_buildtime" value="${prefix}${param.name}">Set in advance</button></span>
@@ -73,7 +73,7 @@ from galaxy.util.expressions import Expr
</div>
%else:
<label>
- ${param.get_label()}
+ ${param.get_label()}:
%if allow_runtime:
<span class="popupmenu"><button type="submit" name="make_runtime" value="${prefix}${param.name}">Set at runtime</button>
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -248,16 +248,16 @@ class SelectField(BaseField):
>>> t.add_option( "tuti", 1 )
>>> t.add_option( "fruity", "x" )
>>> print t.get_html()
- <div><input type="radio" name="foo" value="1" id="foo|1"><label for="foo|1">tuti</label></div>
- <div><input type="radio" name="foo" value="x" id="foo|x"><label for="foo|x">fruity</label></div>
+ <div><input type="radio" name="foo" value="1" id="foo|1"><label class="inline" for="foo|1">tuti</label></div>
+ <div><input type="radio" name="foo" value="x" id="foo|x"><label class="inline" for="foo|x">fruity</label></div>
>>> t = SelectField( "bar", multiple=True, display="checkboxes" )
>>> t.add_option( "automatic", 3 )
>>> t.add_option( "bazooty", 4, selected=True )
>>> print t.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="bar"></div>
- <div><input type="checkbox" name="bar" value="3" id="bar|3"><label for="bar|3">automatic</label></div>
- <div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label for="bar|4">bazooty</label></div>
+ <div><input type="checkbox" name="bar" value="3" id="bar|3"><label class="inline" for="bar|3">automatic</label></div>
+ <div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label class="inline" for="bar|4">bazooty</label></div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=[], size=None ):
self.name = name
@@ -302,7 +302,7 @@ class SelectField(BaseField):
selected_text = ""
if selected:
selected_text = " checked='checked'"
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style, prefix, self.name, escaped_value, uniq_id, selected_text, self.get_disabled_str( disabled ), uniq_id, text ) )
ctr += 1
return "\n".join( rval )
@@ -318,7 +318,7 @@ class SelectField(BaseField):
selected_text = ""
if selected:
selected_text = " checked='checked'"
- rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
+ rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style,
prefix,
self.name,
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -39,6 +39,7 @@ div.form-title-row{padding:5px 10px;}
div.repeat-group-item{border-left:solid #d8b365 5px;margin-left:10px;margin-bottom:10px;}
div.form-row-error{background:#FFCCCC;}
div.form-row label{font-weight:bold;display:block;margin-bottom:.2em;}
+div.form-row label.inline{display:inline;}
div.form-row-input{float:left;}
div.form-row-input label{font-weight:normal;display:inline;}
div.form-row-error-message{width:300px;float:left;color:red;font-weight:bold;padding:3px 0 0 1em;}
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -515,14 +515,14 @@ class SelectToolParameter( ToolParameter
blah
>>> print p.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x" id="blah|x"><label for="blah|x">I am X</label></div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
- <div><input type="checkbox" name="blah" value="z" id="blah|z" checked='checked'><label for="blah|z">I am Z</label></div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x"><label class="inline" for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label class="inline" for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z" checked='checked'><label class="inline" for="blah|z">I am Z</label></div>
>>> print p.get_html( value=["x","y"])
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x" id="blah|x" checked='checked'><label for="blah|x">I am X</label></div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
- <div><input type="checkbox" name="blah" value="z" id="blah|z"><label for="blah|z">I am Z</label></div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x" checked='checked'><label class="inline" for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label class="inline" for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z"><label class="inline" for="blah|z">I am Z</label></div>
>>> print p.to_param_dict_string( ["y", "z"] )
y,z
"""
1
0
galaxy-dist commit 02f6c9dae26e: Data libraries: Fix 'import from current history' showing metadata files that are not visible. Also fix this same issue for 'Copy history items' feature. Do this by adding new 'visible_datasets' mapping property for HDAs. Checkbox labels for both features can now be clicked.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1289852143 18000
# Node ID 02f6c9dae26e9aef40a44bc151ed07b457715839
# Parent 0505090dbbe610741cacd7a9a1c2e79b8cc9ea5c
Data libraries: Fix 'import from current history' showing metadata files that are not visible. Also fix this same issue for 'Copy history items' feature. Do this by adding new 'visible_datasets' mapping property for HDAs. Checkbox labels for both features can now be clicked.
--- a/templates/root/index.mako
+++ b/templates/root/index.mako
@@ -40,7 +40,7 @@
"Show Hidden Datasets": function() {
galaxy_history.location = "${h.url_for( controller='root', action='history', show_hidden=True)}";
},
- "Show structure": function() {
+ "Show Structure": function() {
galaxy_main.location = "${h.url_for( controller='history', action='display_structured' )}";
},
"Export to File": function() {
--- a/templates/library/common/common.mako
+++ b/templates/library/common/common.mako
@@ -427,14 +427,11 @@
<input type="hidden" name="upload_option" value="import_from_history"/><input type="hidden" name="ldda_message" value="${ldda_message}"/><%
+ role_ids_selected = ''
if roles_select_list:
- role_ids_selected = roles_select_list.get_selected( return_value=True, multi=True )
- if role_ids_selected:
- role_ids_selected = ','.join( role_ids_selected )
- else:
- role_ids_selected = ''
- else:
- role_ids_selected = ''
+ selected = roles_select_list.get_selected( return_value=True, multi=True )
+ if selected:
+ role_ids_selected = ','.join( selected )
%><input type="hidden" name="roles" value="${role_ids_selected}"/>
%if replace_dataset not in [ None, 'None' ]:
@@ -450,9 +447,11 @@
${render_template_field( field, render_as_hidden=True )}
%endfor
%endif
- %for hda in history.active_datasets:
+ %for hda in history.visible_datasets:
+ <% encoded_id = trans.security.encode_id( hda.id ) %><div class="form-row">
- <input name="hda_ids" value="${trans.security.encode_id( hda.id )}" type="checkbox"/>${hda.hid}: ${hda.name}
+ <input name="hda_ids" id="hist_${encoded_id}" value="${encoded_id}" type="checkbox"/>
+ <label for="hist_${encoded_id}" style="display: inline;font-weight:normal;">${hda.hid}: ${hda.name}</label></div>
%endfor
<div class="form-row">
@@ -460,9 +459,7 @@
</div></form>
%else:
- <p/>
- Your current history is empty
- <p/>
+ <p>Your current history is empty</p>
%endif
</div></div>
--- a/templates/dataset/copy_view.mako
+++ b/templates/dataset/copy_view.mako
@@ -17,22 +17,29 @@
</p>
%endif
<p>
+ <div class="infomessage">Select any number of source history items and any number of target histories and click "Copy History Items" to add a copy of each selected history item to each selected target history.</div>
+ <div style="clear: both"></div>
+</p>
+<p><div class="toolForm"><form>
- <div style="float: left; width: 50%; padding: 0px 0px 0px 0px;">
+ <div style="float: left; width: 50%; padding: 0px;"><div class="toolFormTitle">Source History Items</div><div class="toolFormBody">
%for data in source_datasets:
<%
checked = ""
if data.id in source_dataset_ids:
- checked = " checked"
+ checked = " checked='checked'"
%>
- <div class="form-row"><input type="checkbox" name="source_dataset_ids" value="${data.id}"${checked}/> ${data.hid}: ${data.name}</div>
+ <div class="form-row">
+ <input type="checkbox" name="source_dataset_ids" id="dataset_${data.id}" value="${data.id}"${checked}/>
+ <label for="dataset_${data.id}" style="display: inline;font-weight:normal;"> ${data.hid}: ${data.name}</label>
+ </div>
%endfor
</div></div>
- <div style="float: right; width: 50%; padding: 0px 0px 0px 0px;">
+ <div style="float: right; width: 50%; padding: 0px;"><div class="toolFormTitle">Target Histories</div><div class="toolFormBody">
%for i, hist in enumerate( target_histories ):
@@ -44,13 +51,16 @@
if hist == trans.get_history():
cur_history_text = " <strong>(current history)</strong>"
%>
- <div class="form-row"><input type="checkbox" name="target_history_ids" value="${hist.id}"${checked}/> ${i + 1}${cur_history_text}: ${hist.name}</div>
+ <div class="form-row">
+ <input type="checkbox" name="target_history_ids" id="hist_${hist.id}" value="${hist.id}"${checked}/>
+ <label for="hist_${hist.id}" style="display: inline;font-weight:normal;">${i + 1}: ${hist.name}${cur_history_text}</label>
+ </div>
%endfor
%if trans.get_user():
<%
checked = ""
if "create_new_history" in target_history_ids:
- checked = " checked"
+ checked = " checked='checked'"
%><br/><div class="form-row"><input type="checkbox" name="target_history_ids" value="create_new_history"${checked}/>New history named: <input type="textbox" name="new_history_name" value="${new_history_name}"/></div>
@@ -64,8 +74,3 @@
</form></div></p>
-<div style="clear: both"></div>
-<p>
- <div class="infomessage">Select any number of source history items and any number of target histories and click "Copy History Items" to add a copy of each selected history item to each selected target history.</div>
- <div style="clear: both"></div>
-</p>
--- a/lib/galaxy/web/controllers/dataset.py
+++ b/lib/galaxy/web/controllers/dataset.py
@@ -773,7 +773,7 @@ class DatasetInterface( BaseController,
trans.sa_session.refresh( history )
elif create_new_history:
target_history_ids.append( "create_new_history" )
- source_datasets = history.active_datasets
+ source_datasets = history.visible_datasets
target_histories = [history]
if user:
target_histories = user.active_histories
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -1033,7 +1033,9 @@ assign_mapper( context, ImplicitlyConver
assign_mapper( context, History, History.table,
properties=dict( galaxy_sessions=relation( GalaxySessionToHistoryAssociation ),
datasets=relation( HistoryDatasetAssociation, backref="history", order_by=asc(HistoryDatasetAssociation.table.c.hid) ),
- active_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & ( not_( HistoryDatasetAssociation.table.c.deleted ) ) ), order_by=asc( HistoryDatasetAssociation.table.c.hid ), viewonly=True ),
+ active_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & not_( HistoryDatasetAssociation.table.c.deleted ) ), order_by=asc( HistoryDatasetAssociation.table.c.hid ), viewonly=True ),
+ visible_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & not_( HistoryDatasetAssociation.table.c.deleted ) & HistoryDatasetAssociation.table.c.visible ),
+ order_by=asc( HistoryDatasetAssociation.table.c.hid ), viewonly=True ),
tags=relation( HistoryTagAssociation, order_by=HistoryTagAssociation.table.c.id, backref="histories" ),
annotations=relation( HistoryAnnotationAssociation, order_by=HistoryAnnotationAssociation.table.c.id, backref="histories" ),
ratings=relation( HistoryRatingAssociation, order_by=HistoryRatingAssociation.table.c.id, backref="histories" ) )
1
0
galaxy-dist commit 3868982a4eff: trackster: Fix error on saving when no chrom is currently viewed due to new saving of current viewport. Remove debug statements
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1289849956 18000
# Node ID 3868982a4eff5036f13650ab303e0b9a4fb30da8
# Parent 2bfb046649f059734e2709643785a95af3b85e81
trackster: Fix error on saving when no chrom is currently viewed due to new saving of current viewport. Remove debug statements
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -83,6 +83,7 @@ var Cache = function( num_elements ) {
var View = function( container, title, vis_id, dbkey, callback ) {
this.container = container;
+ this.chrom = null;
this.vis_id = vis_id;
this.dbkey = dbkey;
this.title = title;
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -201,8 +201,7 @@
});
}
- var payload = { 'tracks': tracks, 'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high } }
- console.log( payload );
+ var payload = { 'tracks': tracks, 'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high } };
$.ajax({
url: "${h.url_for( action='save' )}",
--- a/templates/tracks/new_browser.mako
+++ b/templates/tracks/new_browser.mako
@@ -18,12 +18,11 @@
<div style="clear: both;"></div></div><div class="form-row">
- Is your build not listed here?
+ Is the build not listed here?
<a href="${h.url_for( controller='user', action='dbkeys', panels=True )}">Add a Custom Build</a></div>
%if default_dbkey is not None:
<script type="text/javascript">
- console.log("${default_dbkey}");
$("#new-dbkey option[value='${default_dbkey}']").attr("selected", true);
</script>
%endif
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b,e){this.container=a;this.vis_id=c;this.dbkey=b;this.
title=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top
_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-a
utocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).append
To(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(f){if(f.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=f.chrom_info;var j='<option value="">Select Chrom/Contig</option>';for(var h=0,e=a.chrom_data.length;h<e;h++){var g=a.chrom_data[h].chrom;j+='<option value="'+g+'">'+g+"</option>"}a.chrom_select.html(j);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});if(d){d()}},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f){this.current_x=f.offsetX}).bind("drag",function(f){var h=f.offsetX-this.current_x;this.current_x=f.offsetX;var g=Math.round(h/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for
(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(f){this.original_low=a.low;this.current_height=f.clientY;this.current_x=f.offsetX;this.enable_pan=(f.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(h){if(!this.enable_pan||this.in_reordering){return}var f=$(this);var j=h.offsetX-this.current_x;var g=f.scrollTop()-(h.clientY-this.current_height);f.scrollTop(g);this.current_height=h.clientY;this.current_x=h.offsetX;var i=Math.round(j/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)});this.top_labeltrack.bind("dragstart",function(f){this.drag_origin_x=f.clientX;this.drag_origin_pos=f.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav
_labeltrack.height(),top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var g=Math.min(j.clientX,this.drag_origin_x)-a.container.offset().left,f=Math.max(j.clientX,this.drag_origin_x)-a.container.offset().left,i=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*i)+a.low,Math.round(f/h*i)+a.low);this.drag_div.css({left:g+"px",width:(f-g)+"px"})}).bind("dragend",function(k){var g=Math.min(k.clientX,this.drag_origin_x),f=Math.max(k.clientX,this.drag_origin_x),i=(a.high-a.low),h=a.viewport_container.width(),j=a.low;a.low=Math.round(g/h*i)+j;a.high=Math.round(f/h*i)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},upd
ate_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<
a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(
Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+th
is.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null}
;$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c
){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th cla
ss='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.r
emoveClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.conte
nt_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f=0,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which
)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filtering_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_div.width()+"_"+
o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(function(){if(obj_length(j)===0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height())
;b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div styl
e='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})
}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.data_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DA
TA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.pref
s.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+12+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Mat
h.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<label />").attr("for
",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></input>").attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_valu
e);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},fun
ction(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n
)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.length;u<a;u++){if(g+
u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.left_offset,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=$(q);if(I.datase
t_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.inc_slots[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);if(this.prefs.sho
w_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillStyle="red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] instanceof Array){var
E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al,S[5][0],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.tex
tAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an=0,g=h.length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillT
ext(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q},gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_block_color").va
l(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
+var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;th
is.dbkey=b;this.title=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").pr
ependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em"
).addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.r
edraw()}).appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(f){if(f.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=f.chrom_info;var j='<option value="">Select Chrom/Contig</option>';for(var h=0,e=a.chrom_data.length;h<e;h++){var g=a.chrom_data[h].chrom;j+='<option value="'+g+'">'+g+"</option>"}a.chrom_select.html(j);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});if(d){d()}},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f){this.current_x=f.offsetX}).bind("drag",function(f){var h=f.offsetX-this.current_x;this.current_x=f.offsetX;var g=Math.round(h/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click
",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(f){this.original_low=a.low;this.current_height=f.clientY;this.current_x=f.offsetX;this.enable_pan=(f.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(h){if(!this.enable_pan||this.in_reordering){return}var f=$(this);var j=h.offsetX-this.current_x;var g=f.scrollTop()-(h.clientY-this.current_height);f.scrollTop(g);this.current_height=h.clientY;this.current_x=h.offsetX;var i=Math.round(j/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)});this.top_labeltrack.bind("dragstart",function(f){this.drag_origin_x=f.clientX;this.drag_origin_pos=f.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+a.top_labeltrac
k.height()+a.nav_labeltrack.height(),top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var g=Math.min(j.clientX,this.drag_origin_x)-a.container.offset().left,f=Math.max(j.clientX,this.drag_origin_x)-a.container.offset().left,i=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*i)+a.low,Math.round(f/h*i)+a.low);this.drag_div.css({left:g+"px",width:(f-g)+"px"})}).bind("dragend",function(k){var g=Math.min(k.clientX,this.drag_origin_x),f=Math.max(k.clientX,this.drag_origin_x),i=(a.high-a.low),h=a.viewport_container.width(),j=a.low;a.low=Math.round(g/h*i)+j;a.high=Math.round(f/h*i)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigge
r("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a
.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.p
ow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.h
igh-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.sl
ider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=
function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);
var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a
.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("
nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f=0,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.
keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filtering_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_
div.width()+"_"+o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(function(){if(obj_length(j)===0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_he
ight,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(
),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){conso
le.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.data_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new
Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(r
ound_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+12+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.
get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<labe
l />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></input>").attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(thi
s.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,
mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),
e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.lengt
h;u<a;u++){if(g+u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.left_offset,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=
$(q);if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.inc_slots[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);i
f(this.prefs.show_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillStyle="red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] insta
nceof Array){var E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al,S[5][0],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O
).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an=0,g=h.length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlig
n="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q},gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_
block_color").val(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
1
0
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Anton Nekrutenko <anton(a)bx.psu.edu>
# Date 1289851601 18000
# Node ID 0505090dbbe610741cacd7a9a1c2e79b8cc9ea5c
# Parent 9a7482206be274678079271331171600a2023b03
Changing back
--- a/tools/taxonomy/t2ps_wrapper.py
+++ b/tools/taxonomy/t2ps_wrapper.py
@@ -59,7 +59,7 @@ except OSError, e:
# Convert PS to PDF
try:
- ps2pdf_cmd = 'pstopdf %s -o %s' % ( ps_file.name, pdf_file )
+ ps2pdf_cmd = 'ps2pdf %s %s' % ( ps_file.name, pdf_file )
retcode = subprocess.call( ps2pdf_cmd, shell=True )
if retcode < 0:
print >>sys.stderr, "Execution of ps2pdf terminated by signal", -retcode
1
0
galaxy-dist commit 33dacaafc62e: Change in output redirect. Should fix drawing phylogeny bug. Thanks Nate for pointing this out.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User anton(a)grusha.bx.psu.edu
# Date 1289920626 18000
# Node ID 33dacaafc62eac4a8940c4bc978da1d1a6c68af9
# Parent 94c2040e58255136741d776de8401cfb4128133b
Change in output redirect. Should fix drawing phylogeny bug. Thanks Nate for pointing this out.
--- a/tools/taxonomy/t2ps_wrapper.py
+++ b/tools/taxonomy/t2ps_wrapper.py
@@ -38,7 +38,7 @@ ps_file = tempfile.NamedTemporaryFile('w
# Execute taxonomy2tree
try:
- t2t_cmd = 'taxonomy2tree %s %s %s /dev/null 1 &> /dev/null' % ( tree_file, max_tree_level, newick_file.name )
+ t2t_cmd = 'taxonomy2tree %s %s %s /dev/null 1 > /dev/null 2>&1' % ( tree_file, max_tree_level, newick_file.name )
retcode = subprocess.call( t2t_cmd, shell=True )
if retcode < 0:
print >>sys.stderr, "Execution of taxonomy2tree terminated by signal", -retcode
1
0
galaxy-dist commit 2bfb046649f0: Cleaned up the remote file size method so that only the file size is stored.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289848701 18000
# Node ID 2bfb046649f059734e2709643785a95af3b85e81
# Parent 796201bc8dbc531ddaec5d75fadb88e858adfbc4
Cleaned up the remote file size method so that only the file size is stored.
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1864,20 +1864,21 @@ class Sample( object ):
untransferred_datasets.append( dataset )
return untransferred_datasets
def get_untransferred_dataset_size( self, filepath ):
- # TODO: RC: If rsh keys are not set, this method will return something like the following:
- # greg(a)scofield.bx.psu.edu's password: 46M /afs/bx.psu.edu/home/greg/chr22/chr21.fa
- # This method should return the number of bytes in the file. I believe du
- # displays the file system block usage which may not be the number of bytes in the file.
- # Would ls -l be better?
def print_ticks( d ):
pass
datatx_info = self.request.type.datatx_info
- cmd = 'ssh %s@%s "du -sh \'%s\'"' % ( datatx_info['username'], datatx_info['host'], filepath )
+ login_str = '%s@%s' % ( datatx_info['username'], datatx_info['host'] )
+ cmd = 'ssh %s "du -sh \'%s\'"' % ( login_str, filepath )
output = pexpect.run( cmd,
events={ '.ssword:*': datatx_info['password']+'\r\n',
pexpect.TIMEOUT:print_ticks},
timeout=10 )
- return output.replace( filepath, '' ).strip()
+ # cleanup the output to get just the file size
+ return output.replace( filepath, '' )\
+ .replace( 'Password:', '' )\
+ .replace( "'s password:", '' )\
+ .replace( login_str, '' )\
+ .strip()
def get_api_value( self, view='collection' ):
rval = {}
try:
1
0